Index: /code/branches/ode/ode-0.9/CHANGELOG.txt
===================================================================
--- /code/branches/ode/ode-0.9/CHANGELOG.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/CHANGELOG.txt	(revision 216)
@@ -0,0 +1,467 @@
+ODE CHANGELOG
+-------------
+
+the rules for this file:
+  * entries are sorted newest-first.
+  * summarize sets of changes - dont reproduce every CVS log comment here.
+  * don't ever delete anything.
+  * keep the format consistent (79 char width, M/D/Y date format).
+
+------------------------------------------------------------------------------
+
+11/03/06 david
+
+	* Integrated Christoph Beyer's average based sampling system for body
+	  disabling.
+
+10/26/06 Francisco Leon
+
+	* Totally refactored trimesh collision system.
+	  Using GIMPACT instead of OPCODE. Now works correctly, and faster.
+	  Visit http://gimpact.sourceforge.net.
+	  
+	* Finally, test_moving_trimesh.exe works nicely.   
+	  
+	* Fixed autodisable system. Now is possible to set bigger sleeping 
+	  threshold values and objects won't be sleeping on the air. They will
+	  rest on the floor properly.
+	  	  
+	* dInitODE function added.
+	
+	* Is Obligatory to call dInitODE() at the beginning for initialize ODE,
+	  and calling dCloseODE() when the program ends.
+
+09/20/06 bram
+
+	* Fixed two bugs in cyl/plane collision test.
+
+09/13/06 remi
+
+	* New Rotoide - Prismatic joint type
+	* dJointGetUniversalAngles for efficient angle retrieval.
+
+08/09/06 david
+
+	* Integrated plane2d joint type which constrains bodies to z == 0.
+
+07/06/06 david
+
+	* Added heightfield primitive collision code. Simple test available in
+	  ode/test/test_heightfield
+
+04/03/06 rodrigo
+
+	* Added Convex primitive collision code,
+	  currently only convex-sphere and convex-plane work
+
+04/01/06 bram
+
+	* Added program to test trimesh vs sphere: ode/test/test_basket
+
+03/20/06 jason379
+
+	* Added new autogenerated Visual Studio projects, with Premake scripts
+
+03/17/06 bram
+
+	* Added plane/cyl intersection test
+	* Renamed CCylinder to Capsule
+	
+02/04/06 gcarlton
+
+	* Added support for geom offsets.
+
+10/26/05 rodrigo
+
+	* Removed LIBTOOL from autotools since it was not really required.
+	* Added a target to build ODE as a shared library, this shared
+	  library gets build alongside the static one, no flags required.
+
+10/24/05 tfautre
+
+	(Backported patches from STABLE branch, applied by Adam)
+	
+	* dRandInt changed for a non-double all-int version.
+	* mics minor fixes and improvements.
+
+04/05/05 tfautre
+
+	* Fixed segmentation fault with OPCODE on 64 bits systems.
+
+03/31/05 tfautre
+
+	* Fixed timer.cpp compiler error on x86-64 using GCC.
+
+03/29/05 colin
+
+	* Added trimesh preprocessing to mark unneeded edges and verts.  Also
+	  added support for preprocessed info to the ccylinder-trimesh
+	  collider.
+
+12/07/04 adam
+
+        * Important AMotors bugfix
+
+09/22/04 jeff
+
+	* Assorted small bugfixes and tweaks for
+	  trimesh_{box,ccylinder,trimesh} collisions
+
+09/21/04 jeff
+
+	* added functions to joint.cpp to allow joint attachment to moving
+	  geoms.
+
+	* added malloc-based memory allocation in step.cpp & lcp.cpp (turned
+	  on with a #define switch in common.h)
+	
+05/29/04 russ
+
+	* added joint feedback to the QuickStep solver
+
+05/18/04 russ
+
+	* added warm starting to the QuickStep solver
+
+05/18/04 russ
+
+	* added the QuickStep solver
+	
+	* added contact parameter functions.
+
+05/05/04 adam
+
+        * use dRandInt instead of rand() in stepfast.
+
+04/21/04 russ
+
+	* added auto-disable support from Aras Pranckevicius (with
+	  modifications by russ). this useful feature can speed up
+	  simulation significantly in some cases.
+	
+	* various internal tidyups.
+
+04/20/04 russ
+
+	* changed the meaning of the 'index' argument to dJointGetBody():
+	  it was the only remaining API function that does not respect
+	  dJOINT_REVERSE (spotted by Matthew D. Hancher).
+	
+	* updated the C++ headers: fixed two minor bugs and added
+	  support for dQuadTreeSpace, dRay, and the dGeom::getSpace() method
+	  (from Matthew D. Hancher).
+
+04/18/04 russ
+
+	* changed the way that the dInfinity constant is implemented: now it
+	  is #defined to be one of: FLT_MAX, DBL_MAX, HUGE_VAL, HUGE_VALF, or
+	  a large numeric constant. previously it was a variable that was
+	  exported from the library. this simplifies the configuration and
+	  build process quite a bit, especially in the case of DLLs.
+	
+	* removed the old, deprecated collision system (geom.cpp,space.cpp,
+	  geom.h,space.h,odecpp_old_collision.h). the ODE_OLD_COLLISION
+	  configuration setting no longer has any meaning.
+	
+	* removed support for dGeomGroups, which have been deprecated for
+	  a while and are equivalent to 'spaces' anyway.
+
+04/13/04 russ
+
+	* bug fix in dMassSetCappedCylinder(), from Matthew D. Hancher.
+
+04/08/04 russ
+
+	* added trimesh-CCylinder capability, from Vadim Macagon
+	  <vadim_mcagon@hotmail.com>.
+
+04/04/04 adam
+
+        * yet another rewrite of triangle-box collision code, this
+        time based on code donated by Croteam, ported by asko@jetti.org
+        and tweaked by Erwin.
+
+04/04/04 adam
+
+        * merged trimesh-trimesh collision code by
+        Jeffrey Smith <jeffreys@Softimage.com>.
+
+        * changed it to not break the trimesh interface, fix
+        some GCC compilation problems, bring it up to date with
+        ODE changes from 2003-11-15 -> 2004-04-04.
+
+        * add ability to drop meshes on meshes in test_moving_trimesh,
+        not as good as it could be but it's illustrative.
+
+01/16/04 adam
+
+	* implement a bunch of ultra-simple TriMesh functions that were
+	in the headers but not in the code -- patch by
+	Vadim Macagon <vadim_mcagon@hotmail.com>
+
+	* disable temporal coherence on trimeshes by default, since
+	it has scaleability issues that don't make it a general clear win.
+
+12/01/03 adam
+
+	* implement dxHashSpace::collide2(), not particularly efficiently.
+
+11/14/03 adam
+
+	* applied several Trimesh fixes and improvements from
+	Aras Pranckevicius <nearaz@interamotion.com>
+
+10/22/03 adam
+
+	* apply Nguyen Binh's work for removing many dSetZero() calls
+	and some other extraneous initializations.
+
+07/29/03 martin
+
+	* added dJointAdd*Torque/Force().
+
+07/10/03 russ
+
+	* added the StepFast code, by David Whittaker.
+
+07/02/03 martin
+
+	* added dMassSet*Total().
+
+07/01/03 martin
+
+	* added joint limits and motors to universal joints.
+
+	* reversed the polarity of the dJOINT_REVERSE flag.
+
+06/30/03 russ
+
+	* added the TriMesh geom class and the quad tree space to the ODE
+	  core. both of these were developed by Erwin de Vries. added OPCODE
+	  to the ODE distribution, this is required by TriMesh.
+
+06/23/03 martin
+
+	* added dGeomSetQuaternion() and dGeomGetQuaternion()
+	
+	* added dJointGet*Anchor2()
+
+05/07/03 russ
+
+	* added dGeomGetSpace().
+
+02/05/03 russ
+
+	* added dMassSetCylinder().
+
+12/07/02 russ
+
+	* added dAreConnectedExcluding().
+
+11/30/02 russ
+
+	* added the ray geom class.
+
+	* added the dGeomXXXPointDepth() functions.
+
+	* added a collision test infrastructure, and some more tests.
+
+11/24/02 russ
+
+	* added support for multiple box-box contacts.
+
+11/10/02 russ
+
+	* added new collision system. select between the old/new system by
+	  setting the ODE_OLD_COLLISION variable in config/user-settings.
+
+10/28/02 russ
+
+	* fixed two problems in the LCP code to improve the reliability of
+	  the dContactApprox1 contact mode.
+
+	* added a FAQ question about rolling bodies getting stuck when they
+	  hit multiple geoms.
+
+09/08/02 russ
+
+	* added dClosestLineSegmentPoints().
+	* implemented dCollideCB().
+
+08/28/02 russ
+
+	* added dJointSetFeedback() and dJointGetFeedback().
+
+08/05/02 russ
+
+	* added dGeomTransformSetInfo() and dGeomTransformGetInfo().
+
+07/13/02 russ
+
+	* added dBodySetForce(), dBodySetTorque(), dWorldImpulseToForce(),
+	  dBodyGetPosRelPoint(), dBodyGetPosRelPoint(), dBodyVectorToWorld(),
+	  dBodyVectorFromWorld().
+
+	* added dBodyGetPointVel() (thanks to Colin Reed).
+
+	* added a new C++ interface (from Martin C. Martin, with modifications
+	  by russ). the old C++ interface is now in odecpp_old.h.
+
+06/25/02 russ
+
+	* added an additional BSD-style licensing option for ODE.
+
+06/23/02 russ
+
+	* added dCloseODE(), contributed by Nate Waddoups and David McClurg.
+
+05/16/02 russ
+
+	* added dSpaceQuery(), contributed by Nate Waddoups.
+
+04/07/02 russ
+
+	* added a section to the documentation for universal joints.
+	  this includes a picture of the joint.
+
+04/05/02 russ
+
+	* added a universal joint class (generously contributed by
+	  Martin C. Martin). it doesn't (yet) have a motor or joint limits,
+	  but it does come with tests.
+
+03/11/02 russ
+
+	* makefile changes to accomodate OSs with command line length
+	  limitations (thanks to Norman Lin).
+
+01/06/02 russ
+
+	* added the dBodySetGravityMode() and dBodyGetGravityMode()
+	  functions, which change the dxBodyNoGravity body flag.
+
+	* added support for building a DLL with MSVC - there is now a
+	  msvc-dll target. thanks to Norman Lin for doing this.
+
+12/28/01 russ
+
+	* added the dParamCFM joint parameter.
+
+12/24/01 russ
+
+	* reworked the build system to make it more cross-platform.
+	  there is now a single top-level makefile and a configurator.c
+	  program. see the INSTALL file for details.
+
+12/04/01 russ
+
+	* the "angular motor" joint has been completed, and a new section
+	  has been added to the documentation.
+
+11/26/01 russ
+
+	* added a new joint type: "angular motor". using this joint is a good
+	  way to get ball-joint motors and limits. this is work in progress -
+	  it has not been fully implemented or tested yet.
+
+11/22/01 russ
+
+	* replaced the mmap()-based joint group stack (stack.cpp) with a
+	  malloc()-based arena stack (obstack.cpp). this will be more
+	  portable and should not impact performance.
+
+11/12/01 russ
+
+	* changed the meaning of the 'flags' parameter to dCollide() and
+	  related functions: now the size of the contact buffer is kept in
+	  the lower 16 bits. this change will be backward compatible.
+
+	* added dBodyGetFiniteRotationMode() and dBodyGetFiniteRotationAxis().
+
+	* added dBodyAddForceAtRelPos() function.
+
+11/11/01 russ
+
+	* added the ability to manually enable and disable bodies.
+	  see dBodyEnable(), dBodyDisable(), dBodyIsEnabled().
+
+	* fixed a potential bug: when a world is destroyed that contains
+	  joints in joint groups, those joints are marked as "deactivated" in
+	  the joint group, so when the joint group is destroyed they can be
+	  ignored.
+
+	* the test_boxstack demo has new options to enable and disable bodies.
+
+	* new configuration parameter in config.h: dEFFICIENT_SIZE.
+
+11/11/01 russ
+
+	* started the change log for ODE. changes older than today were added
+	  to this file by inspecting the CVS logs.
+
+11/05/01 russ
+
+	* added REAL() constructions for floating point numbers, to prevent
+	  many warnings when compiling under VC++.
+
+11/03/01 russ
+
+	* added geometry transform class, documented composite objects.
+
+	* added collision rule: no contacts if both geoms on the same body.
+	  this is not the best rule, may have to remove this in the future.
+
+	* new dMassAdd() function.
+
+	* capped cylinder to capped cylinder collision function.
+
+10/31/01 russ
+
+	* increase CFM in some demos to make them more robust.
+
+10/29/01 russ
+
+	* added new accessor functions.
+
+10/19/01 russ
+
+	* added the dJOINT_TWOBODIES flag to the joint, that says it can not
+	  be attached to just one body.
+
+10/12/01 russ
+
+	* fixed a collision bug in dCollide() that was causing memory
+	  corruption when multiple contacts were being returned.
+
+10/11/01 russ
+
+	* joints can now return m=0 to be "inactive". added a "null" joint
+	  to test this.
+
+10/09/01 russ
+
+	* in the LCP solver, try to fail gracefully when s <= 0.
+
+	* dAABBTestFn() API change.
+
+10/08/01 russ
+
+	* fixed a contact swapping bug in dCollide().
+
+10/07/01 russ
+
+	* added capped cylinder geometry object.
+
+09/30/01 russ
+
+	* the test_buggy demo now uses geometry groups.
+
+	* added a dAABBTestFn field in the geometry classes.
+
+09/29/01 russ
+
+	* added geometry groups.
+
+09/20/01 russ
+
+	* added finite rotation stuff.
Index: /code/branches/ode/ode-0.9/GIMPACT/GIMPACT-LICENSE-BSD.TXT
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/GIMPACT-LICENSE-BSD.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/GIMPACT-LICENSE-BSD.TXT	(revision 216)
@@ -0,0 +1,29 @@
+GIMPACT : Geometric tools for VR.
+
+Copyright  (c) 2006 , Francisco León.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this list of
+      conditions and the following disclaimer.
+      
+    * Redistributions in binary form must reproduce the above copyright notice, this list 
+      of conditions and the following disclaimer in the documentation and/or other materials 
+      provided with the distribution.
+      
+    * Neither the name of the GIMPACT nor the names of its contributors may be used
+      to endorse or promote products derived from this software without specific prior
+      written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
+ DAMAGE.
Index: /code/branches/ode/ode-0.9/GIMPACT/GIMPACT-LICENSE-LGPL.TXT
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/GIMPACT-LICENSE-LGPL.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/GIMPACT-LICENSE-LGPL.TXT	(revision 216)
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_boxpruning.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_boxpruning.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_boxpruning.h	(revision 216)
@@ -0,0 +1,323 @@
+#ifndef GIM_BOXPRUNING_H_INCLUDED
+#define GIM_BOXPRUNING_H_INCLUDED
+
+/*! \file gim_boxpruning.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_radixsort.h"
+#include "GIMPACT/gim_geometry.h"
+
+/*! \defgroup BOX_PRUNNING
+
+\brief
+Tools for find overlapping objects on a scenary. These functions sort boxes for faster collisioin queries, using radix sort or quick sort as convenience. See \ref SORTING .
+<ul>
+<li> For using these collision routines, you must create a \ref GIM_AABB_SET by using this function : \ref gim_aabbset_alloc.
+<li> The  GIM_AABB_SET objects must be updated on their boxes on each query, and they must be update by calling \ref gim_aabbset_update
+<li> Before calling collision functions, you must create a pair set with \ref GIM_CREATE_PAIR_SET
+<li> For finding collision pairs on a scene (common space for objects), call \ref gim_aabbset_self_intersections
+<li> For finding collision pairs between two box sets , call \ref gim_aabbset_box_collision
+<li> After using collision routines, you must destroy the pairset with \ref GIM_DESTROY_PAIR_SET
+<li> When the box set is no longer used, you must destroy it by calling \ref gim_aabbset_destroy
+</ul>
+*/
+//! @{
+//! Overlapping pair
+struct GIM_PAIR
+{
+    GUINT m_index1;
+    GUINT m_index2;
+};
+//typedef struct _GIM_PAIR GIM_PAIR;
+
+//! Box container
+struct GIM_AABB_SET
+{
+    GUINT m_count;
+    aabb3f m_global_bound;//!< Global calculated bound of all boxes
+    aabb3f * m_boxes;
+    GUINT * m_maxcoords;//!<Upper corners of the boxes, in integer representation
+    GIM_RSORT_TOKEN * m_sorted_mincoords;//!< sorted min coords (lower corners), with their coord value as the m_key and m_value as the box index
+    char m_shared;//!< if m_shared == 0 then the memory is allocated and the set must be destroyed, else the pointers are shared and the set should't be destroyed
+};
+//typedef  struct _GIM_AABB_SET GIM_AABB_SET;
+
+//! Function for creating  an overlapping pair set
+#define GIM_CREATE_PAIR_SET(dynarray) GIM_DYNARRAY_CREATE(GIM_PAIR,dynarray,G_ARRAY_GROW_SIZE)
+//! Function for destroying an overlapping pair set
+#define GIM_DESTROY_PAIR_SET(dynarray) GIM_DYNARRAY_DESTROY(dynarray)
+
+//! Allocate memory for all aabb set.
+void gim_aabbset_alloc(GIM_AABB_SET * aabbset, GUINT count);
+
+//! Destroys the aabb set.
+void gim_aabbset_destroy(GIM_AABB_SET * aabbset);
+
+//! Calcs the global bound only
+/*!
+\pre aabbset must be allocated. And the boxes must be already set.
+*/
+void gim_aabbset_calc_global_bound(GIM_AABB_SET * aabbset);
+
+//! Sorts the boxes for box prunning.
+/*!
+1) find the integer representation of the aabb coords
+2) Sorts the min coords
+3) Calcs the global bound
+\pre aabbset must be allocated. And the boxes must be already set.
+\param aabbset
+\param calc_global_bound If 1 , calcs the global bound
+\post If aabbset->m_sorted_mincoords == 0, then it allocs the sorted coordinates
+*/
+void gim_aabbset_sort(GIM_AABB_SET * aabbset, char calc_global_bound);
+
+//! log(N) Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+/*!
+\pre aabbset must be allocated and sorted, the boxes must be already set.
+\param aabbset Must be sorted. Global bound isn't required
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_self_intersections_sorted(GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collision_pairs);
+
+//! NxN Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+/*!
+\pre aabbset must be allocated, the boxes must be already set.
+\param aabbset Global bound isn't required. Doen't need to be sorted.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_self_intersections_brute_force(GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collision_pairs);
+
+//! log(N) Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+/*!
+\pre aabbset1 and aabbset2 must be allocated and sorted, the boxes must be already set.
+\param aabbset1 Must be sorted, Global bound is required.
+\param aabbset2 Must be sorted, Global bound is required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_bipartite_intersections_sorted(GIM_AABB_SET * aabbset1, GIM_AABB_SET * aabbset2, GDYNAMIC_ARRAY * collision_pairs);
+
+//! NxM Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+/*!
+\pre aabbset1 and aabbset2 must be allocated and sorted, the boxes must be already set.
+\param aabbset1 Must be sorted, Global bound is required.
+\param aabbset2 Must be sorted, Global bound is required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_bipartite_intersections_brute_force(GIM_AABB_SET * aabbset1,GIM_AABB_SET * aabbset2, GDYNAMIC_ARRAY * collision_pairs);
+
+
+/*
+                Brute-Force Vs Sorted pruning
+Different approaches must be applied when colliding sets with different number of
+elements. When sets have less of 100 boxes, is often better to apply force brute
+approach instead of sorted methods, because at lowlevel bruteforce routines gives
+better perormance and consumes less resources, due of their simplicity.
+But when sets are larger, the complexiity of bruteforce increases exponencially.
+In the case of large sets, sorted approach is applied. So GIMPACT has the following
+strategies:
+
+On Sorting sets:
+!) When sets have more of 140 boxes, the boxes are sorted by its coded min coord
+and the global box is calculated. But when sets are smaller (less of 140 boxes),
+Is convenient to apply brute force approach.
+
+*******************************************************************************/
+
+//! Constant for apply approaches between brute force and sorted pruning on bipartite queries
+#define GIM_MIN_SORTED_BIPARTITE_PRUNING_BOXES 600
+//! Constant for apply approaches between brute force and sorted pruning for box collision
+#define GIM_MIN_SORTED_PRUNING_BOXES 140
+
+
+//Use these functions for general initialization
+
+//! Initalizes the set. Sort Boxes if needed.
+/*!
+\pre aabbset must be allocated. And the boxes must be already set.
+\post If the set has less of GIM_MIN_SORTED_BIPARTITE_PRUNING_BOXES boxes, only calcs the global box,
+ else it Sorts the entire set( Only applicable for large sets)
+*/
+void gim_aabbset_update(GIM_AABB_SET * aabbset);
+
+///Use these functions for general collision
+
+//! Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+/*!
+This function sorts the set and then it calls to gim_aabbset_self_intersections_brute_force or gim_aabbset_self_intersections_sorted. This is an example of how to use this function:
+\code
+//Create contact list
+GDYNAMIC_ARRAY collision_pairs;
+GIM_CREATE_PAIR_SET(collision_pairs);
+//Do collision
+gim_aabbset_self_intersections(&aabbset,&collision_pairs);
+if(collision_pairs.m_size==0)
+{
+    GIM_DYNARRAY_DESTROY(collision_pairs);//
+    return; //no collisioin
+}
+
+//pair pointer
+GIM_PAIR *pairs = GIM_DYNARRAY_POINTER(GIM_PAIR,collision_pairs);
+GUINT i, ti1,ti2;
+for (i=0;i<collision_pairs.m_size; i++)
+{
+    ti1 = pairs[i].m_index1;
+    ti2 = pairs[i].m_index2;
+    //Do something with the pairs
+    ....
+    ....
+    ...
+
+}
+//Terminate
+GIM_DYNARRAY_DESTROY(dummycontacts);
+GIM_DYNARRAY_DESTROY(collision_pairs);
+\endcode
+\param aabbset Set of boxes. Sorting isn't required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+\pre aabbset must be allocated and initialized.
+\post If aabbset->m_count >= GIM_MIN_SORTED_PRUNING_BOXES, then it calls to gim_aabbset_sort and then to gim_aabbset_self_intersections_sorted. Global box won't be calculated.
+*/
+void gim_aabbset_self_intersections(GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collision_pairs);
+
+//! Collides two sets. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+/*!
+\pre aabbset1 and aabbset2 must be allocated and updated. See gim_aabbset_update.
+\param aabbset1 Must be updated.
+\param aabbset2 Must be updated.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_bipartite_intersections(GIM_AABB_SET * aabbset1, GIM_AABB_SET * aabbset2, GDYNAMIC_ARRAY * collision_pairs);
+
+///Function for create Box collision result set
+
+#define GIM_CREATE_BOXQUERY_LIST(dynarray) GIM_DYNARRAY_CREATE(GUINT,dynarray,G_ARRAY_GROW_SIZE)
+
+//! Finds intersections between a box and a set. Return the colliding boxes of the set
+/*!
+\pre aabbset must be allocated and initialized.
+\param test_aabb Box for collision query
+\param aabbset Set of boxes .Global bound is required.
+\param collided Array of GUINT elements, indices of boxes. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_box_collision(aabb3f *test_aabb, GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collided);
+
+//! Finds intersections between a box and a set. Return the colliding boxes of the set
+/*!
+\pre aabbset must be allocated and initialized.
+\param vorigin Origin point of ray.
+\param vdir Direction vector of ray.
+\param tmax Max distance param for ray.
+\param aabbset Set of boxes .Global bound is required.
+\param collided Array of GUINT elements, indices of boxes. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_ray_collision(vec3f vorigin,vec3f vdir, GREAL tmax, GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collided);
+
+
+/*
+For sorting, each box corner must be discretized to a 32 bit integer.
+For this, we take the x and z coordinates from the box corner (a vector vec3f)
+Then convert the (x,z) pair to an integer. For convenience, we choose an error
+constant for converting the coordinates (0.05).
+*******************************************************************************/
+
+/**
+ For fitting the coordinate to an integer, we need to constraint the range of its values. So each coord component (x, z) must lie between 0 and 65536.
+ 20 give us a 0.05 floating point error
+*/
+#define ERROR_AABB 20.0f
+
+/**
+An error of 0.05 allows to make coordinates up to 1638.0f and no less of -1638.0f.
+So the maximum size of a room should be about 3276x3276 . Its dimensions must lie between  [-1638,1638.0f]
+*/
+#define MAX_AABB_SIZE 1638.0f
+
+//! Converts a vector coordinate to an integer for box sorting
+/*!
+\param vx X component
+\param vz Z component
+\param uint_key a GUINT
+*/
+#define GIM_CONVERT_VEC3F_GUINT_XZ(vx,vz,uint_key)\
+{\
+    GUINT _z = ((GUINT)(vz*ERROR_AABB))+32768;\
+    uint_key = ((GUINT)(vx*ERROR_AABB))+32768;\
+    uint_key = (uint_key<<16) + _z;\
+}\
+
+//! Converts a vector coordinate to an integer for box sorting,rounding to the upper int
+/*!
+\param vx X component
+\param vz Z component
+\param uint_key a GUINT
+*/
+#define GIM_CONVERT_VEC3F_GUINT_XZ_UPPER(vx,vz,uint_key)\
+{\
+    GUINT _z = ((GUINT)ceilf(vz*ERROR_AABB))+32768;\
+    uint_key = ((GUINT)ceilf(vx*ERROR_AABB))+32768;\
+    uint_key = (uint_key<<16) + _z;\
+}\
+
+
+//! Converts a vector coordinate to an integer for box sorting. Secure clamped
+/*!
+\param vx X component
+\param vz Z component
+\param uint_key a GUINT
+*/
+#define GIM_CONVERT_VEC3F_GUINT_XZ_CLAMPED(vx,vz,uint_key)\
+{\
+    GREAL _cx = CLAMP(vx,-MAX_AABB_SIZE,MAX_AABB_SIZE);\
+    GREAL _cz = CLAMP(vz,-MAX_AABB_SIZE,MAX_AABB_SIZE);\
+    GUINT _z = ((GUINT)(_cz*ERROR_AABB))+32768;\
+    uint_key = ((GUINT)(_cx*ERROR_AABB))+32768;\
+    uint_key = (uint_key<<16) + _z;\
+}\
+
+//! Converts a vector coordinate to an integer for box sorting. Secure clamped, rounded
+/*!
+\param vx X component
+\param vz Z component
+\param uint_key a GUINT
+*/
+#define GIM_CONVERT_VEC3F_GUINT_XZ_UPPER_CLAMPED(vx,vz,uint_key)\
+{\
+    GREAL _cx = CLAMP(vx,-MAX_AABB_SIZE,MAX_AABB_SIZE);\
+    GREAL _cz = CLAMP(vz,-MAX_AABB_SIZE,MAX_AABB_SIZE);\
+    GUINT _z = ((GUINT)ceilf(_cz*ERROR_AABB))+32768;\
+    uint_key = ((GUINT)ceilf(_cx*ERROR_AABB))+32768;\
+    uint_key = (uint_key<<16) + _z;\
+}\
+
+//! @}
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_contact.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_contact.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_contact.h	(revision 216)
@@ -0,0 +1,115 @@
+#ifndef GIM_CONTACT_H_INCLUDED
+#define GIM_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_geometry.h"
+#include "GIMPACT/gim_radixsort.h"
+
+/*! \defgroup CONTACTS
+\brief
+Functions for managing and sorting contacts resulting from a collision query.
+<ul>
+<li> Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
+<li> After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
+<li> Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
+</ul>
+
+*/
+//! @{
+/// Structure for collision results
+struct GIM_CONTACT
+{
+    vec3f m_point;
+    vec3f m_normal;
+    GREAL m_depth;//Positive value indicates interpenetration
+    void * m_handle1;
+    void * m_handle2;
+    GUINT m_feature1;//Face number
+    GUINT m_feature2;//Face number
+};
+//typedef struct _GIM_CONTACT GIM_CONTACT;
+
+#define CONTACT_DIFF_EPSILON 0.00001f
+
+#define GIM_CALC_KEY_CONTACT(pos,hash)\
+{\
+	GINT _coords[] = {(GINT)(pos[0]*1000.0f+1.0f),(GINT)(pos[1]*1333.0f),(GINT)(pos[2]*2133.0f+3.0f)};\
+	GUINT _hash=0;\
+	GUINT *_uitmp = (GUINT *)(&_coords[0]);\
+	_hash = *_uitmp;\
+	_uitmp++;\
+	_hash += (*_uitmp)<<4;\
+	_uitmp++;\
+	_hash += (*_uitmp)<<8;\
+	hash = _hash;\
+}\
+
+///Creates a contact list for queries
+#define GIM_CREATE_CONTACT_LIST(contact_array) GIM_DYNARRAY_CREATE(GIM_CONTACT,contact_array,100)
+
+#define GIM_PUSH_CONTACT(contact_array, point, normal, deep,handle1, handle2, feat1, feat2)\
+{\
+    GIM_DYNARRAY_PUSH_EMPTY(GIM_CONTACT,contact_array);\
+    GIM_CONTACT * _last = GIM_DYNARRAY_POINTER_LAST(GIM_CONTACT,contact_array);\
+    VEC_COPY(_last->m_point,point);\
+    VEC_COPY(_last->m_normal,normal);\
+    _last->m_depth = deep;\
+    _last->m_handle1 = handle1;\
+    _last->m_handle2 = handle2;\
+    _last->m_feature1 = feat1;\
+    _last->m_feature2 = feat2;\
+}\
+
+///Receive pointer to contacts
+#define GIM_COPY_CONTACTS(dest_contact, source_contact)\
+{\
+    VEC_COPY(dest_contact->m_point,source_contact->m_point);\
+    VEC_COPY(dest_contact->m_normal,source_contact->m_normal);\
+    dest_contact->m_depth = source_contact->m_depth;\
+    dest_contact->m_handle1 = source_contact->m_handle1;\
+    dest_contact->m_handle2 = source_contact->m_handle2;\
+    dest_contact->m_feature1 = source_contact->m_feature1;\
+    dest_contact->m_feature2 = source_contact->m_feature2;\
+}\
+
+//! Merges duplicate contacts with minimum depth criterion
+void gim_merge_contacts(GDYNAMIC_ARRAY * source_contacts,
+					GDYNAMIC_ARRAY * dest_contacts);
+
+
+//! Merges to an unique contact
+void gim_merge_contacts_unique(GDYNAMIC_ARRAY * source_contacts,
+					GDYNAMIC_ARRAY * dest_contacts);
+
+//! @}
+#endif // GIM_CONTACT_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_geometry.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_geometry.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_geometry.h	(revision 216)
@@ -0,0 +1,1872 @@
+#ifndef GIM_VECTOR_H_INCLUDED
+#define GIM_VECTOR_H_INCLUDED
+
+/*! \file gim_geometry.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_math.h"
+
+/*! \defgroup GEOMETRIC_TYPES
+\brief
+Basic types and constants for geometry
+*/
+//! @{
+
+//! Integer vector 2D
+typedef GINT vec2i[2];
+//! Integer vector 3D
+typedef GINT vec3i[3];
+//! Integer vector 4D
+typedef GINT vec4i[4];
+
+//! Float vector 2D
+typedef GREAL vec2f[2];
+//! Float vector 3D
+typedef GREAL vec3f[3];
+//! Float vector 4D
+typedef GREAL vec4f[4];
+
+//! Matrix 2D, row ordered
+typedef GREAL mat2f[2][2];
+//! Matrix 3D, row ordered
+typedef GREAL mat3f[3][3];
+//! Matrix 4D, row ordered
+typedef GREAL mat4f[4][4];
+
+//! Quaternion
+typedef GREAL quatf[4];
+
+//! Axis aligned box
+struct aabb3f{
+    GREAL minX;
+    GREAL maxX;
+    GREAL minY;
+    GREAL maxY;
+    GREAL minZ;
+    GREAL maxZ;
+};
+//typedef struct _aabb3f aabb3f;
+//! @}
+
+
+/*! \defgroup VECTOR_OPERATIONS
+Operations for vectors : vec2f,vec3f and vec4f
+*/
+//! @{
+
+//! Zero out a 2D vector
+#define VEC_ZERO_2(a)				\
+{						\
+   (a)[0] = (a)[1] = 0.0f;			\
+}\
+
+
+//! Zero out a 3D vector
+#define VEC_ZERO(a)				\
+{						\
+   (a)[0] = (a)[1] = (a)[2] = 0.0f;		\
+}\
+
+
+/// Zero out a 4D vector
+#define VEC_ZERO_4(a)				\
+{						\
+   (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f;	\
+}\
+
+
+/// Vector copy
+#define VEC_COPY_2(b,a)				\
+{						\
+   (b)[0] = (a)[0];				\
+   (b)[1] = (a)[1];				\
+}\
+
+
+/// Copy 3D vector
+#define VEC_COPY(b,a)				\
+{						\
+   (b)[0] = (a)[0];				\
+   (b)[1] = (a)[1];				\
+   (b)[2] = (a)[2];				\
+}\
+
+
+/// Copy 4D vector
+#define VEC_COPY_4(b,a)				\
+{						\
+   (b)[0] = (a)[0];				\
+   (b)[1] = (a)[1];				\
+   (b)[2] = (a)[2];				\
+   (b)[3] = (a)[3];				\
+}\
+
+
+/// Vector difference
+#define VEC_DIFF_2(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] - (v1)[0];		\
+   (v21)[1] = (v2)[1] - (v1)[1];		\
+}\
+
+
+/// Vector difference
+#define VEC_DIFF(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] - (v1)[0];		\
+   (v21)[1] = (v2)[1] - (v1)[1];		\
+   (v21)[2] = (v2)[2] - (v1)[2];		\
+}\
+
+
+/// Vector difference
+#define VEC_DIFF_4(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] - (v1)[0];		\
+   (v21)[1] = (v2)[1] - (v1)[1];		\
+   (v21)[2] = (v2)[2] - (v1)[2];		\
+   (v21)[3] = (v2)[3] - (v1)[3];		\
+}\
+
+
+/// Vector sum
+#define VEC_SUM_2(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] + (v1)[0];		\
+   (v21)[1] = (v2)[1] + (v1)[1];		\
+}\
+
+
+/// Vector sum
+#define VEC_SUM(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] + (v1)[0];		\
+   (v21)[1] = (v2)[1] + (v1)[1];		\
+   (v21)[2] = (v2)[2] + (v1)[2];		\
+}\
+
+
+/// Vector sum
+#define VEC_SUM_4(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] + (v1)[0];		\
+   (v21)[1] = (v2)[1] + (v1)[1];		\
+   (v21)[2] = (v2)[2] + (v1)[2];		\
+   (v21)[3] = (v2)[3] + (v1)[3];		\
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE_2(c,a,b)			\
+{						\
+   (c)[0] = (a)*(b)[0];				\
+   (c)[1] = (a)*(b)[1];				\
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE(c,a,b)			\
+{						\
+   (c)[0] = (a)*(b)[0];				\
+   (c)[1] = (a)*(b)[1];				\
+   (c)[2] = (a)*(b)[2];				\
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE_4(c,a,b)			\
+{						\
+   (c)[0] = (a)*(b)[0];				\
+   (c)[1] = (a)*(b)[1];				\
+   (c)[2] = (a)*(b)[2];				\
+   (c)[3] = (a)*(b)[3];				\
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM_2(c,a,b)			\
+{						\
+   (c)[0] += (a)*(b)[0];			\
+   (c)[1] += (a)*(b)[1];			\
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM(c,a,b)			\
+{						\
+   (c)[0] += (a)*(b)[0];			\
+   (c)[1] += (a)*(b)[1];			\
+   (c)[2] += (a)*(b)[2];			\
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM_4(c,a,b)			\
+{						\
+   (c)[0] += (a)*(b)[0];			\
+   (c)[1] += (a)*(b)[1];			\
+   (c)[2] += (a)*(b)[2];			\
+   (c)[3] += (a)*(b)[3];			\
+}\
+
+
+/// Vector dot product
+#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1])
+
+
+/// Vector dot product
+#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2])
+
+/// Vector dot product
+#define VEC_DOT_4(a,b)	((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
+
+/// vector impact parameter (squared)
+#define VEC_IMPACT_SQ(bsq,direction,position) {\
+   GREAL _llel_ = VEC_DOT(direction, position);\
+   bsq = VEC_DOT(position, position) - _llel_*_llel_;\
+}\
+
+
+/// vector impact parameter
+#define VEC_IMPACT(bsq,direction,position)	{\
+   VEC_IMPACT_SQ(bsq,direction,position);		\
+   GIM_SQRT(bsq,bsq);					\
+}\
+
+/// Vector length
+#define VEC_LENGTH_2(a,l)\
+{\
+    GREAL _pp = VEC_DOT_2(a,a);\
+    GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_LENGTH(a,l)\
+{\
+    GREAL _pp = VEC_DOT(a,a);\
+    GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_LENGTH_4(a,l)\
+{\
+    GREAL _pp = VEC_DOT_4(a,a);\
+    GIM_SQRT(_pp,l);\
+}\
+
+/// Vector inv length
+#define VEC_INV_LENGTH_2(a,l)\
+{\
+    GREAL _pp = VEC_DOT_2(a,a);\
+    GIM_INV_SQRT(_pp,l);\
+}\
+
+
+/// Vector inv length
+#define VEC_INV_LENGTH(a,l)\
+{\
+    GREAL _pp = VEC_DOT(a,a);\
+    GIM_INV_SQRT(_pp,l);\
+}\
+
+
+/// Vector inv length
+#define VEC_INV_LENGTH_4(a,l)\
+{\
+    GREAL _pp = VEC_DOT_4(a,a);\
+    GIM_INV_SQRT(_pp,l);\
+}\
+
+
+
+/// distance between two points
+#define VEC_DISTANCE(_len,_va,_vb) {\
+    vec3f _tmp_;				\
+    VEC_DIFF(_tmp_, _vb, _va);			\
+    VEC_LENGTH(_tmp_,_len);			\
+}\
+
+
+/// Vector length
+#define VEC_CONJUGATE_LENGTH(a,l)\
+{\
+    GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\
+    GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_NORMALIZE(a) {	\
+    GREAL len;\
+    VEC_INV_LENGTH(a,len); \
+    if(len<G_REAL_INFINITY)\
+    {\
+        a[0] *= len;				\
+        a[1] *= len;				\
+        a[2] *= len;				\
+    }						\
+}\
+
+/// Set Vector size
+#define VEC_RENORMALIZE(a,newlen) {	\
+    GREAL len;\
+    VEC_INV_LENGTH(a,len); \
+    if(len<G_REAL_INFINITY)\
+    {\
+        len *= newlen;\
+        a[0] *= len;				\
+        a[1] *= len;				\
+        a[2] *= len;				\
+    }						\
+}\
+
+/// Vector cross
+#define VEC_CROSS(c,a,b)		\
+{						\
+   c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1];	\
+   c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2];	\
+   c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0];	\
+}\
+
+
+/*! Vector perp -- assumes that n is of unit length
+ * accepts vector v, subtracts out any component parallel to n */
+#define VEC_PERPENDICULAR(vp,v,n)			\
+{						\
+   GREAL dot = VEC_DOT(v, n);			\
+   vp[0] = (v)[0] - dot*(n)[0];		\
+   vp[1] = (v)[1] - dot*(n)[1];		\
+   vp[2] = (v)[2] - dot*(n)[2];		\
+}\
+
+
+/*! Vector parallel -- assumes that n is of unit length */
+#define VEC_PARALLEL(vp,v,n)			\
+{						\
+   GREAL dot = VEC_DOT(v, n);			\
+   vp[0] = (dot) * (n)[0];			\
+   vp[1] = (dot) * (n)[1];			\
+   vp[2] = (dot) * (n)[2];			\
+}\
+
+/*! Same as Vector parallel --  n can have any length
+ * accepts vector v, subtracts out any component perpendicular to n */
+#define VEC_PROJECT(vp,v,n)			\
+{ \
+	GREAL scalar = VEC_DOT(v, n);			\
+	scalar/= VEC_DOT(n, n); \
+	vp[0] = (scalar) * (n)[0];			\
+    vp[1] = (scalar) * (n)[1];			\
+    vp[2] = (scalar) * (n)[2];			\
+}\
+
+
+/*! accepts vector v*/
+#define VEC_UNPROJECT(vp,v,n)			\
+{ \
+	GREAL scalar = VEC_DOT(v, n);			\
+	scalar = VEC_DOT(n, n)/scalar; \
+	vp[0] = (scalar) * (n)[0];			\
+    vp[1] = (scalar) * (n)[1];			\
+    vp[2] = (scalar) * (n)[2];			\
+}\
+
+
+/*! Vector reflection -- assumes n is of unit length
+ Takes vector v, reflects it against reflector n, and returns vr */
+#define VEC_REFLECT(vr,v,n)			\
+{						\
+   GREAL dot = VEC_DOT(v, n);			\
+   vr[0] = (v)[0] - 2.0 * (dot) * (n)[0];	\
+   vr[1] = (v)[1] - 2.0 * (dot) * (n)[1];	\
+   vr[2] = (v)[2] - 2.0 * (dot) * (n)[2];	\
+}\
+
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with two scalars */
+#define VEC_BLEND_AB(vr,sa,a,sb,b)			\
+{						\
+   vr[0] = (sa) * (a)[0] + (sb) * (b)[0];	\
+   vr[1] = (sa) * (a)[1] + (sb) * (b)[1];	\
+   vr[2] = (sa) * (a)[2] + (sb) * (b)[2];	\
+}\
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with s <=1 */
+#define VEC_BLEND(vr,a,b,s)	VEC_BLEND_AB(vr,1-s,a,sb,s)
+
+#define VEC_SET3(a,b,op,c) a[0]=b[0] op c[0]; a[1]=b[1] op c[1]; a[2]=b[2] op c[2];
+//! @}
+
+
+/*! \defgroup MATRIX_OPERATIONS
+Operations for matrices : mat2f, mat3f and mat4f
+*/
+//! @{
+
+/// initialize matrix
+#define IDENTIFY_MATRIX_3X3(m)			\
+{						\
+   m[0][0] = 1.0;				\
+   m[0][1] = 0.0;				\
+   m[0][2] = 0.0;				\
+						\
+   m[1][0] = 0.0;				\
+   m[1][1] = 1.0;				\
+   m[1][2] = 0.0;				\
+						\
+   m[2][0] = 0.0;				\
+   m[2][1] = 0.0;				\
+   m[2][2] = 1.0;				\
+}\
+
+/*! initialize matrix */
+#define IDENTIFY_MATRIX_4X4(m)			\
+{						\
+   m[0][0] = 1.0;				\
+   m[0][1] = 0.0;				\
+   m[0][2] = 0.0;				\
+   m[0][3] = 0.0;				\
+						\
+   m[1][0] = 0.0;				\
+   m[1][1] = 1.0;				\
+   m[1][2] = 0.0;				\
+   m[1][3] = 0.0;				\
+						\
+   m[2][0] = 0.0;				\
+   m[2][1] = 0.0;				\
+   m[2][2] = 1.0;				\
+   m[2][3] = 0.0;				\
+						\
+   m[3][0] = 0.0;				\
+   m[3][1] = 0.0;				\
+   m[3][2] = 0.0;				\
+   m[3][3] = 1.0;				\
+}\
+
+/*! initialize matrix */
+#define ZERO_MATRIX_4X4(m)			\
+{						\
+   m[0][0] = 0.0;				\
+   m[0][1] = 0.0;				\
+   m[0][2] = 0.0;				\
+   m[0][3] = 0.0;				\
+						\
+   m[1][0] = 0.0;				\
+   m[1][1] = 0.0;				\
+   m[1][2] = 0.0;				\
+   m[1][3] = 0.0;				\
+						\
+   m[2][0] = 0.0;				\
+   m[2][1] = 0.0;				\
+   m[2][2] = 0.0;				\
+   m[2][3] = 0.0;				\
+						\
+   m[3][0] = 0.0;				\
+   m[3][1] = 0.0;				\
+   m[3][2] = 0.0;				\
+   m[3][3] = 0.0;				\
+}\
+
+/*! matrix rotation  X */
+#define ROTX_CS(m,cosine,sine)		\
+{					\
+   /* rotation about the x-axis */	\
+					\
+   m[0][0] = 1.0;			\
+   m[0][1] = 0.0;			\
+   m[0][2] = 0.0;			\
+   m[0][3] = 0.0;			\
+					\
+   m[1][0] = 0.0;			\
+   m[1][1] = (cosine);			\
+   m[1][2] = (sine);			\
+   m[1][3] = 0.0;			\
+					\
+   m[2][0] = 0.0;			\
+   m[2][1] = -(sine);			\
+   m[2][2] = (cosine);			\
+   m[2][3] = 0.0;			\
+					\
+   m[3][0] = 0.0;			\
+   m[3][1] = 0.0;			\
+   m[3][2] = 0.0;			\
+   m[3][3] = 1.0;			\
+}\
+
+/*! matrix rotation  Y */
+#define ROTY_CS(m,cosine,sine)		\
+{					\
+   /* rotation about the y-axis */	\
+					\
+   m[0][0] = (cosine);			\
+   m[0][1] = 0.0;			\
+   m[0][2] = -(sine);			\
+   m[0][3] = 0.0;			\
+					\
+   m[1][0] = 0.0;			\
+   m[1][1] = 1.0;			\
+   m[1][2] = 0.0;			\
+   m[1][3] = 0.0;			\
+					\
+   m[2][0] = (sine);			\
+   m[2][1] = 0.0;			\
+   m[2][2] = (cosine);			\
+   m[2][3] = 0.0;			\
+					\
+   m[3][0] = 0.0;			\
+   m[3][1] = 0.0;			\
+   m[3][2] = 0.0;			\
+   m[3][3] = 1.0;			\
+}\
+
+/*! matrix rotation  Z */
+#define ROTZ_CS(m,cosine,sine)		\
+{					\
+   /* rotation about the z-axis */	\
+					\
+   m[0][0] = (cosine);			\
+   m[0][1] = (sine);			\
+   m[0][2] = 0.0;			\
+   m[0][3] = 0.0;			\
+					\
+   m[1][0] = -(sine);			\
+   m[1][1] = (cosine);			\
+   m[1][2] = 0.0;			\
+   m[1][3] = 0.0;			\
+					\
+   m[2][0] = 0.0;			\
+   m[2][1] = 0.0;			\
+   m[2][2] = 1.0;			\
+   m[2][3] = 0.0;			\
+					\
+   m[3][0] = 0.0;			\
+   m[3][1] = 0.0;			\
+   m[3][2] = 0.0;			\
+   m[3][3] = 1.0;			\
+}\
+
+/*! matrix copy */
+#define COPY_MATRIX_2X2(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+				\
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_2X3(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+   b[0][2] = a[0][2];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[1][2];		\
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_3X3(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+   b[0][2] = a[0][2];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[1][2];		\
+				\
+   b[2][0] = a[2][0];		\
+   b[2][1] = a[2][1];		\
+   b[2][2] = a[2][2];		\
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_4X4(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+   b[0][2] = a[0][2];		\
+   b[0][3] = a[0][3];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[1][2];		\
+   b[1][3] = a[1][3];		\
+				\
+   b[2][0] = a[2][0];		\
+   b[2][1] = a[2][1];		\
+   b[2][2] = a[2][2];		\
+   b[2][3] = a[2][3];		\
+				\
+   b[3][0] = a[3][0];		\
+   b[3][1] = a[3][1];		\
+   b[3][2] = a[3][2];		\
+   b[3][3] = a[3][3];		\
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_2X2(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[1][0];		\
+				\
+   b[1][0] = a[0][1];		\
+   b[1][1] = a[1][1];		\
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_3X3(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[1][0];		\
+   b[0][2] = a[2][0];		\
+				\
+   b[1][0] = a[0][1];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[2][1];		\
+				\
+   b[2][0] = a[0][2];		\
+   b[2][1] = a[1][2];		\
+   b[2][2] = a[2][2];		\
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_4X4(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[1][0];		\
+   b[0][2] = a[2][0];		\
+   b[0][3] = a[3][0];		\
+				\
+   b[1][0] = a[0][1];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[2][1];		\
+   b[1][3] = a[3][1];		\
+				\
+   b[2][0] = a[0][2];		\
+   b[2][1] = a[1][2];		\
+   b[2][2] = a[2][2];		\
+   b[2][3] = a[3][2];		\
+				\
+   b[3][0] = a[0][3];		\
+   b[3][1] = a[1][3];		\
+   b[3][2] = a[2][3];		\
+   b[3][3] = a[3][3];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_2X2(b,s,a)		\
+{					\
+   b[0][0] = (s) * a[0][0];		\
+   b[0][1] = (s) * a[0][1];		\
+					\
+   b[1][0] = (s) * a[1][0];		\
+   b[1][1] = (s) * a[1][1];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_3X3(b,s,a)		\
+{					\
+   b[0][0] = (s) * a[0][0];		\
+   b[0][1] = (s) * a[0][1];		\
+   b[0][2] = (s) * a[0][2];		\
+					\
+   b[1][0] = (s) * a[1][0];		\
+   b[1][1] = (s) * a[1][1];		\
+   b[1][2] = (s) * a[1][2];		\
+					\
+   b[2][0] = (s) * a[2][0];		\
+   b[2][1] = (s) * a[2][1];		\
+   b[2][2] = (s) * a[2][2];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_4X4(b,s,a)		\
+{					\
+   b[0][0] = (s) * a[0][0];		\
+   b[0][1] = (s) * a[0][1];		\
+   b[0][2] = (s) * a[0][2];		\
+   b[0][3] = (s) * a[0][3];		\
+					\
+   b[1][0] = (s) * a[1][0];		\
+   b[1][1] = (s) * a[1][1];		\
+   b[1][2] = (s) * a[1][2];		\
+   b[1][3] = (s) * a[1][3];		\
+					\
+   b[2][0] = (s) * a[2][0];		\
+   b[2][1] = (s) * a[2][1];		\
+   b[2][2] = (s) * a[2][2];		\
+   b[2][3] = (s) * a[2][3];		\
+					\
+   b[3][0] = s * a[3][0];		\
+   b[3][1] = s * a[3][1];		\
+   b[3][2] = s * a[3][2];		\
+   b[3][3] = s * a[3][3];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_2X2(b,s,a)		\
+{					\
+   b[0][0] += (s) * a[0][0];		\
+   b[0][1] += (s) * a[0][1];		\
+					\
+   b[1][0] += (s) * a[1][0];		\
+   b[1][1] += (s) * a[1][1];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_3X3(b,s,a)		\
+{					\
+   b[0][0] += (s) * a[0][0];		\
+   b[0][1] += (s) * a[0][1];		\
+   b[0][2] += (s) * a[0][2];		\
+					\
+   b[1][0] += (s) * a[1][0];		\
+   b[1][1] += (s) * a[1][1];		\
+   b[1][2] += (s) * a[1][2];		\
+					\
+   b[2][0] += (s) * a[2][0];		\
+   b[2][1] += (s) * a[2][1];		\
+   b[2][2] += (s) * a[2][2];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_4X4(b,s,a)		\
+{					\
+   b[0][0] += (s) * a[0][0];		\
+   b[0][1] += (s) * a[0][1];		\
+   b[0][2] += (s) * a[0][2];		\
+   b[0][3] += (s) * a[0][3];		\
+					\
+   b[1][0] += (s) * a[1][0];		\
+   b[1][1] += (s) * a[1][1];		\
+   b[1][2] += (s) * a[1][2];		\
+   b[1][3] += (s) * a[1][3];		\
+					\
+   b[2][0] += (s) * a[2][0];		\
+   b[2][1] += (s) * a[2][1];		\
+   b[2][2] += (s) * a[2][2];		\
+   b[2][3] += (s) * a[2][3];		\
+					\
+   b[3][0] += (s) * a[3][0];		\
+   b[3][1] += (s) * a[3][1];		\
+   b[3][2] += (s) * a[3][2];		\
+   b[3][3] += (s) * a[3][3];		\
+}\
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_2X2(c,a,b)		\
+{						\
+   c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0];	\
+   c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1];	\
+						\
+   c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0];	\
+   c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1];	\
+						\
+}\
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_3X3(c,a,b)				\
+{								\
+   c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0];	\
+   c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1];	\
+   c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2];	\
+								\
+   c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0];	\
+   c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1];	\
+   c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2];	\
+								\
+   c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0];	\
+   c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1];	\
+   c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2];	\
+}\
+
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_4X4(c,a,b)		\
+{						\
+   c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\
+   c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\
+   c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\
+   c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\
+						\
+   c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\
+   c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\
+   c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\
+   c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\
+						\
+   c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\
+   c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\
+   c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\
+   c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\
+						\
+   c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\
+   c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\
+   c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\
+   c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\
+}\
+
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_2X2(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1];				\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1];				\
+}\
+
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_3X3(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];		\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];		\
+   p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];		\
+}\
+
+
+/*! matrix times vector
+v is a vec4f
+*/
+#define MAT_DOT_VEC_4X4(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3];	\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3];	\
+   p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3];	\
+   p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3];	\
+}\
+
+/*! matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+Last column is added as the position
+*/
+#define MAT_DOT_VEC_3X4(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3];	\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3];	\
+   p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3];	\
+}\
+
+/*! vector transpose times matrix */
+/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */
+#define VEC_DOT_MAT_3X3(p,v,m)					\
+{								\
+   p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0];		\
+   p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1];		\
+   p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2];		\
+}\
+
+
+/*! affine matrix times vector */
+/** The matrix is assumed to be an affine matrix, with last two
+ * entries representing a translation */
+#define MAT_DOT_VEC_2X3(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2];		\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2];		\
+}\
+
+
+/** inverse transpose of matrix times vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ *
+ * DANGER !!! Do Not use this on normal vectors!!!
+ * It will leave normals the wrong length !!!
+ * See macro below for use on normals.
+ */
+#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v)			\
+{								\
+   GREAL det;						\
+								\
+   det = m[0][0]*m[1][1] - m[0][1]*m[1][0];			\
+   p[0] = m[1][1]*v[0] - m[1][0]*v[1];				\
+   p[1] = - m[0][1]*v[0] + m[0][0]*v[1];			\
+								\
+   /* if matrix not singular, and not orthonormal, then renormalize */ \
+   if ((det!=1.0f) && (det != 0.0f)) {				\
+      det = 1.0f / det;						\
+      p[0] *= det;						\
+      p[1] *= det;						\
+   }								\
+}\
+
+
+/** transform normal vector by inverse transpose of matrix
+ * and then renormalize the vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ * Vector p is then normalized.
+ */
+#define NORM_XFORM_2X2(p,m,v)					\
+{								\
+   double len;							\
+								\
+   /* do nothing if off-diagonals are zero and diagonals are 	\
+    * equal */							\
+   if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \
+      p[0] = m[1][1]*v[0] - m[1][0]*v[1];			\
+      p[1] = - m[0][1]*v[0] + m[0][0]*v[1];			\
+								\
+      len = p[0]*p[0] + p[1]*p[1];				\
+      GIM_INV_SQRT(len,len);					\
+      p[0] *= len;						\
+      p[1] *= len;						\
+   } else {							\
+      VEC_COPY_2 (p, v);					\
+   }								\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_2X2(m,v,t)				\
+{								\
+   m[0][0] = v[0] * t[0];					\
+   m[0][1] = v[0] * t[1];					\
+								\
+   m[1][0] = v[1] * t[0];					\
+   m[1][1] = v[1] * t[1];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_3X3(m,v,t)				\
+{								\
+   m[0][0] = v[0] * t[0];					\
+   m[0][1] = v[0] * t[1];					\
+   m[0][2] = v[0] * t[2];					\
+								\
+   m[1][0] = v[1] * t[0];					\
+   m[1][1] = v[1] * t[1];					\
+   m[1][2] = v[1] * t[2];					\
+								\
+   m[2][0] = v[2] * t[0];					\
+   m[2][1] = v[2] * t[1];					\
+   m[2][2] = v[2] * t[2];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_4X4(m,v,t)				\
+{								\
+   m[0][0] = v[0] * t[0];					\
+   m[0][1] = v[0] * t[1];					\
+   m[0][2] = v[0] * t[2];					\
+   m[0][3] = v[0] * t[3];					\
+								\
+   m[1][0] = v[1] * t[0];					\
+   m[1][1] = v[1] * t[1];					\
+   m[1][2] = v[1] * t[2];					\
+   m[1][3] = v[1] * t[3];					\
+								\
+   m[2][0] = v[2] * t[0];					\
+   m[2][1] = v[2] * t[1];					\
+   m[2][2] = v[2] * t[2];					\
+   m[2][3] = v[2] * t[3];					\
+								\
+   m[3][0] = v[3] * t[0];					\
+   m[3][1] = v[3] * t[1];					\
+   m[3][2] = v[3] * t[2];					\
+   m[3][3] = v[3] * t[3];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_2X2(m,v,t)				\
+{								\
+   m[0][0] += v[0] * t[0];					\
+   m[0][1] += v[0] * t[1];					\
+								\
+   m[1][0] += v[1] * t[0];					\
+   m[1][1] += v[1] * t[1];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_3X3(m,v,t)				\
+{								\
+   m[0][0] += v[0] * t[0];					\
+   m[0][1] += v[0] * t[1];					\
+   m[0][2] += v[0] * t[2];					\
+								\
+   m[1][0] += v[1] * t[0];					\
+   m[1][1] += v[1] * t[1];					\
+   m[1][2] += v[1] * t[2];					\
+								\
+   m[2][0] += v[2] * t[0];					\
+   m[2][1] += v[2] * t[1];					\
+   m[2][2] += v[2] * t[2];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_4X4(m,v,t)				\
+{								\
+   m[0][0] += v[0] * t[0];					\
+   m[0][1] += v[0] * t[1];					\
+   m[0][2] += v[0] * t[2];					\
+   m[0][3] += v[0] * t[3];					\
+								\
+   m[1][0] += v[1] * t[0];					\
+   m[1][1] += v[1] * t[1];					\
+   m[1][2] += v[1] * t[2];					\
+   m[1][3] += v[1] * t[3];					\
+								\
+   m[2][0] += v[2] * t[0];					\
+   m[2][1] += v[2] * t[1];					\
+   m[2][2] += v[2] * t[2];					\
+   m[2][3] += v[2] * t[3];					\
+								\
+   m[3][0] += v[3] * t[0];					\
+   m[3][1] += v[3] * t[1];					\
+   m[3][2] += v[3] * t[2];					\
+   m[3][3] += v[3] * t[3];					\
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_2X2(d,m)					\
+{								\
+   d = m[0][0] * m[1][1] - m[0][1] * m[1][0];			\
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_3X3(d,m)					\
+{								\
+   d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]);		\
+   d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]);	\
+   d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]);	\
+}\
+
+
+/** i,j,th cofactor of a 4x4 matrix
+ *
+ */
+#define COFACTOR_4X4_IJ(fac,m,i,j) 				\
+{								\
+   int __ii[4], __jj[4], __k;						\
+								\
+   for (__k=0; __k<i; __k++) __ii[__k] = __k;				\
+   for (__k=i; __k<3; __k++) __ii[__k] = __k+1;				\
+   for (__k=0; __k<j; __k++) __jj[__k] = __k;				\
+   for (__k=j; __k<3; __k++) __jj[__k] = __k+1;				\
+								\
+   (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[2]] 	\
+                            - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[1]]); \
+   (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[2]]	\
+                             - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[0]]);\
+   (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[1]]	\
+                             - m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[0]]);\
+								\
+   __k = i+j;							\
+   if ( __k != (__k/2)*2) {						\
+      (fac) = -(fac);						\
+   }								\
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_4X4(d,m)					\
+{								\
+   double cofac;						\
+   COFACTOR_4X4_IJ (cofac, m, 0, 0);				\
+   d = m[0][0] * cofac;						\
+   COFACTOR_4X4_IJ (cofac, m, 0, 1);				\
+   d += m[0][1] * cofac;					\
+   COFACTOR_4X4_IJ (cofac, m, 0, 2);				\
+   d += m[0][2] * cofac;					\
+   COFACTOR_4X4_IJ (cofac, m, 0, 3);				\
+   d += m[0][3] * cofac;					\
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_2X2(a,m)					\
+{								\
+   a[0][0] = (m)[1][1];						\
+   a[0][1] = - (m)[1][0];						\
+   a[1][0] = - (m)[0][1];						\
+   a[1][1] = (m)[0][0];						\
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_3X3(a,m)					\
+{								\
+   a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1];			\
+   a[0][1] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]);		\
+   a[0][2] = m[1][0]*m[2][1] - m[1][1]*m[2][0];			\
+   a[1][0] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]);		\
+   a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0];			\
+   a[1][2] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]);		\
+   a[2][0] = m[0][1]*m[1][2] - m[0][2]*m[1][1];			\
+   a[2][1] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]);		\
+   a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]);		\
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_4X4(a,m)					\
+{								\
+   int i,j;							\
+								\
+   for (i=0; i<4; i++) {					\
+      for (j=0; j<4; j++) {					\
+         COFACTOR_4X4_IJ (a[i][j], m, i, j);			\
+      }								\
+   }								\
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_2X2(a,m)					\
+{								\
+   a[0][0] = (m)[1][1];						\
+   a[1][0] = - (m)[1][0];						\
+   a[0][1] = - (m)[0][1];						\
+   a[1][1] = (m)[0][0];						\
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_3X3(a,m)					\
+{								\
+   a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1];			\
+   a[1][0] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]);		\
+   a[2][0] = m[1][0]*m[2][1] - m[1][1]*m[2][0];			\
+   a[0][1] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]);		\
+   a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0];			\
+   a[2][1] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]);		\
+   a[0][2] = m[0][1]*m[1][2] - m[0][2]*m[1][1];			\
+   a[1][2] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]);		\
+   a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]);		\
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_4X4(a,m)					\
+{								\
+   char _i_,_j_;							\
+								\
+   for (_i_=0; _i_<4; _i_++) {					\
+      for (_j_=0; _j_<4; _j_++) {					\
+         COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_);			\
+      }								\
+   }								\
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_2X2(a,s,m)				\
+{								\
+   a[0][0] = (s) * m[1][1];					\
+   a[1][0] = - (s) * m[1][0];					\
+   a[0][1] = - (s) * m[0][1];					\
+   a[1][1] = (s) * m[0][0];					\
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_3X3(a,s,m)				\
+{								\
+   a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);	\
+   a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]);	\
+   a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);	\
+								\
+   a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]);	\
+   a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]);	\
+   a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]);	\
+								\
+   a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]);	\
+   a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]);	\
+   a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]);	\
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_4X4(a,s,m)				\
+{								\
+   char _i_,_j_; \
+   for (_i_=0; _i_<4; _i_++) {					\
+      for (_j_=0; _j_<4; _j_++) {					\
+         COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_);			\
+         a[_j_][_i_] *= s;						\
+      }								\
+   }								\
+}\
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_2X2(b,det,a)			\
+{						\
+   GREAL _tmp_;					\
+   DETERMINANT_2X2 (det, a);			\
+   _tmp_ = 1.0 / (det);				\
+   SCALE_ADJOINT_2X2 (b, _tmp_, a);		\
+}\
+
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_3X3(b,det,a)			\
+{						\
+   GREAL _tmp_;					\
+   DETERMINANT_3X3 (det, a);			\
+   _tmp_ = 1.0 / (det);				\
+   SCALE_ADJOINT_3X3 (b, _tmp_, a);		\
+}\
+
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_4X4(b,det,a)			\
+{						\
+   GREAL _tmp_;					\
+   DETERMINANT_4X4 (det, a);			\
+   _tmp_ = 1.0 / (det);				\
+   SCALE_ADJOINT_4X4 (b, _tmp_, a);		\
+}\
+
+//! @}
+
+/*! \defgroup BOUND_AABB_OPERATIONS
+*/
+//! @{
+
+//!Initializes an AABB
+#define INVALIDATE_AABB(aabb) {\
+    (aabb).minX = G_REAL_INFINITY;\
+    (aabb).maxX = -G_REAL_INFINITY;\
+    (aabb).minY = G_REAL_INFINITY;\
+    (aabb).maxY = -G_REAL_INFINITY;\
+    (aabb).minZ = G_REAL_INFINITY;\
+    (aabb).maxZ = -G_REAL_INFINITY;\
+}\
+
+#define AABB_GET_MIN(aabb,vmin) {\
+    vmin[0] = (aabb).minX;\
+    vmin[1] = (aabb).minY;\
+    vmin[2] = (aabb).minZ;\
+}\
+
+#define AABB_GET_MAX(aabb,vmax) {\
+    vmax[0] = (aabb).maxX;\
+    vmax[1] = (aabb).maxY;\
+    vmax[2] = (aabb).maxZ;\
+}\
+
+//!Copy boxes
+#define AABB_COPY(dest_aabb,src_aabb)\
+{\
+    (dest_aabb).minX = (src_aabb).minX;\
+    (dest_aabb).maxX = (src_aabb).maxX;\
+    (dest_aabb).minY = (src_aabb).minY;\
+    (dest_aabb).maxY = (src_aabb).maxY;\
+    (dest_aabb).minZ = (src_aabb).minZ;\
+    (dest_aabb).maxZ = (src_aabb).maxZ;\
+}\
+
+//! Computes an Axis aligned box from  a triangle
+#define COMPUTEAABB_FOR_TRIANGLE(aabb,V1,V2,V3) {\
+    (aabb).minX = MIN3(V1[0],V2[0],V3[0]);\
+    (aabb).maxX = MAX3(V1[0],V2[0],V3[0]);\
+    (aabb).minY = MIN3(V1[1],V2[1],V3[1]);\
+    (aabb).maxY = MAX3(V1[1],V2[1],V3[1]);\
+    (aabb).minZ = MIN3(V1[2],V2[2],V3[2]);\
+    (aabb).maxZ = MAX3(V1[2],V2[2],V3[2]);\
+}\
+
+//! Merge two boxes to destaabb
+#define MERGEBOXES(destaabb,aabb) {\
+    (destaabb).minX = MIN((aabb).minX,(destaabb).minX);\
+    (destaabb).minY = MIN((aabb).minY,(destaabb).minY);\
+    (destaabb).minZ = MIN((aabb).minZ,(destaabb).minZ);\
+    (destaabb).maxX = MAX((aabb).maxX,(destaabb).maxX);\
+    (destaabb).maxY = MAX((aabb).maxY,(destaabb).maxY);\
+    (destaabb).maxZ = MAX((aabb).maxZ,(destaabb).maxZ);\
+}\
+
+//! Extends the box
+#define AABB_POINT_EXTEND(destaabb,p) {\
+    (destaabb).minX = MIN(p[0],(destaabb).minX);\
+    (destaabb).maxX = MAX(p[0],(destaabb).maxX);\
+    (destaabb).minY = MIN(p[1],(destaabb).minY);\
+    (destaabb).maxY = MAX(p[1],(destaabb).maxY);\
+    (destaabb).minZ = MIN(p[2],(destaabb).minZ);\
+    (destaabb).maxZ = MAX(p[2],(destaabb).maxZ);\
+}\
+
+//! Finds the intersection box of two boxes
+#define BOXINTERSECTION(aabb1, aabb2, iaabb) {\
+    (iaabb).minX = MAX((aabb1).minX,(aabb2).minX);\
+    (iaabb).minY = MAX((aabb1).minY,(aabb2).minY);\
+    (iaabb).minZ = MAX((aabb1).minZ,(aabb2).minZ);\
+    (iaabb).maxX = MIN((aabb1).maxX,(aabb2).maxX);\
+    (iaabb).maxY = MIN((aabb1).maxY,(aabb2).maxY);\
+    (iaabb).maxZ = MIN((aabb1).maxZ,(aabb2).maxZ);\
+}\
+
+//! Determines if two aligned boxes do intersect
+#define AABBCOLLISION(intersected,aabb1,aabb2) {\
+	intersected = 1;\
+	if ((aabb1).minX > (aabb2).maxX ||\
+        (aabb1).maxX < (aabb2).minX ||\
+        (aabb1).minY > (aabb2).maxY ||\
+        (aabb1).maxY < (aabb2).minY ||\
+        (aabb1).minZ > (aabb2).maxZ ||\
+        (aabb1).maxZ < (aabb2).minZ )\
+	{\
+		intersected = 0;\
+	}\
+}\
+
+#define AXIS_INTERSECT(min,max, a, d,tfirst, tlast,is_intersected) {\
+	if(IS_ZERO(d))\
+	{\
+        is_intersected = !(a < min || a > max);\
+	}\
+	else\
+	{\
+        GREAL a0, a1;\
+        a0 = (min - a) / (d);\
+        a1 = (max - a) / (d);\
+        if(a0 > a1)   SWAP_NUMBERS(a0, a1);\
+        tfirst = MAX(a0, tfirst);\
+        tlast = MIN(a1, tlast);\
+        if (tlast < tfirst)\
+        {\
+             is_intersected = 0;\
+        }\
+        else\
+        {\
+            is_intersected = 1;\
+        }\
+	}\
+}\
+
+/*! \brief Finds the Ray intersection parameter.
+
+\param aabb Aligned box
+\param vorigin A vec3f with the origin of the ray
+\param vdir A vec3f with the direction of the ray
+\param tparam Output parameter
+\param tmax Max lenght of the ray
+\param is_intersected 1 if the ray collides the box, else false
+
+*/
+#define BOX_INTERSECTS_RAY(aabb, vorigin, vdir, tparam, tmax,is_intersected) { \
+	GREAL _tfirst = 0.0f, _tlast = tmax;\
+	AXIS_INTERSECT(aabb.minX,aabb.maxX,vorigin[0], vdir[0], _tfirst, _tlast,is_intersected);\
+	if(is_intersected)\
+	{\
+        AXIS_INTERSECT(aabb.minY,aabb.maxY,vorigin[1], vdir[1], _tfirst, _tlast,is_intersected);\
+	}\
+	if(is_intersected)\
+	{\
+        AXIS_INTERSECT(aabb.minZ,aabb.maxZ,vorigin[2], vdir[2], _tfirst, _tlast,is_intersected);\
+	}\
+	tparam = _tfirst;\
+}\
+
+#define AABB_PROJECTION_INTERVAL(aabb,direction, vmin, vmax)\
+{\
+    GREAL _center[] = {(aabb.minX + aabb.maxX)*0.5f, (aabb.minY + aabb.maxY)*0.5f, (aabb.minZ + aabb.maxZ)*0.5f};\
+    \
+    GREAL _extend[] = {aabb.maxX-_center[0],aabb.maxY-_center[1],aabb.maxZ-_center[2]};\
+    GREAL _fOrigin =  VEC_DOT(direction,_center);\
+	GREAL _fMaximumExtent = _extend[0]*fabsf(direction[0]) + \
+                            _extend[1]*fabsf(direction[1]) + \
+                            _extend[2]*fabsf(direction[2]); \
+\
+    vmin = _fOrigin - _fMaximumExtent; \
+    vmax = _fOrigin + _fMaximumExtent; \
+}\
+
+/*!
+classify values:
+<ol>
+<li> 0 : In back of plane
+<li> 1 : Spanning
+<li> 2 : In front of
+</ol>
+*/
+#define PLANE_CLASSIFY_BOX(plane,aabb,classify)\
+{\
+	GREAL _fmin,_fmax; \
+	AABB_PROJECTION_INTERVAL(aabb,plane, _fmin, _fmax); \
+	if(plane[3] >= _fmax) \
+	{ \
+		classify = 0;/*In back of*/ \
+	} \
+	else \
+	{ \
+		if(plane[3]+0.000001f>=_fmin) \
+		{ \
+			classify = 1;/*Spanning*/ \
+		} \
+		else \
+		{ \
+			classify = 2;/*In front of*/ \
+		} \
+	} \
+}\
+//! @}
+
+/*! \defgroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+
+#define PLANEDIREPSILON 0.0000001f
+#define PARALELENORMALS 0.000001f
+
+#define TRIANGLE_NORMAL(v1,v2,v3,n){\
+    vec3f _dif1,_dif2; \
+    VEC_DIFF(_dif1,v2,v1); \
+    VEC_DIFF(_dif2,v3,v1); \
+    VEC_CROSS(n,_dif1,_dif2); \
+    VEC_NORMALIZE(n); \
+}\
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
+    TRIANGLE_NORMAL(v1,v2,v3,plane);\
+    plane[3] = VEC_DOT(v1,plane);\
+}\
+
+/// Calc a plane from an edge an a normal. plane is a vec4f
+#define EDGE_PLANE(e1,e2,n,plane) {\
+    vec3f _dif; \
+    VEC_DIFF(_dif,e2,e1); \
+    VEC_CROSS(plane,_dif,n); \
+    VEC_NORMALIZE(plane); \
+    plane[3] = VEC_DOT(e1,plane);\
+}\
+
+#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
+
+#define PROJECT_POINT_PLANE(point,plane,projected) {\
+	GREAL _dis;\
+	_dis = DISTANCE_PLANE_POINT(plane,point);\
+	VEC_SCALE(projected,-_dis,plane);\
+	VEC_SUM(projected,projected,point);	\
+}\
+
+#define POINT_IN_HULL(point,planes,plane_count,outside)\
+{\
+	GREAL _dis;\
+	outside = 0;\
+	GUINT _i = 0;\
+	do\
+	{\
+	    _dis = DISTANCE_PLANE_POINT(planes[_i],point);\
+	    if(_dis>0.0f) outside = 1;\
+	    _i++;\
+	}while(_i<plane_count&&outside==0);\
+}\
+
+
+#define PLANE_CLIP_SEGMENT(s1,s2,plane,clipped) {\
+	GREAL _dis1,_dis2;\
+	_dis1 = DISTANCE_PLANE_POINT(plane,s1);\
+	VEC_DIFF(clipped,s2,s1);\
+	_dis2 = VEC_DOT(clipped,plane);\
+	VEC_SCALE(clipped,-_dis1/_dis2,clipped);\
+	VEC_SUM(clipped,clipped,s1);	\
+}\
+
+//! Confirms if the plane intersect the edge or nor
+/*!
+intersection type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+#define PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped,intersection_type) \
+{\
+	GREAL _dis1,_dis2;\
+	_dis1 = DISTANCE_PLANE_POINT(plane,s1);\
+	_dis2 = DISTANCE_PLANE_POINT(plane,s2);\
+	if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)\
+	{\
+	    if(_dis1<_dis2) intersection_type = 0;\
+	    else  intersection_type = 1;\
+	}\
+	else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)\
+	{\
+	    if(_dis1>_dis2) intersection_type = 2;\
+	    else  intersection_type = 3;	    \
+	}\
+	else\
+	{\
+	    if(_dis1<_dis2) intersection_type = 4;\
+	    else  intersection_type = 5;\
+        VEC_DIFF(clipped,s2,s1);\
+        _dis2 = VEC_DOT(clipped,plane);\
+        VEC_SCALE(clipped,-_dis1/_dis2,clipped);\
+        VEC_SUM(clipped,clipped,s1);	\
+	}\
+}\
+
+//! Confirms if the plane intersect the edge or not
+/*!
+clipped1 and clipped2 are the vertices behind the plane.
+clipped1 is the closest
+
+intersection_type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+#define PLANE_CLIP_SEGMENT_CLOSEST(s1,s2,plane,clipped1,clipped2,intersection_type)\
+{\
+	PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1,intersection_type);\
+	if(intersection_type == 0)\
+	{\
+	    VEC_COPY(clipped1,s1);\
+	    VEC_COPY(clipped2,s2);\
+	}\
+	else if(intersection_type == 1)\
+	{\
+	    VEC_COPY(clipped1,s2);\
+	    VEC_COPY(clipped2,s1);\
+	}\
+	else if(intersection_type == 2)\
+	{\
+	    VEC_COPY(clipped1,s1);\
+	    VEC_COPY(clipped2,s2);\
+	}\
+	else if(intersection_type == 3)\
+	{\
+	    VEC_COPY(clipped1,s2);\
+	    VEC_COPY(clipped2,s1);\
+	}\
+	else if(intersection_type == 4)\
+	{	    \
+	    VEC_COPY(clipped2,s1);\
+	}\
+	else if(intersection_type == 5)\
+	{	    \
+	    VEC_COPY(clipped2,s2);\
+	}\
+}\
+
+
+//! Finds the 2 smallest cartesian coordinates of a plane normal
+#define PLANE_MINOR_AXES(plane, i0, i1)\
+{\
+    GREAL A[] = {fabs(plane[0]),fabs(plane[1]),fabs(plane[2])};\
+    if(A[0]>A[1])\
+	{\
+		if(A[0]>A[2])\
+		{\
+			i0=1;  /* A[0] is greatest */ \
+			i1=2;\
+		}\
+		else \
+		{\
+			i0=0;      /* A[2] is greatest */ \
+			i1=1; \
+		}\
+	}\
+	else   /* A[0]<=A[1] */ \
+	{\
+		if(A[2]>A[1]) \
+		{ \
+			i0=0;      /* A[2] is greatest */ \
+			i1=1; \
+		}\
+		else \
+		{\
+			i0=0;      /* A[1] is greatest */ \
+			i1=2; \
+		}\
+	} \
+}\
+
+//! Ray plane collision
+#define RAY_PLANE_COLLISION(plane,vDir,vPoint,pout,tparam,does_intersect)\
+{\
+	GREAL _dis,_dotdir;	\
+	_dotdir = VEC_DOT(plane,vDir);\
+	if(_dotdir<PLANEDIREPSILON)\
+	{\
+	    does_intersect = 0;\
+	}\
+	else\
+	{\
+        _dis = DISTANCE_PLANE_POINT(plane,vPoint);	\
+        tparam = -_dis/_dotdir;\
+        VEC_SCALE(pout,tparam,vDir);\
+        VEC_SUM(pout,vPoint,pout);	\
+        does_intersect = 1;\
+	}\
+}\
+
+//! Bidireccional ray
+#define LINE_PLANE_COLLISION(plane,vDir,vPoint,pout,tparam, tmin, tmax)\
+{\
+    tparam = -DISTANCE_PLANE_POINT(plane,vPoint);\
+	tparam /= VEC_DOT(plane,vDir);\
+    tparam = CLAMP(tparam,tmin,tmax);\
+    VEC_SCALE(pout,tparam,vDir);\
+    VEC_SUM(pout,vPoint,pout);	\
+}\
+
+/*! \brief Returns the Ray on which 2 planes intersect if they do.
+    Written by Rodrigo Hernandez on ODE convex collision
+
+  \param p1 Plane 1
+  \param p2 Plane 2
+  \param p Contains the origin of the ray upon returning if planes intersect
+  \param d Contains the direction of the ray upon returning if planes intersect
+  \param dointersect 1 if the planes intersect, 0 if paralell.
+
+*/
+#define INTERSECT_PLANES(p1,p2,p,d,dointersect) \
+{ \
+  VEC_CROSS(d,p1,p2); \
+  GREAL denom = VEC_DOT(d, d);\
+  if (IS_ZERO(denom)) \
+  { \
+      dointersect = 0; \
+  } \
+  else \
+  { \
+      vec3f _n;\
+      _n[0]=p1[3]*p2[0] - p2[3]*p1[0]; \
+      _n[1]=p1[3]*p2[1] - p2[3]*p1[1]; \
+      _n[2]=p1[3]*p2[2] - p2[3]*p1[2]; \
+      VEC_CROSS(p,_n,d); \
+      p[0]/=denom; \
+      p[1]/=denom; \
+      p[2]/=denom; \
+      dointersect = 1; \
+  }\
+}\
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+#define CLOSEST_POINT_ON_SEGMENT(cp,v,e1,e2)			\
+{ \
+    vec3f _n;\
+    VEC_DIFF(_n,e2,e1);\
+    VEC_DIFF(cp,v,e1);\
+	GREAL _scalar = VEC_DOT(cp, _n);			\
+	_scalar/= VEC_DOT(_n, _n); \
+	if(_scalar <0.0f)\
+	{\
+	    VEC_COPY(cp,e1);\
+	}\
+	else if(_scalar >1.0f)\
+	{\
+	    VEC_COPY(cp,e2);\
+	}\
+	else \
+	{\
+        VEC_SCALE(cp,_scalar,_n);\
+        VEC_SUM(cp,cp,e1);\
+	}	\
+}\
+
+
+/*! \brief Finds the line params where these lines intersect.
+
+\param dir1 Direction of line 1
+\param point1 Point of line 1
+\param dir2 Direction of line 2
+\param point2 Point of line 2
+\param t1 Result Parameter for line 1
+\param t2 Result Parameter for line 2
+\param dointersect  0  if the lines won't intersect, else 1
+
+*/
+#define LINE_INTERSECTION_PARAMS(dir1,point1, dir2, point2,t1,t2,dointersect) {\
+    GREAL det;\
+	GREAL e1e1 = VEC_DOT(dir1,dir1);\
+	GREAL e1e2 = VEC_DOT(dir1,dir2);\
+	GREAL e2e2 = VEC_DOT(dir2,dir2);\
+	vec3f p1p2;\
+    VEC_DIFF(p1p2,point1,point2);\
+    GREAL p1p2e1 = VEC_DOT(p1p2,dir1);\
+	GREAL p1p2e2 = VEC_DOT(p1p2,dir2);\
+	det = e1e2*e1e2 - e1e1*e2e2;\
+	if(IS_ZERO(det))\
+	{\
+	     dointersect = 0;\
+	}\
+	else\
+	{\
+        t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;\
+        t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;\
+        dointersect = 1;\
+	}\
+}\
+
+//! Find closest points on segments
+#define SEGMENT_COLLISION(vA1,vA2,vB1,vB2,vPointA,vPointB)\
+{\
+    vec3f _AD,_BD,_N;\
+    vec4f _M;\
+    VEC_DIFF(_AD,vA2,vA1);\
+    VEC_DIFF(_BD,vB2,vB1);\
+    VEC_CROSS(_N,_AD,_BD);\
+    VEC_CROSS(_M,_N,_BD);\
+    _M[3] = VEC_DOT(_M,vB1);\
+    float _tp; \
+    LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,0.0f, 1.0f);\
+    /*Closest point on segment*/ \
+    VEC_DIFF(vPointB,vPointA,vB1);\
+	_tp = VEC_DOT(vPointB, _BD);			\
+	_tp/= VEC_DOT(_BD, _BD); \
+	_tp = CLAMP(_tp,0.0f,1.0f);	\
+    VEC_SCALE(vPointB,_tp,_BD);\
+    VEC_SUM(vPointB,vPointB,vB1);\
+}\
+
+//! @}
+
+///Additional Headers for Collision
+#include "GIMPACT/gim_tri_collision.h"
+#include "GIMPACT/gim_tri_sphere_collision.h"
+#include "GIMPACT/gim_tri_capsule_collision.h"
+
+#endif // GIM_VECTOR_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_math.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_math.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_math.h	(revision 216)
@@ -0,0 +1,147 @@
+#ifndef GIM_MATH_H_INCLUDED
+#define GIM_MATH_H_INCLUDED
+
+/*! \file gim_math.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include <math.h>
+#include <float.h>
+
+
+/*! \defgroup BASIC_TYPES
+Basic types and constants
+Conventions:
+Types starting with G
+Constants starting with G_
+*/
+//! @{
+/*! Types */
+#define GREAL float
+#define GINT long
+#define GUINT unsigned long
+/*! Constants for integers*/
+#define GUINT_BIT_COUNT 32
+#define GUINT_EXPONENT 5
+
+#define G_FASTMATH 1
+#define G_PI 3.14159265358979f
+#define G_HALF_PI 1.5707963f
+//267948966
+#define G_TWO_PI 6.28318530f
+//71795864
+#define G_ROOT3 1.73205f
+#define G_ROOT2 1.41421f
+#define G_UINT_INFINITY 65534
+#define G_REAL_INFINITY FLT_MAX
+#define	G_SIGN_BITMASK			0x80000000
+#define G_USE_EPSILON_TEST
+#define G_EPSILON 0.0000001f
+//! @}
+
+/*! \defgroup MATH_FUNCTIONS
+mathematical functions
+*/
+//! @{
+#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f)
+#define G_RADTODEG(X) ((X)*180.0f/3.1415926f)
+
+//! Integer representation of a floating-point value.
+#define IR(x)					((GUINT&)(x))
+
+//! Signed integer representation of a floating-point value.
+#define SIR(x)					((GINT&)(x))
+
+//! Absolute integer representation of a floating-point value
+#define AIR(x)					(IR(x)&0x7fffffff)
+
+//! Floating-point representation of an integer value.
+#define FR(x)					((GREAL&)(x))
+
+#define MAX(a,b) (a<b?b:a)
+#define MIN(a,b) (a>b?b:a)
+
+#define MAX3(a,b,c) MAX(a,MAX(b,c))
+#define MIN3(a,b,c) MIN(a,MIN(b,c))
+
+#define IS_ZERO(value) (value < G_EPSILON &&  value > -G_EPSILON)
+
+#define IS_NEGATIVE(value) (value <= -G_EPSILON)
+
+#define IS_POSISITVE(value) (value >= G_EPSILON)
+
+///returns a clamped number
+#define CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+
+///Swap numbers
+#define SWAP_NUMBERS(a,b){ \
+    a = a+b; \
+    b = a-b; \
+    a = a-b; \
+}\
+
+#define GIM_INV_SQRT(va,isva)\
+{\
+    if(va<=0.0000001f)\
+    {\
+        isva = G_REAL_INFINITY;\
+    }\
+    else\
+    {\
+        GREAL _x = va * 0.5f;\
+        GUINT _y = 0x5f3759df - ( IR(va) >> 1);\
+        isva = FR(_y);\
+        isva  = isva * ( 1.5f - ( _x * isva * isva ) );\
+    }\
+}\
+
+#define GIM_SQRT(va,sva)\
+{\
+    GIM_INV_SQRT(va,sva);\
+    sva = 1.0f/sva;\
+}\
+
+//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
+GREAL gim_inv_sqrt(GREAL f);
+
+//! Computes sqrtf(x) faster.
+/*!
+\sa gim_inv_sqrt
+*/
+GREAL gim_sqrt(GREAL f);
+
+//!Initializes mathematical functions
+void gim_init_math();
+
+//! Generates an unit random
+GREAL gim_unit_random();
+//! @}
+
+#endif // GIM_MATH_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_memory.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_memory.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_memory.h	(revision 216)
@@ -0,0 +1,1040 @@
+#ifndef GIM_MEMORY_H_INCLUDED
+#define GIM_MEMORY_H_INCLUDED
+/*! \file gim_memory.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_math.h"
+#include <memory.h>
+
+//#define PREFETCH 1
+//! \defgroup PREFETCH
+//! @{
+#ifdef PREFETCH
+#include <xmmintrin.h>	// for prefetch
+#define pfval	64
+#define pfval2	128
+//! Prefetch 64
+#define pf(_x,_i)	_mm_prefetch((void *)(_x + _i + pfval), 0)
+//! Prefetch 128
+#define pf2(_x,_i)	_mm_prefetch((void *)(_x + _i + pfval2), 0)
+#else
+//! Prefetch 64
+#define pf(_x,_i)
+//! Prefetch 128
+#define pf2(_x,_i)
+#endif
+//! @}
+
+/*! \defgroup ARRAY_UTILITIES
+\brief
+Functions for manip packed arrays of numbers
+*/
+//! @{
+#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
+{\
+    GUINT _i_;\
+    for (_i_=0;_i_<element_count ;_i_++)\
+    {\
+    	dest_array[_i_] = source_array[_i_];\
+    }\
+}\
+
+#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
+{\
+    GUINT _i_;\
+    for (_i_=0;_i_<element_count ;_i_++)\
+    {\
+    	copy_macro(dest_array[_i_],source_array[_i_]);\
+    }\
+}\
+
+
+#define GIM_ZERO_ARRAY(array,element_count)\
+{\
+    GUINT _i_;\
+    for (_i_=0;_i_<element_count ;_i_++)\
+    {\
+    	array[_i_] = 0;\
+    }\
+}\
+
+#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
+{\
+    GUINT _i_;\
+    for (_i_=0;_i_<element_count ;_i_++)\
+    {\
+    	array[_i_] = constant;\
+    }\
+}\
+//! @}
+
+/*! \defgroup MEMORY_FUNCTION_PROTOTYPES
+Function prototypes to allocate and free memory.
+*/
+//! @{
+typedef void * gim_alloc_function (size_t size);
+typedef void * gim_alloca_function (size_t size);//Allocs on the heap
+typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
+typedef void gim_free_function (void *ptr, size_t size);
+//! @}
+
+/*! \defgroup MEMORY_FUNCTION_HANDLERS
+\brief
+Memory Function Handlers
+ set new memory management functions. if fn is 0, the default handlers are
+  used. */
+//! @{
+void gim_set_alloc_handler (gim_alloc_function *fn);
+void gim_set_alloca_handler (gim_alloca_function *fn);
+void gim_set_realloc_handler (gim_realloc_function *fn);
+void gim_set_free_handler (gim_free_function *fn);
+//! @}
+
+/*! \defgroup MEMORY_FUNCTION_GET_HANDLERS
+\brief
+get current memory management functions.
+*/
+//! @{
+gim_alloc_function *gim_get_alloc_handler (void);
+gim_alloca_function *gim_get_alloca_handler(void);
+gim_realloc_function *gim_get_realloc_handler (void);
+gim_free_function  *gim_get_free_handler (void);
+//! @}
+
+/*! \defgroup MEMORY_FUNCTIONS
+Standar Memory functions
+*/
+//! @{
+void * gim_alloc(size_t size);
+void * gim_alloca(size_t size);
+void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
+void gim_free(void *ptr, size_t size);
+//! @}
+
+/*! \defgroup DYNAMIC_ARRAYS
+\brief
+Dynamic Arrays. Allocated from system memory.
+<ul>
+<li> For initializes a dynamic array, use GIM_DYNARRAY_CREATE or GIM_DYNARRAY_CREATE_SIZED.
+<li> When an array is no longer used, must be terminated with the macro GIM_DYNARRAY_DESTROY.
+</ul>
+*/
+//! @{
+#define G_ARRAY_GROW_SIZE 100
+
+//! Dynamic array handle.
+struct GDYNAMIC_ARRAY
+{
+    char * m_pdata;
+    GUINT m_size;
+    GUINT m_reserve_size;
+};
+//typedef  struct _GDYNAMIC_ARRAY GDYNAMIC_ARRAY;
+
+//! Creates a dynamic array zero sized
+#define GIM_DYNARRAY_CREATE(type,array_data,reserve_size) \
+{ \
+    array_data.m_pdata = (char *)gim_alloc(reserve_size*sizeof(type)); \
+    array_data.m_size = 0; \
+    array_data.m_reserve_size = reserve_size; \
+}\
+
+//! Creates a dynamic array with n = size elements
+#define GIM_DYNARRAY_CREATE_SIZED(type,array_data,size) \
+{ \
+    array_data.m_pdata = (char *)gim_alloc(size*sizeof(type)); \
+    array_data.m_size = size; \
+    array_data.m_reserve_size = size; \
+}\
+
+//! Reserves memory for a dynamic array.
+#define GIM_DYNARRAY_RESERVE_SIZE(type,array_data,reserve_size) \
+{ \
+    if(reserve_size>array_data.m_reserve_size )\
+    { \
+        array_data.m_pdata = (char *) gim_realloc(array_data.m_pdata,array_data.m_size*sizeof(type),reserve_size*sizeof(type));\
+        array_data.m_reserve_size = reserve_size; \
+    }\
+}\
+
+//! Set the size of the array
+#define GIM_DYNARRAY_SET_SIZE(type,array_data,size) \
+{ \
+    GIM_DYNARRAY_RESERVE_SIZE(type,array_data,size);\
+    array_data.m_size = size;\
+}\
+
+//! Gets a pointer from the beginning of the array
+#define GIM_DYNARRAY_POINTER(type,array_data) (type *)(array_data.m_pdata)
+
+//! Gets a pointer from the last elemento of the array
+#define GIM_DYNARRAY_POINTER_LAST(type,array_data) (((type *)array_data.m_pdata)+array_data.m_size-1)
+
+//! Inserts an element at the last position
+#define GIM_DYNARRAY_PUSH_ITEM(type,array_data,item)\
+{\
+    if(array_data.m_reserve_size<=array_data.m_size)\
+    {\
+        GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
+    }\
+    type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
+    memcpy(&_pt[array_data.m_size],&item,sizeof(type));\
+    array_data.m_size++;    \
+}\
+
+//! Inserts an element at the last position
+#define GIM_DYNARRAY_PUSH_EMPTY(type,array_data)\
+{\
+    if(array_data.m_reserve_size<=array_data.m_size)\
+    {\
+        GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
+    }\
+    array_data.m_size++;    \
+}\
+
+//! Inserts an element
+#define GIM_DYNARRAY_INSERT_ITEM(type,array_data,item,index) \
+{ \
+    if(array_data.m_reserve_size<=array_data.m_size)\
+    {\
+        GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
+    }\
+    type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
+    if(index<array_data.m_size-1) \
+    { \
+        memcpy(&_pt[index+1],&_pt[index],(array_data.m_size-index)*sizeof(type));\
+    } \
+    memcpy(&_pt[index],&item,sizeof(type));\
+    array_data.m_size++;    \
+}\
+
+//! Removes an element
+#define GIM_DYNARRAY_DELETE_ITEM(type,array_data,index) \
+{ \
+    if(index<array_data.m_size-1) \
+    { \
+        type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
+        memcpy(&_pt[index],&_pt[index+1],(array_data.m_size-index-1)*sizeof(type));\
+    } \
+    array_data.m_size--;    \
+}\
+
+//! Removes an element at the last position
+#define GIM_DYNARRAY_POP_ITEM(array_data) \
+{ \
+    if(array_data.m_size>0) \
+    { \
+        array_data.m_size--;    \
+    } \
+}\
+
+//! Destroys the array
+void GIM_DYNARRAY_DESTROY(GDYNAMIC_ARRAY & array_data);
+//! @}
+
+/*! \defgroup BITSET
+\brief
+Bitsets , based on \ref DYNAMIC_ARRAYS .
+<ul>
+<li> For initializes a bitset array, use \ref GIM_BITSET_CREATE or \ref GIM_BITSET_CREATE_SIZED.
+<li> When the bitset is no longer used, must be terminated with the macro \ref GIM_DYNARRAY_DESTROY.
+<li> For putting a mark on the bitset, call \ref GIM_BITSET_SET
+<li> For clearing a mark on the bitset, call \ref GIM_BITSET_CLEAR
+<li> For retrieving a bit value from a bitset, call \ref GIM_BITSET_GET-
+</ul>
+*/
+//! @{
+
+//! Creates a bitset
+#define GIM_BITSET_CREATE(array_data) GIM_DYNARRAY_CREATE(GUINT,array_data,G_ARRAY_GROW_SIZE)
+
+//! Creates a bitset, with their bits set to 0.
+#define GIM_BITSET_CREATE_SIZED(array_data,bits_count)\
+{\
+    array_data.m_size = bits_count/GUINT_BIT_COUNT + 1;\
+    GIM_DYNARRAY_CREATE(GUINT,array_data,array_data.m_size);\
+    GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
+    memset(_pt,0,sizeof(GUINT)*(array_data.m_size));\
+}\
+
+//! Gets the bitset bit count.
+#define GIM_BITSET_SIZE(array_data) (array_data.m_size*GUINT_BIT_COUNT)
+
+//! Resizes a bitset, with their bits set to 0.
+#define GIM_BITSET_RESIZE(array_data,new_bits_count)\
+{    \
+    GUINT _oldsize = array_data.m_size;\
+    array_data.m_size = new_bits_count/GUINT_BIT_COUNT + 1;    \
+    if(_oldsize<array_data.m_size)\
+    {\
+        if(array_data.m_size > array_data.m_reserve_size)\
+        {\
+            GIM_DYNARRAY_RESERVE_SIZE(GUINT,array_data,array_data.m_size+G_ARRAY_GROW_SIZE);\
+        }\
+        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
+        memset(&_pt[_oldsize],0,sizeof(GUINT)*(array_data.m_size-_oldsize));\
+    }\
+}\
+
+//! Sets all bitset bit to 0.
+#define GIM_BITSET_CLEAR_ALL(array_data)\
+{\
+    memset(array_data.m_pdata,0,sizeof(GUINT)*array_data.m_size);\
+}\
+
+//! Sets all bitset bit to 1.
+#define GIM_BITSET_SET_ALL(array_data)\
+{\
+    memset(array_data.m_pdata,0xFF,sizeof(GUINT)*array_data.m_size);\
+}\
+
+///Sets the desired bit to 1
+#define GIM_BITSET_SET(array_data,bit_index)\
+{\
+    if(bit_index>=GIM_BITSET_SIZE(array_data))\
+	{\
+	    GIM_BITSET_RESIZE(array_data,bit_index);\
+	}\
+	GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
+	_pt[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));\
+}\
+
+///Return 0 or 1
+#define GIM_BITSET_GET(array_data,bit_index,get_value) \
+{\
+    if(bit_index>=GIM_BITSET_SIZE(array_data))\
+	{\
+	    get_value = 0;\
+	}\
+	else\
+	{\
+        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
+        get_value = _pt[bit_index >> GUINT_EXPONENT] & (1 << (bit_index & (GUINT_BIT_COUNT-1)));\
+	}\
+}\
+
+///Sets the desired bit to 0
+#define GIM_BITSET_CLEAR(array_data,bit_index) \
+{\
+    if(bit_index<GIM_BITSET_SIZE(array_data))\
+	{\
+        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
+        _pt[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));\
+	}\
+}\
+//! @}
+
+/*! \defgroup MEMORY_ACCESS_CONSTANTS
+\brief
+Memory Access constants.
+\sa BUFFERS
+*/
+//! @{
+#define G_MA_READ_ONLY 1
+#define G_MA_WRITE_ONLY 2
+#define G_MA_READ_WRITE 3
+//! @}
+
+/*! \defgroup MEMORY_USAGE_CONSTANTS
+\brief
+Memory usage constants.
+\sa BUFFERS
+*/
+//! @{
+/// Don't care how memory is used
+#define G_MU_EITHER 0
+/// specified once, doesn't allow read information
+#define G_MU_STATIC_WRITE 1
+/// specified once, allows to read information from a shadow buffer
+#define G_MU_STATIC_READ 2
+/// write directly on buffer, allows to read information from a shadow buffer
+#define G_MU_STATIC_READ_DYNAMIC_WRITE 3
+/// upload data to buffer from the shadow buffer, allows to read information from a shadow buffer
+#define G_MU_STATIC_READ_DYNAMIC_WRITE_COPY 4
+/// specified once, allows to read information directly from memory
+#define G_MU_STATIC_WRITE_DYNAMIC_READ 5
+/// write directly on buffer, allows to read information directly from memory
+#define G_MU_DYNAMIC_READ_WRITE 6
+//! @}
+
+/*! \defgroup BUFFER_ERRORS
+\brief
+Buffer operation errors
+\sa BUFFERS
+*/
+//! @{
+#define G_BUFFER_OP_SUCCESS 0
+#define G_BUFFER_OP_INVALID 1
+#define G_BUFFER_OP_STILLREFCOUNTED 2
+//! @}
+
+/*! \defgroup BUFFER_MANAGER_IDS
+\brief
+Buffer manager identifiers
+\sa BUFFERS, BUFFER_MANAGERS
+*/
+//! @{
+#define G_BUFFER_MANAGER_SYSTEM 0
+#define G_BUFFER_MANAGER_SHARED 1
+#define G_BUFFER_MANAGER_USER 2
+//! @}
+
+/*! \defgroup BUFFERS
+\brief
+Buffer operations and structs.
+<ul>
+<li> Before using buffers you must initializes GIMPACT buffer managers by calling \ref gimpact_init.
+<li> For initializes a buffer, use  \ref gim_create_buffer, \ref gim_create_buffer_from_data , \ref gim_create_common_buffer, \ref gim_create_common_buffer_from_data or \ref gim_create_shared_buffer_from_data.
+<li> For accessing to the buffer memory, you must call \ref gim_lock_buffer, and then \ref gim_unlock_buffer for finish the access.
+<li> When a buffer is no longer needed, you must free it by calling \ref gim_buffer_free.
+<li> You must call \ref gimpact_terminate when finish your application.
+<li> For a safe manipulation of buffers, use \ref BUFFER_ARRAYS
+</ul>
+\sa BUFFER_MANAGERS, BUFFER_ARRAYS
+*/
+//! @{
+
+//! Buffer handle.
+struct GBUFFER_ID
+{
+    GUINT m_buffer_id;
+    GUINT m_buffer_manager_id;
+};
+//typedef  struct _GBUFFER_ID GBUFFER_ID;
+
+//! Buffer internal data
+struct GBUFFER_DATA
+{
+    GUINT m_buffer_handle;//!< if 0, buffer doesn't exists
+    GUINT m_size;
+    GUINT m_usage;
+    GINT m_access;
+    GUINT m_lock_count;
+    char * m_mapped_pointer;
+    GBUFFER_ID m_shadow_buffer;
+    GUINT m_refcount;//! Reference counting for safe garbage collection
+};
+//typedef  struct _GBUFFER_DATA GBUFFER_DATA;
+//! @}
+
+/*! \defgroup BUFFERS_MANAGER_PROTOTYPES
+\brief
+Function prototypes to allocate and free memory for buffers
+\sa BUFFER_MANAGERS, BUFFERS
+*/
+//! @{
+
+//! Returns a Buffer handle
+typedef GUINT gim_buffer_alloc_function(GUINT size,int usage);
+
+//! Returns a Buffer handle, and copies the pdata to the buffer
+typedef GUINT gim_buffer_alloc_data_function(const void * pdata,GUINT size,int usage);
+
+//! Changes the size of the buffer preserving the content, and returns the new buffer id
+typedef GUINT gim_buffer_realloc_function(GUINT buffer_handle,GUINT oldsize,int old_usage,GUINT newsize,int new_usage);
+
+//! It changes the m_buffer_handle member to 0/0
+typedef void gim_buffer_free_function(GUINT buffer_handle,GUINT size);
+
+//! It maps the m_mapped_pointer. Returns a pointer
+typedef char * gim_lock_buffer_function(GUINT buffer_handle,int access);
+
+//! It sets the m_mapped_pointer to 0
+typedef void gim_unlock_buffer_function(GUINT buffer_handle);
+
+typedef void gim_download_from_buffer_function(
+        GUINT source_buffer_handle,
+		GUINT source_pos,
+		void * destdata,
+		GUINT copysize);
+
+typedef void  gim_upload_to_buffer_function(
+        GUINT dest_buffer_handle,
+		GUINT dest_pos,
+		void * sourcedata,
+		GUINT copysize);
+
+typedef void gim_copy_buffers_function(
+		GUINT source_buffer_handle,
+		GUINT source_pos,
+		GUINT dest_buffer_handle,
+		GUINT dest_pos,
+		GUINT copysize);
+//! @}
+
+
+/*! \defgroup BUFFER_MANAGERS
+\brief
+Buffer Manager operations
+*/
+//! @{
+//! Buffer manager prototype
+struct GBUFFER_MANAGER_PROTOTYPE
+{
+    gim_buffer_alloc_function * alloc_fn;
+    gim_buffer_alloc_data_function *alloc_data_fn;
+    gim_buffer_realloc_function * realloc_fn;
+    gim_buffer_free_function * free_fn;
+    gim_lock_buffer_function * lock_buffer_fn;
+    gim_unlock_buffer_function * unlock_buffer_fn;
+    gim_download_from_buffer_function * download_from_buffer_fn;
+    gim_upload_to_buffer_function * upload_to_buffer_fn;
+    gim_copy_buffers_function * copy_buffers_fn;
+};
+//typedef  struct _GBUFFER_MANAGER_PROTOTYPE GBUFFER_MANAGER_PROTOTYPE;
+
+//! Buffer manager
+struct GBUFFER_MANAGER_DATA
+{
+    GDYNAMIC_ARRAY m_buffer_array;//!< Array of GBUFFER_DATA objects
+    GDYNAMIC_ARRAY m_free_positions;//!< Array of GUINT elements. Free positions
+    GBUFFER_MANAGER_PROTOTYPE m_prototype;//! Prototype of functions
+    GUINT m_active; //!< 0 or 1
+};
+//typedef  struct _GBUFFER_MANAGER_DATA GBUFFER_MANAGER_DATA;
+
+//! Adds a buffer Manager to the Memory Singleton
+void gim_create_buffer_manager(GBUFFER_MANAGER_PROTOTYPE * prototype,GUINT buffer_manager_id);
+//! Gets buffer manager
+GUINT gim_get_buffer_manager_count();
+//! Destroys a buffer manager
+void gim_destroy_buffer_manager(GUINT buffer_manager_id);
+void gim_get_buffer_manager_data(GUINT buffer_manager_id,GBUFFER_MANAGER_DATA ** pbm_data);
+void gim_init_buffer_managers();
+void gim_terminate_buffer_managers();
+
+//! @}
+
+
+/*! \addtogroup BUFFERS
+*/
+//! @{
+
+//!Creates a buffer on the buffer manager specified by buffer_manager_id
+/*!
+\param buffer_manager_id
+\param buffer_size
+\param usage An usage constant. Use G_MU_DYNAMIC_READ_WRITE as default.
+\param buffer_id a pointer for receive the new buffer id
+\return An error code. 0 if success.
+\post m_refcount = 0
+*/
+GUINT gim_create_buffer(
+    GUINT buffer_manager_id,
+    GUINT buffer_size,
+    int usage,
+    GBUFFER_ID * buffer_id);
+
+//!Creates a buffer on the buffer manager specified by buffer_manager_id
+/*!
+\param buffer_manager_id
+\param pdata Data for allocating
+\param buffer_size Size of the data buffer
+\param usage An usage constant. Use G_MU_DYNAMIC_READ_WRITE as default.
+\param buffer_id a pointer for receive the new buffer id
+\return An error code. 0 if success.
+\post m_refcount = 0
+*/
+GUINT gim_create_buffer_from_data(
+    GUINT buffer_manager_id,
+    const void * pdata,
+    GUINT buffer_size,
+    int usage,
+    GBUFFER_ID * buffer_id);
+
+//!Allocates on the G_BUFFER_MANAGER_SYSTEM
+GUINT gim_create_common_buffer(GUINT buffer_size, GBUFFER_ID * buffer_id);
+//!Allocates on the G_BUFFER_MANAGER_SYSTEM, and copies the data
+GUINT gim_create_common_buffer_from_data(
+    const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id);
+//!Creates a buffer with shared data
+GUINT gim_create_shared_buffer_from_data(
+    const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id);
+
+
+//! Add reference counting to buffer.
+GINT gim_buffer_add_ref(GBUFFER_ID * buffer_id);
+
+//! Function for resize buffer, preserving the content
+/*!
+\param buffer_id
+\param newsize
+\return An error code. 0 if success.
+\post If m_refcount>0 then it decrements it.
+*/
+GINT gim_buffer_realloc(GBUFFER_ID * buffer_id,GUINT newsize);
+
+//! Eliminates the buffer.
+/*!
+If the buffer reference counting is <= 1 and is unlocked, then it eliminates the buffer.
+*/
+GINT gim_buffer_free(GBUFFER_ID * buffer_id);
+
+//! Locks the buffer for memory access.
+/*!
+\param buffer_id Id from buffer.
+\param access Must have the following values: G_MA_READ_ONLY,G_MA_WRITE_ONLY or G_MA_READ_WRITE.
+\param map_pointer Dest Pointer of the memory address from buffer.
+\post m_lock_count increases.
+*/
+GINT gim_lock_buffer(GBUFFER_ID * buffer_id,int access,char ** map_pointer);
+
+//! Unlocks the buffer for memory access.
+GINT gim_unlock_buffer(GBUFFER_ID * buffer_id);
+
+//! Gets the buffer size in bytes
+GINT gim_get_buffer_size(GBUFFER_ID * buffer_id,GUINT * buffer_size);
+
+//! Determines if the buffer is locked
+GINT gim_get_buffer_is_locked(GBUFFER_ID * buffer_id,GUINT * lock_count);
+
+//! Copies the content of the buffer to a dest pointer
+GINT gim_download_from_buffer(
+        GBUFFER_ID * buffer_id,
+		GUINT source_pos,
+		void * destdata,
+		GUINT copysize);
+
+//! Copies the content of a memory pointer to the buffer
+GINT  gim_upload_to_buffer(
+		GBUFFER_ID * buffer_id,
+		GUINT dest_pos,
+		void * sourcedata,
+		GUINT copysize);
+
+//! Copies two buffers.
+GINT  gim_copy_buffers(
+		GBUFFER_ID * source_buffer_id,
+		GUINT source_pos,
+		GBUFFER_ID * dest_buffer_id,
+		GUINT dest_pos,
+		GUINT copysize);
+//! @}
+
+
+/*! \defgroup BUFFER_ARRAYS
+
+\brief
+Buffered Arrays, for manip elements on a buffer and treat it as an array.
+<ul>
+<li> Before using buffer arrays you must initializes GIMPACT buffer managers by calling gimpact_init.
+<li> Before creating buffer arrays, you must create a buffer. see \ref BUFFERS.
+<li> Create a buffer narray by calling \ref GIM_BUFFER_ARRAY_INIT_TYPE, \ref GIM_BUFFER_ARRAY_INIT_TYPE_OFFSET or \ref GIM_BUFFER_ARRAY_INIT_OFFSET_STRIDE.
+<li> For accessing to the array elements, you must call \ref gim_buffer_array_lock, and then \ref gim_buffer_array_unlock for finish the access.
+<li> When a buffer array is no longer needed, you must free it by calling \ref GIM_BUFFER_ARRAY_DESTROY.
+</ul>
+The following example shows how Buffer arrays can be used:
+
+\code
+int main()
+{
+    //init gimpact
+    gimpact_init();
+
+    //Buffer handle to use
+    GBUFFER_ID bufferhandle;
+
+    //Create a memory buffer of 100 float numbers
+    gim_create_common_buffer(100*sizeof(float), &bufferhandle);
+
+    //Create a buffer array from the bufferhandle
+    GBUFFER_ARRAY buffer_float_array;
+    GIM_BUFFER_ARRAY_INIT_TYPE(float,buffer_float_array,bufferhandle,100);
+
+    ////Access to the buffer data, set all elements of the array
+
+    int i, count;
+    count = buffer_float_array.m_element_count;
+    //Locks the array
+    gim_buffer_array_lock(&buffer_float_array,G_MA_READ_WRITE);
+    float  * pelements = GIM_BUFFER_ARRAY_POINTER(float, buffer_float_array, 0); // A pointer to the buffer memory
+
+    //fill the array with random numbers
+    for (i = 0;i < count;i++ )
+    {
+        pelements[i] = gim_unit_random();
+    }
+    //unlock buffer
+    gim_buffer_array_unlock(&buffer_float_array);
+
+    //Program code
+        ....
+        ....
+
+    //Destroy array
+    GIM_BUFFER_ARRAY_DESTROY(buffer_float_array);
+
+    //terminate gimpact
+    gimpact_terminate();
+}
+\endcode
+
+\sa BUFFERS
+*/
+//! @{
+
+//! Buffer managed array struct.
+struct GBUFFER_ARRAY
+{
+  GBUFFER_ID m_buffer_id;
+  char * m_buffer_data;
+  char m_byte_stride;
+  GUINT m_byte_offset;
+  GUINT m_element_count;
+};
+//typedef  struct _GBUFFER_ARRAY GBUFFER_ARRAY;
+
+//! Sets offset for a buffered array.
+#define GIM_BUFFER_ARRAY_SET_OFFSET(_array_data,_offset) (_array_data).m_byte_offset = _offset*(_array_data).m_byte_stride;
+
+//! Sets offset for a buffered array.
+#define GIM_BUFFER_ARRAY_GET_OFFSET(_array_data,_offset) _offset = (_array_data).m_byte_offset/(_array_data).m_byte_stride;
+
+//!Return a pointer of the element at the _index
+#define GIM_BUFFER_ARRAY_POINTER(_type,_array_data,_index) (_type *)((_array_data).m_buffer_data + _index*(_array_data).m_byte_stride)
+
+//! Sets stride for a buffered array.
+#define GIM_BUFFER_ARRAY_SET_STRIDE(_type,_array_data) (_array_data).m_byte_stride = sizeof(_type);
+
+//! Is array stride equal to the size of the type ?
+#define GIM_BUFFER_ARRAY_IS_ALIGNED(_type,_array_data) ((_array_data).m_byte_stride == sizeof(_type))
+
+///Verify if two arrays have the same data
+#define GIM_BUFFER_ARRAY_ARE_SAME(_array_data1,_array_data2,aresame)\
+{\
+    aresame = 1;\
+    if((_array_data1).m_buffer_id.m_buffer_id != (_array_data2).m_buffer_id.m_buffer_id || (_array_data1).m_buffer_id.m_buffer_manager_id != (_array_data2).m_buffer_id.m_buffer_manager_id || (_array_data1).m_byte_offset != (_array_data2).m_byte_offset)\
+    {\
+        aresame = 0;\
+    }\
+}\
+
+//! Reserve size for a buffered array.
+/*!
+\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
+*/
+#define GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,reserve_size)\
+{ \
+    if(reserve_size>(array_data).m_element_count)\
+    {\
+        GUINT _buffer_size,_newarray_size;\
+        gim_get_buffer_size(&(array_data).m_buffer_id,_buffer_size);\
+        _newarray_size = reserve_size*(array_data).m_byte_stride;\
+        if(_newarray_size>_buffer_size)\
+        { \
+            _newarray_size += G_ARRAY_GROW_SIZE*(array_data).m_byte_stride;\
+            gim_buffer_realloc(&(array_data).m_buffer_id,_newarray_size);\
+        }\
+    }\
+}\
+
+//! Pushes an element at last position
+/*!
+\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
+*/
+#define GIM_BUFFER_ARRAY_PUSH_ITEM(type,array_data,item)\
+{\
+    GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,(array_data).m_element_count+1);\
+    gim_buffer_array_lock(&array_data,G_MA_WRITE_ONLY);\
+    type * _pt = GIM_BUFFER_ARRAY_POINTER(type,array_data,(array_data).m_element_count);\
+    memcpy(_pt,&item,sizeof(type));\
+    gim_buffer_array_unlock(&array_data);\
+    (array_data)->m_element_count++; \
+}\
+
+//! Pushes a new element at last position
+/*!
+\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
+*/
+#define GIM_BUFFER_ARRAY_PUSH_EMPTY(type,array_data)\
+{\
+    GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,(array_data).m_element_count+1);\
+    array_data->m_element_count++; \
+}\
+
+//! Inserts an element
+/*!
+\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
+*/
+#define GIM_BUFFER_ARRAY_INSERT_ITEM(type,array_data,item,index) \
+{ \
+    GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,(array_data).m_element_count+1);\
+    gim_buffer_array_lock(&array_data,G_MA_WRITE_ONLY);\
+    type * _pt = GIM_BUFFER_ARRAY_POINTER(type,array_data,0);\
+    if(index<(array_data)->m_element_count-1) \
+    { \
+        memcpy(&_pt[index+1],&_pt[index],((array_data).m_element_count-index)*sizeof(type));\
+    } \
+    memcpy(&_pt[index],&item,sizeof(type));\
+    gim_buffer_array_unlock(&array_data);\
+    (array_data).m_element_count++; \
+}\
+
+//! Deletes an element
+/*!
+\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
+*/
+#define GIM_BUFFER_ARRAY_DELETE_ITEM(type,array_data,index) \
+{ \
+    if(index<(array_data).m_element_count-1) \
+    { \
+        gim_buffer_array_lock(&array_data,G_MA_WRITE_ONLY);\
+        type * _pt = GIM_BUFFER_ARRAY_POINTER(type,array_data,0);\
+        memcpy(&_pt[index],&_pt[index+1],((array_data).m_element_count-index-1)*sizeof(type));\
+        gim_buffer_array_unlock(&array_data);\
+    } \
+    (array_data).m_element_count--;    \
+}\
+
+//! Deletes an element at last position
+/*!
+\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
+*/
+#define GIM_BUFFER_ARRAY_POP_ITEM(array_data) \
+{ \
+    if((array_data).m_element_count>0) \
+    { \
+        (array_data).m_element_count--;    \
+    } \
+}\
+
+
+//! Initializes an GBUFFER_ARRAY object from a buffer ID
+/*!
+m_buffer_data will be 0, for acces to the elements, you'd need to call lock_array
+\param array_data Array structure to be filled
+\param buffer_id A GBUFFER_ID structure which this array_daya will refer to
+\param element_count Number of elements
+\param offset element offset, it isn't byte offset. 0 is recomended
+\param byte_stride size of each element.  0 is recomended.
+\post Adds reference to the buffer
+\sa gim_buffer_add_ref
+*/
+#define GIM_BUFFER_ARRAY_INIT_OFFSET_STRIDE(array_data,buffer_id,element_count,offset,byte_stride)\
+{\
+    (array_data).m_buffer_id.m_buffer_id = (buffer_id).m_buffer_id;\
+    (array_data).m_buffer_id.m_buffer_manager_id = (buffer_id).m_buffer_manager_id;\
+    (array_data).m_buffer_data = 0;\
+    (array_data).m_element_count = element_count;\
+    (array_data).m_byte_stride = byte_stride;\
+    GIM_BUFFER_ARRAY_SET_OFFSET(array_data,offset);\
+    gim_buffer_add_ref(&(buffer_id));\
+}\
+
+//! Initializes an GBUFFER_ARRAY object from a buffer ID and a Given type
+/*!
+m_buffer_data will be 0, for acces to the elements, you'd need to call lock_array
+\param type Type of the Array. It determines the stride.
+\param array_data Array structure to be filled
+\param buffer_id A GBUFFER_ID structure which this array_daya will refer to
+\param element_count Number of elements
+\param offset element offset, it isn't byte offset. 0 is recomended
+\post Adds reference to the buffer
+\sa gim_buffer_add_ref
+*/
+#define GIM_BUFFER_ARRAY_INIT_TYPE_OFFSET(type,array_data,buffer_id,element_count,offset)\
+{\
+    (array_data).m_buffer_id.m_buffer_id = (buffer_id).m_buffer_id;\
+    (array_data).m_buffer_id.m_buffer_manager_id = (buffer_id).m_buffer_manager_id;\
+    (array_data).m_buffer_data = 0;\
+    (array_data).m_element_count = element_count;\
+    GIM_BUFFER_ARRAY_SET_STRIDE(type,array_data);\
+    GIM_BUFFER_ARRAY_SET_OFFSET(array_data,offset);\
+    gim_buffer_add_ref(&(buffer_id));\
+}\
+
+//! Initializes a buffer array giving a data type and a buffer id
+/*!
+m_buffer_data will be 0, for acces to the elements, you'd need to call lock_array.
+\param type Type of the Array. It determines the stride.
+\param array_data Array structure to be filled
+\param buffer_id A GBUFFER_ID structure which this array_daya will refer to
+\param element_count Number of elements
+\post Adds reference to the buffer
+\sa gim_buffer_add_ref
+*/
+#define GIM_BUFFER_ARRAY_INIT_TYPE(type,array_data,buffer_id,element_count) GIM_BUFFER_ARRAY_INIT_TYPE_OFFSET(type,array_data,buffer_id,element_count,0)
+
+//! Gain access to the array buffer through the m_buffer_data element
+/*!
+m_buffer_data pointer will be located at the m_byte_offset position of the buffer m_buffer
+Then, You'd need to call unlock_array when finish to using the array access.
+
+\pre if m_buffer_data != 0, the function returns
+\param array_data Array structure to be locked
+\param access A constant for access to the buffer. can be G_MA_READ_ONLY,G_MA_WRITE_ONLY or G_MA_READ_WRITE
+\return an Buffer error code
+*/
+GINT gim_buffer_array_lock(GBUFFER_ARRAY * array_data, int access);
+
+//! close the access to the array buffer through the m_buffer_data element
+/*!
+\param array_data Array structure to be locked
+\return an Buffer error code
+*/
+GINT gim_buffer_array_unlock(GBUFFER_ARRAY * array_data);
+
+//! Copy an array by reference
+/*!
+\post A reference to the m_buffer_id is increased.
+*/
+void gim_buffer_array_copy_ref(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY  * dest_data);
+
+
+//! Copy an array by value
+/*!
+\post A new buffer is created
+*/
+void gim_buffer_array_copy_value(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY  * dest_data, GUINT buffer_manager_id,int usage);
+
+//! Destroys an GBUFFER_ARRAY object
+/*!
+\post Attemps to destroy the buffer, decreases reference counting
+*/
+void GIM_BUFFER_ARRAY_DESTROY(GBUFFER_ARRAY & array_data);
+
+//! Copy the content of the array to a pointer
+/*!
+\pre dest_data must have the same size as the array_data
+\param type
+\param array_data A GBUFFERED_ARRAY structure
+\param dest_data A type pointer
+*/
+#define GIM_BUFFER_ARRAY_DOWNLOAD(type,array_data,dest_data)\
+{\
+    if(GIM_BUFFER_ARRAY_IS_ALIGNED(type,array_data))\
+    {\
+        gim_download_from_buffer(&(array_data).m_buffer_id, (array_data).m_byte_offset,(void *) dest_data, (array_data).m_element_count*(array_data).m_byte_stride);\
+    }\
+    else\
+    {\
+        GUINT _k_, _ecount_= (array_data).m_element_count;\
+        type * _source_vert_;\
+        type * _dest_vert_ = dest_data;\
+        gim_buffer_array_lock(&(array_data),G_MA_READ_ONLY);\
+        for (_k_ = 0;_k_< _ecount_; _k_++)\
+        {\
+            _source_vert_ = GIM_BUFFER_ARRAY_POINTER(type,array_data,_k_);\
+            memcpy(_dest_vert_,_source_vert_,sizeof(type));\
+            _dest_vert_++;\
+        }\
+        gim_buffer_array_unlock(&(array_data));\
+    }\
+}\
+
+//! Upload the content of a a pointer to a buffered array
+/*!
+\pre source_data must have the same size as the array_data
+\param type
+\param array_data A GBUFFERED_ARRAY structure
+\param source_data A void pointer
+*/
+#define GIM_BUFFER_ARRAY_UPLOAD(type,array_data,source_data)\
+{\
+    if(GIM_BUFFER_ARRAY_IS_ALIGNED(type,array_data))\
+    {\
+        gim_upload_to_buffer(&(array_data).m_buffer_id, (array_data).m_byte_offset,(void *) source_data, (array_data).m_element_count*(array_data).m_byte_stride);\
+    }\
+    else\
+    {\
+        GUINT _k_, _ecount_= (array_data).m_element_count;\
+        type * _source_vert_ = source_data;\
+        type * _dest_vert_;\
+        gim_buffer_array_lock(&(array_data),G_MA_WRITE_ONLY);\
+        for (_k_ = 0;_k_< _ecount_; _k_++)\
+        {\
+            _dest_vert_ = GIM_BUFFER_ARRAY_POINTER(type,array_data,_k_);\
+            memcpy(_dest_vert_,_source_vert_,sizeof(type));\
+            _source_vert_++;\
+        }\
+        gim_buffer_array_unlock(&(array_data));\
+    }\
+}\
+
+
+//!Kernel function prototype for process streams, given a buffered array as source and
+/*!
+\param 1 the uniform arguments
+\param 2 the source stream
+\param 3 the destination stream
+*/
+typedef void (* gim_kernel_func)(void *,GBUFFER_ARRAY *,GBUFFER_ARRAY *);
+
+//! Generic Stream Processingp loop
+/*!
+
+This macro executes a kernel macro or function for each element of the streams
+\pre _src_array->m_count <= _dst_array->m_count
+
+\param _uniform_data An argument to be passed to the Kernel function
+\param _src_array An GBUFFER_ARRAY structure passed as the source stream
+\param _dst_array An GBUFFER_ARRAY  structure passed as the source stream
+\param _kernel Macro or function of the kernel
+\param _src_type Required. Type of all elements of the source stream
+\param _dst_type Required. Type of all elements of the dest stream
+*/
+#define GIM_PROCESS_BUFFER_ARRAY(_uniform_data,_src_array,_dst_array,_kernel,_src_type,_dst_type) {\
+\
+    gim_buffer_array_lock(&_src_array,G_MA_READ_ONLY);\
+    gim_buffer_array_lock(&_dst_array,G_MA_WRITE_ONLY);\
+\
+    GUINT _i_, _count_=(_src_array).m_element_count;\
+\
+    _src_type * _source_vert_;\
+    _dst_type * _dest_vert_;\
+    if(GIM_BUFFER_ARRAY_IS_ALIGNED(_src_type,_src_array) && GIM_BUFFER_ARRAY_IS_ALIGNED(_dst_type,_dst_array))\
+    {\
+\
+        _source_vert_ = GIM_BUFFER_ARRAY_POINTER(_src_type,_src_array,0);\
+        _dest_vert_ = GIM_BUFFER_ARRAY_POINTER(_dst_type,_dst_array,0);\
+        for (_i_ = 0;_i_< _count_; _i_++)\
+        {\
+            _kernel(_uniform_data,(*_source_vert_),(*_dest_vert_));\
+            _source_vert_++;\
+            _dest_vert_++;\
+        }\
+    }\
+    else\
+    {\
+        for (_i_ = 0;_i_< _count_; _i_++)\
+        {\
+            _source_vert_ = GIM_BUFFER_ARRAY_POINTER(_src_type,_src_array,_i_);\
+            _dest_vert_ = GIM_BUFFER_ARRAY_POINTER(_dst_type,_dst_array,_i_);\
+            _kernel(_uniform_data,(*_source_vert_),(*_dest_vert_));\
+        }\
+    }\
+    gim_buffer_array_unlock(&_src_array);\
+    gim_buffer_array_unlock(&_dst_array);\
+}\
+
+//! @}
+
+#endif // GIM_MEMORY_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_radixsort.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_radixsort.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_radixsort.h	(revision 216)
@@ -0,0 +1,258 @@
+#ifndef GIM_RADIXSORT_H_INCLUDED
+#define GIM_RADIXSORT_H_INCLUDED
+/*! \file gim_radixsort.h
+\author Francisco León.
+Based on the work of Michael Herf : "fast floating-point radix sort"
+Avaliable on http://www.stereopsis.com/radix.html
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_memory.h"
+
+/*! \defgroup SORTING
+\brief
+Macros for sorting.
+*/
+//! @{
+struct GIM_RSORT_TOKEN
+{
+    GUINT m_key;
+    GUINT m_value;
+};
+//typedef struct _GIM_RSORT_TOKEN GIM_RSORT_TOKEN;
+
+//comparator for sorting
+#define RSORT_TOKEN_COMPARATOR(x, y) ((int)((x.m_key) - (y.m_key)))
+
+// ---- utils for accessing 11-bit quantities
+#define D11_0(x)	(x & 0x7FF)
+#define D11_1(x)	(x >> 11 & 0x7FF)
+#define D11_2(x)	(x >> 22 )
+
+
+//COMMON FUNCTIONS FOR ACCESSING THE KEY OF AN ELEMENT
+
+
+//For the type of your array, you need to declare a macro for obtaining the key, like these:
+#define SIMPLE_GET_FLOAT32KEY(e,key) {key =(GREAL)(e);}
+
+#define SIMPLE_GET_INTKEY(e,key) {key =(GINT)(e);}
+
+#define SIMPLE_GET_UINTKEY(e,key) {key =(GUINT)(e);}
+
+//For the type of your array, you need to declare a macro for copy elements, like this:
+
+#define SIMPLE_COPY_ELEMENTS(dest,src) {dest = src;}
+
+#define kHist 2048
+
+///Radix sort for unsigned integer keys
+
+#define GIM_RADIX_SORT_RTOKENS(array,sorted,element_count)\
+{\
+	GUINT i;\
+	GUINT b0[kHist * 3];\
+	GUINT *b1 = b0 + kHist;\
+	GUINT *b2 = b1 + kHist;\
+	for (i = 0; i < kHist * 3; i++)\
+	{\
+		b0[i] = 0;\
+	}\
+	GUINT fi;\
+	GUINT pos;\
+	for (i = 0; i < element_count; i++)\
+	{\
+	    fi = array[i].m_key;\
+		b0[D11_0(fi)] ++;\
+		b1[D11_1(fi)] ++;\
+		b2[D11_2(fi)] ++;\
+	}\
+	{\
+		GUINT sum0 = 0, sum1 = 0, sum2 = 0;\
+		GUINT tsum;\
+		for (i = 0; i < kHist; i++)\
+		{\
+			tsum = b0[i] + sum0;\
+			b0[i] = sum0 - 1;\
+			sum0 = tsum;\
+			tsum = b1[i] + sum1;\
+			b1[i] = sum1 - 1;\
+			sum1 = tsum;\
+			tsum = b2[i] + sum2;\
+			b2[i] = sum2 - 1;\
+			sum2 = tsum;\
+		}\
+	}\
+	for (i = 0; i < element_count; i++)\
+	{\
+        fi = array[i].m_key;\
+		pos = D11_0(fi);\
+		pos = ++b0[pos];\
+		sorted[pos].m_key = array[i].m_key;\
+		sorted[pos].m_value = array[i].m_value;\
+	}\
+	for (i = 0; i < element_count; i++)\
+	{\
+        fi = sorted[i].m_key;\
+		pos = D11_1(fi);\
+		pos = ++b1[pos];\
+		array[pos].m_key = sorted[i].m_key;\
+		array[pos].m_value = sorted[i].m_value;\
+	}\
+	for (i = 0; i < element_count; i++)\
+	{\
+        fi = array[i].m_key;\
+		pos = D11_2(fi);\
+		pos = ++b2[pos];\
+		sorted[pos].m_key = array[i].m_key;\
+		sorted[pos].m_value = array[i].m_value;\
+	}\
+}\
+
+/// Get the sorted tokens from an array. For generic use. Tokens are GIM_RSORT_TOKEN
+#define GIM_RADIX_SORT_ARRAY_TOKENS(array, sorted_tokens, element_count, get_uintkey_macro)\
+{\
+    GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN )*element_count);\
+    GUINT _i;\
+    for (_i=0;_i<element_count;_i++)\
+    {\
+        get_uintkey_macro(array[_i],_unsorted[_i].m_key);\
+        _unsorted[_i].m_value = _i;\
+    }\
+    GIM_RADIX_SORT_RTOKENS(_unsorted,sorted_tokens,element_count);\
+    gim_free(_unsorted,sizeof(GIM_RSORT_TOKEN )*element_count);\
+}\
+
+/// Sorts array in place. For generic use
+#define GIM_RADIX_SORT(type,array,element_count,get_uintkey_macro,copy_elements_macro)\
+{\
+    GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN )*element_count);\
+    GIM_RADIX_SORT_ARRAY_TOKENS(array,_sorted,element_count,get_uintkey_macro);\
+    type * _original_array = (type *) gim_alloc(sizeof(type)*element_count); \
+    memcpy(_original_array,array,sizeof(type)*element_count);\
+    GUINT _i;\
+    for (_i=0;_i<element_count;_i++)\
+    {\
+        copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);\
+    }\
+    gim_free(_original_array,sizeof(type)*element_count);\
+    gim_free(_sorted,sizeof(GIM_RSORT_TOKEN )*element_count);\
+}\
+
+/// Sorts array in place using quick sort
+#define GIM_QUICK_SORT_ARRAY(type, array, array_count, comp_macro, exchange_macro) \
+{\
+  GINT   _i_, _j_, _p_, _stack_index_, _start_, _end_;\
+  GINT   _start_stack_[64]; \
+  GINT   _end_stack_[64];\
+  _start_stack_[0] = 0;\
+  _end_stack_[0] = (array_count);\
+  _stack_index_ = 1;\
+  while (_stack_index_ > 0)\
+  {\
+    _stack_index_ --;\
+    _start_ = _start_stack_[_stack_index_];\
+    _end_ = _end_stack_[_stack_index_];\
+    while (_end_ - _start_ > 2)\
+    {\
+      _p_ = _start_;\
+      _i_ = _start_ + 1;\
+      _j_ = _end_ - 1;\
+      while (_i_<_j_) \
+      {\
+        for(; _i_<=_j_ && comp_macro(((array)[_i_]),((array)[_p_]))<=0; _i_++) ;\
+        if (_i_ > _j_) \
+        {\
+          exchange_macro(type, array, _j_, _p_);\
+          _i_ = _j_;\
+        }\
+        else\
+        {\
+          for(; _i_<=_j_ && comp_macro(((array)[_j_]),((array)[_p_]))>=0; _j_--) ;\
+          if (_i_ > _j_) \
+          {\
+            exchange_macro(type, array, _j_, _p_);\
+            _i_ = _j_;\
+          }\
+          else if (_i_ < _j_)\
+          {\
+            exchange_macro(type, array, _i_, _j_);\
+            if (_i_+2 < _j_) {_i_++; _j_--;}\
+            else if (_i_+1 < _j_) _i_++;\
+          }\
+        }\
+      }\
+      if (_i_-_start_ > 1 && _end_-_j_ > 1) \
+      {\
+        if (_i_-_start_ < _end_-_j_-1) \
+        {\
+          _start_stack_[_stack_index_] = _j_+1;\
+          _end_stack_[_stack_index_] = _end_;\
+          _stack_index_ ++;\
+          _end_ = _i_;\
+        }\
+        else\
+        {\
+          _start_stack_[_stack_index_] = _start_;\
+          _end_stack_[_stack_index_] = _i_;\
+          _stack_index_ ++;\
+          _start_ = _j_+1;\
+        }\
+      }\
+      else\
+      {\
+        if (_i_-_start_ > 1)\
+        {\
+          _end_ = _i_;\
+        }\
+        else \
+        {\
+          _start_ = _j_+1;\
+        }\
+      }\
+    }\
+    if (_end_ - _start_ == 2) \
+    {\
+      if (comp_macro(((array)[_start_]),((array)[_end_-1])) > 0) \
+      {\
+        exchange_macro(type, array, _start_, _end_-1);\
+      }\
+    }\
+  }\
+}\
+
+#define GIM_DEF_EXCHANGE_MACRO(type, _array, _i, _j)\
+{\
+    type _e_tmp_ =(_array)[(_i)];\
+    (_array)[(_i)]=(_array)[(_j)];\
+    (_array)[(_j)]= _e_tmp_;\
+}\
+
+#define GIM_COMP_MACRO(x, y) ((GINT)((x) - (y)))
+//! @}
+#endif // GIM_RADIXSORT_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_capsule_collision.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_capsule_collision.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_capsule_collision.h	(revision 216)
@@ -0,0 +1,111 @@
+#ifndef GIM_TRI_CAPSULE_COLLISION_H_INCLUDED
+#define GIM_TRI_CAPSULE_COLLISION_H_INCLUDED
+
+/*! \file gim_tri_capsule_collision.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_memory.h"
+
+/*! \addtogroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+//! Capsule struct
+struct GIM_CAPSULE_DATA
+{
+    GREAL m_radius;
+    vec3f m_point1;
+    vec3f m_point2;
+};
+//typedef struct _GIM_CAPSULE_DATA GIM_CAPSULE_DATA;
+
+#define CALC_CAPSULE_AABB(capsule,aabb)\
+{\
+    if(capsule.m_point1[0]<capsule.m_point2[0])\
+    {\
+        aabb.minX = capsule.m_point1[0] - capsule.m_radius;\
+        aabb.maxX = capsule.m_point2[0] + capsule.m_radius;\
+    }\
+    else\
+    {\
+        aabb.minX = capsule.m_point2[0] - capsule.m_radius;\
+        aabb.maxX = capsule.m_point1[0] + capsule.m_radius;\
+    }\
+    if(capsule.m_point1[1]<capsule.m_point2[1])\
+    {\
+        aabb.minY = capsule.m_point1[1] - capsule.m_radius;\
+        aabb.maxY = capsule.m_point2[1] + capsule.m_radius;\
+    }\
+    else\
+    {\
+        aabb.minY = capsule.m_point2[1] - capsule.m_radius;\
+        aabb.maxY = capsule.m_point1[1] + capsule.m_radius;\
+    }\
+    if(capsule.m_point1[2]<capsule.m_point2[2])\
+    {\
+        aabb.minZ = capsule.m_point1[2] - capsule.m_radius;\
+        aabb.maxZ = capsule.m_point2[2] + capsule.m_radius;\
+    }\
+    else\
+    {\
+        aabb.minZ = capsule.m_point2[2] - capsule.m_radius;\
+        aabb.maxZ = capsule.m_point1[2] + capsule.m_radius;\
+    }\
+}\
+
+//! Utility function for find the closest point between a segment and a triangle
+/*!
+
+\param triangle
+\param s1
+\param s2
+\param contacts Contains the closest points on the segment (1,2), and the normal points to segment, and m_depth contains the distance
+
+\post The contacts array is not set to 0. It adds aditional contacts
+*/
+void gim_closest_point_triangle_segment(GIM_TRIANGLE_DATA * triangle, vec3f s1,vec3f s2, GDYNAMIC_ARRAY * contacts);
+
+
+
+
+
+//! Utility function for find the closest point between a capsule and a triangle
+/*!
+
+\param triangle
+\param capsule
+\param contacts Contains the closest points on the capsule, and the normal points to triangle
+\return 1 if the triangle collides the capsule
+\post The contacts array is not set to 0. It adds aditional contacts
+*/
+int gim_triangle_capsule_collision(GIM_TRIANGLE_DATA * triangle, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts);
+//! @}
+
+#endif // GIM_TRI_CAPSULE_COLLISION_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_collision.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_collision.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_collision.h	(revision 216)
@@ -0,0 +1,253 @@
+#ifndef GIM_TRI_COLLISION_H_INCLUDED
+#define GIM_TRI_COLLISION_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco León Nájera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+/*! \addtogroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+
+#define MAX_TRI_CLIPPING 8
+
+//! Clips a polygon by a plane
+#define PLANE_CLIP_POLYGON(plane,polygon_points,polygon_point_count,clipped,clipped_count,max_clipped) \
+{ \
+    clipped_count = 0; \
+    GUINT  _i, _vi, _prevclassif=32000, _classif; \
+	GREAL _d; \
+	for(_i=0;_i<=polygon_point_count;_i++) \
+	{ \
+		_vi = _i%polygon_point_count; \
+		_d = DISTANCE_PLANE_POINT(plane,polygon_points[_vi]); \
+		_classif = _d>G_EPSILON ?1:0; \
+		if(_classif == 0) \
+		{ \
+			if(_prevclassif==1) \
+			{\
+				if(clipped_count<max_clipped) \
+				{\
+                    PLANE_CLIP_SEGMENT(polygon_points[_i-1],polygon_points[_vi],plane,clipped[clipped_count]); \
+                    clipped_count++; \
+                } \
+            } \
+			if(clipped_count<max_clipped&&_i<polygon_point_count) \
+			{ \
+			    VEC_COPY(clipped[clipped_count],polygon_points[_vi]); \
+				clipped_count++; \
+			} \
+		} \
+		else \
+		{ \
+            if(_prevclassif==0) \
+            { \
+                if(clipped_count<max_clipped) \
+                { \
+                    PLANE_CLIP_SEGMENT(polygon_points[_i-1],polygon_points[_vi],plane,clipped[clipped_count]); \
+                    clipped_count++; \
+                } \
+            } \
+		} \
+		_prevclassif = _classif; \
+	} \
+}\
+
+
+struct GIM_TRIPLANES_CACHE
+{
+    /*!
+    Planes are:
+    0 : Face normal plane (0,3)
+    1 : Edge 1 plane (4,7)
+    2 : Edge 2 plane (8,11)
+    3 : Edge 3 plane (12,15)
+    */
+    vec4f m_planes[4];
+};
+//typedef struct _GIM_TRIPLANES_CACHE GIM_TRIPLANES_CACHE;
+
+
+struct GIM_TRIANGLE_DATA
+{
+    vec3f m_vertices[3];
+    GIM_TRIPLANES_CACHE m_planes;
+};
+//typedef struct _GIM_TRIANGLE_DATA GIM_TRIANGLE_DATA;
+
+//! tri_data is a GIM_TRIANGLE_DATA
+#define GIM_CALC_TRIANGLE_DATA_PLANES(tri_data)\
+{\
+        TRIANGLE_PLANE((tri_data).m_vertices[0],(tri_data).m_vertices[1],(tri_data).m_vertices[2],(tri_data).m_planes.m_planes[0]);\
+        EDGE_PLANE((tri_data).m_vertices[0],(tri_data).m_vertices[1],((tri_data).m_planes.m_planes[0]),((tri_data).m_planes.m_planes[1]));\
+        EDGE_PLANE((tri_data).m_vertices[1],(tri_data).m_vertices[2],((tri_data).m_planes.m_planes[0]),((tri_data).m_planes.m_planes[2]));\
+        EDGE_PLANE((tri_data).m_vertices[2],(tri_data).m_vertices[0],((tri_data).m_planes.m_planes[0]), ((tri_data).m_planes.m_planes[3]));\
+}\
+
+//Structure for collision
+
+struct GIM_TRIANGLE_CONTACT_DATA
+{
+    GREAL m_penetration_depth;
+    GUINT m_point_count;
+    vec3f m_separating_normal;
+    vec3f m_points[MAX_TRI_CLIPPING];
+};
+//typedef struct _GIM_TRIANGLE_CONTACT_DATA GIM_TRIANGLE_CONTACT_DATA;
+
+struct GIM_TRIANGLE_RAY_CONTACT_DATA
+{
+    GREAL u;
+    GREAL v;
+    GREAL tparam;
+    GUINT m_face_id;
+    vec3f m_point;
+    vec3f m_normal;
+};
+//typedef struct _GIM_TRIANGLE_RAY_CONTACT_DATA GIM_TRIANGLE_RAY_CONTACT_DATA;
+
+//! Fast Triangle Triangle overlapping test
+int gim_triangle_triangle_overlap(
+							GIM_TRIANGLE_DATA *tri1,
+							GIM_TRIANGLE_DATA *tri2);
+
+
+//! Fast but inacurate conservative Triangle Triangle overlapping test
+int gim_triangle_triangle_overlap_fast(
+							GIM_TRIANGLE_DATA *tri1,
+							GIM_TRIANGLE_DATA *tri2);
+
+
+//! Finds the contact points from a collision of two triangles
+/*!
+Returns the contact points, the penetration depth and the separating normal of the collision
+between two triangles. The normal is pointing toward triangle 1 from triangle 2
+*/
+int gim_triangle_triangle_collision(
+							GIM_TRIANGLE_DATA *tri1,
+							GIM_TRIANGLE_DATA *tri2,
+							GIM_TRIANGLE_CONTACT_DATA * contact_data);
+
+//Ray triangle
+
+
+/*!
+	Solve the System for u,v parameters:
+
+	u*axe1[i1] + v*axe2[i1] = vecproj[i1]
+	u*axe1[i2] + v*axe2[i2] = vecproj[i2]
+
+	sustitute:
+	v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
+
+	then the first equation in terms of 'u':
+
+	--> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
+
+	--> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
+
+	--> u*(axe1[i1]  - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
+
+	--> u*((axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
+
+	--> u*(axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
+
+	--> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1])
+
+if 0.0<= u+v <=1.0 then they are inside of triangle
+
+	*/
+#define TRIANGLE_GET_UVPARAMETERS(point,vec1,vec2,vec3,tri_plane,u,v,outside)\
+{\
+	vec3f _axe1, _axe2, _vecproj;\
+	VEC_DIFF(_axe1,vec2,vec1);\
+	VEC_DIFF(_axe2,vec3,vec1);\
+	VEC_DIFF(_vecproj,point,vec1);\
+	GUINT _i1,_i2;\
+	PLANE_MINOR_AXES(tri_plane, _i1, _i2);\
+	if(fabsf(_axe2[_i2])<G_EPSILON)\
+	{\
+		u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1]  - _axe1[_i1]*_axe2[_i2]);\
+		v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];\
+	}\
+	else\
+	{\
+		u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2]  - _axe1[_i2]*_axe2[_i1]);\
+		v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];\
+	}\
+	if(u<-G_EPSILON)\
+	{\
+		outside = 1;\
+	}\
+	else if(v<-G_EPSILON)\
+	{\
+		outside = 1;\
+	}\
+	else\
+	{\
+		float sumuv;\
+		sumuv = u+v;\
+		if(sumuv<-G_EPSILON)\
+		{\
+			outside = 1;\
+		}\
+		else if(sumuv-1.0f>G_EPSILON)\
+		{\
+			outside = 1;\
+		}\
+		else\
+		{\
+			outside = 0;\
+		}\
+	}\
+}\
+
+//! Finds the collision of a ray and a triangle.
+#define RAY_TRIANGLE_INTERSECTION(vOrigin,vDir,vec1,vec2,vec3,tri_plane,pout,u,v,tparam,tmax,does_intersect)\
+{\
+	RAY_PLANE_COLLISION(tri_plane,vDir,vOrigin,pout,tparam,does_intersect);\
+	if(does_intersect != 0)\
+	{\
+        if(tparam<-G_EPSILON||tparam>tmax+G_EPSILON)\
+        {\
+            does_intersect = 0;\
+        }\
+        else\
+        {\
+            TRIANGLE_GET_UVPARAMETERS(pout,vec1,vec2,vec3,tri_plane,u,v,does_intersect);\
+            does_intersect = !does_intersect;\
+        }\
+	}\
+}\
+
+
+//! @}
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_sphere_collision.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_sphere_collision.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_tri_sphere_collision.h	(revision 216)
@@ -0,0 +1,51 @@
+#ifndef GIM_TRI_SPHERE_COLLISION_H_INCLUDED
+#define GIM_TRI_SPHERE_COLLISION_H_INCLUDED
+
+/*! \file gim_tri_sphere_collision.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+/*! \addtogroup GEOMETRIC_OPERATIONS
+*/
+//! @{
+
+//! Finds the contact points from a collision of a triangle and a sphere
+/*!
+\param tri
+\param center
+\param radius
+\param contact_data Contains the closest points on the Sphere, and the normal is pointing to triangle
+*/
+int gim_triangle_sphere_collision(
+							GIM_TRIANGLE_DATA *tri,
+							vec3f center, GREAL radius,
+							GIM_TRIANGLE_CONTACT_DATA * contact_data);
+
+//! @}
+#endif // GIM_TRI_SPHERE_COLLISION_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_trimesh.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_trimesh.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_trimesh.h	(revision 216)
@@ -0,0 +1,539 @@
+#ifndef GIM_TRIMESH_H_INCLUDED
+#define GIM_TRIMESH_H_INCLUDED
+/*! \file gim_trimesh.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_boxpruning.h"
+#include "GIMPACT/gim_contact.h"
+
+
+///MAsk defines
+#define GIM_TRIMESH_TRANSFORMED_REPLY 1
+#define GIM_TRIMESH_NEED_UPDATE 2
+
+/*! \addtogroup TRIMESH
+\brief
+A Trimesh is the basic geometric structure for representing solid objects.
+<p><strong>CREATING TRIMESHES</strong></p>
+<ul>
+<li> For creating trimeshes, you must initialize Buffer managers by calling \ref gimpact_init
+<li> Then you must define the vertex and index sources by creating them with \ref BUFFER_ARRAYS routines, and then call  \ref gim_trimesh_create_from_arrays.
+<li> An alternative way for creaing trimesh objects is calling  \ref gim_trimesh_create_from_data.
+<li> For access to the trimesh data (vertices, triangle indices), you must call  \ref gim_trimesh_locks_work_data , and  \ref gim_trimesh_unlocks_work_data for finish the access.
+<li> Each time when the trimesh data is modified, you must call  \ref gim_trimesh_update after.
+<li> When a trimesh is no longer needed, you must call \ref gim_trimesh_destroy.
+</ul>
+
+<p>This is an example of how to create a deformable trimesh that shares vertices with the user application:</p>
+\code
+//Declaration of vertices
+vec3f trimeshvertices[200];
+//Declaration of indices
+GUINT trimeshindices[100];
+
+... Initializing vertices and triangle indices at beginning
+
+//Then create trimesh
+GIM_TRIMESH mytrimesh;
+
+//Calling trimesh create function
+
+gim_trimesh_create_from_data(
+&mytrimesh,
+trimeshvertices,200,
+0 ,//copy_vertices is 0
+trimeshindices,
+100,
+0, //copy_indices is 0
+0 //transformed_reply is 0
+);
+\endcode
+<p>Note that parameter transformed_reply is 0, that means that m_transformed_vertex_buffer is a reference to m_source_vertex on the trimesh, and transformations are not avaliable. Use that configuration if you have to simulate a deformable trimesh like cloth or elastic bodies.</p>
+<p>When the trimesh is no longer needed, destroy it safely with gim_trimesh_destroy()</p>
+<p><strong>UPDATING TRIMESHES</strong></p>
+<p>On simulation loops, is needed to update trimeshes every time for update vertices althought updating triangle boxes and planes cache. There is two ways for update trimeshes: </p>
+<ul>
+<li> Updating vertices directly. You need to access to the \ref GIM_TRIMESH.m_source_vertex_buffer member; a vertex buffer which has access to the source vertices.
+\code
+// Access to the source vertices
+gim_buffer_array_lock(&mytrimesh.m_source_vertex_buffer, G_MA_READ_WRITE);
+
+//Get a pointer to the vertex buffer
+vec3f * vertexpointer = GIM_BUFFER_ARRAY_POINTER(vec3f,mytrimesh.m_source_vertex_buffer,0);
+
+//Get the amount of vertices
+int veccount = mytrimesh.m_source_vertex_buffer.m_element_count;
+
+//Modify vertices
+for (int i=0;i<veccount ;i++ )
+{
+    .....
+    .....
+    processing vertices
+    .....
+	.....
+}
+
+// Don't forget to unlock the source vertex array
+gim_buffer_array_unlock(&mytrimesh.m_source_vertex_buffer);
+
+// Notify that the state of the trimesh is changed
+gim_trimesh_post_update(&mytrimesh.m_source_vertex_buffer);
+
+\endcode
+For making trimeshes that allow to update their vertices, use \ref gim_trimesh_create_from_data with parameter <strong>transformed_reply</strong> = 0.
+</ul>
+<ul>
+<li> Aplying a transformation. Simply use \ref gim_trimesh_set_tranform . Remember that with this method trimeshes must be created with \ref gim_trimesh_create_from_data with parameter <strong>transformed_reply</strong> = 1.
+</ul>
+<p> After updating vertices, you must call \ref gim_trimesh_update()</p>
+<p><strong>TRIMESHES COLLISION</strong></p>
+<p>Before collide trimeshes, you need to update them first.</p>
+<p>Then you must use \ref gim_trimesh_trimesh_collision().</p>
+
+*/
+//! @{
+
+//! Prototype for updating vertices
+typedef void * gim_update_trimesh_function(struct _GIM_TRIMESH *);
+
+//! Trimesh
+struct GIM_TRIMESH
+{
+    ///Original
+    //@{
+    GBUFFER_ARRAY m_source_vertex_buffer;//!< Buffer of vec3f coordinates
+
+    //! (GUINT) Indices of triangles,groups of three elements.
+    /*!
+    Array of GUINT. Triangle indices. Each triple contains indices of the vertices for each triangle.
+    \invariant must be aligned
+    */
+    GBUFFER_ARRAY m_tri_index_buffer;
+    //@}
+    ///Allocated
+    //@{
+    char m_mask;//!< Don't use directly
+
+    //! Allocated transformed vertices vec3f
+    /*!
+    Array of vec3f.If gim_trimesh_has_tranformed_reply(this) == 1 then it refers to the m_source_vertex_buffer
+    \invariant must be aligned
+    */
+    GBUFFER_ARRAY m_transformed_vertex_buffer;
+    //@}
+    ///Auxiliary data
+    //@{
+    GIM_AABB_SET m_aabbset;
+    GDYNAMIC_ARRAY m_planes_cache_buffer;//! Allocated GIM_TRIPLANES_CACHE
+    GDYNAMIC_ARRAY m_planes_cache_bitset;
+    gim_update_trimesh_function * m_update_callback;//! If null, then m_transform is applied.
+    mat4f m_transform;
+    //@}
+};
+//typedef struct _GIM_TRIMESH GIM_TRIMESH;
+
+/// Info about mesh
+//! Return the trimesh triangle count
+GUINT gim_trimesh_get_triangle_count(GIM_TRIMESH * trimesh);
+
+//! Returns 1 if the m_transformed_vertex_buffer is a reply of m_source_vertex_buffer
+char gim_trimesh_has_tranformed_reply(GIM_TRIMESH * trimesh);
+
+//! Returns 1 if the trimesh needs to update their aabbset and the planes cache.
+char gim_trimesh_needs_update(GIM_TRIMESH * trimesh);
+
+//! Change the state of the trimesh for force it to update
+/*!
+Call it after made changes to the trimesh.
+\post gim_trimesh_need_update(trimesh) will return 1
+\sa gim_trimesh_needs_update,gim_trimesh_has_tranformed_reply
+*/
+void gim_trimesh_post_update(GIM_TRIMESH * trimesh);
+
+//! Creates the aabb set and the triangles cache
+/*!
+
+\param trimesh
+\param vertex_array
+\param triindex_array
+\param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array.
+\post it copies the arrays by reference, and creates the auxiliary data (m_aabbset,m_planes_cache_buffer)
+*/
+void gim_trimesh_create_from_arrays(GIM_TRIMESH * trimesh, GBUFFER_ARRAY * vertex_array, GBUFFER_ARRAY * triindex_array,char transformed_reply);
+
+
+
+//! Create a trimesh from vertex array and an index array
+/*!
+\param trimesh An uninitialized GIM_TRIMESH  structure
+\param vertex_array A buffer to a vec3f array
+\param vertex_count
+\param triindex_array
+\param index_count
+\param copy_vertices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data.
+\param copy_indices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data.
+\param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array. Use 1 if you will apply transformations to the trimesh. See \ref gim_trimesh_set_tranform().
+*/
+void gim_trimesh_create_from_data(GIM_TRIMESH * trimesh, vec3f * vertex_array, GUINT vertex_count,char copy_vertices, GUINT * triindex_array, GUINT index_count,char copy_indices,char transformed_reply);
+
+//! Clears auxiliary data and releases buffer arrays
+void gim_trimesh_destroy(GIM_TRIMESH * trimesh);
+
+//! Copies two meshes
+/*!
+\param source_trimesh
+\param dest_trimesh
+\param copy_by_reference If 1, it attach a reference to the source vertices, else it copies the vertices
+\param transformed_reply If 1, transformed vertices are reply of source vertives. 1 Is recommended
+*/
+void gim_trimesh_copy(GIM_TRIMESH * source_trimesh,GIM_TRIMESH * dest_trimesh, char copy_by_reference, char transformed_reply);
+
+
+//! Locks the trimesh for working with it
+/*!
+\post locks m_tri_index_buffer and m_transformed_vertex_buffer.
+\param trimesh
+*/
+void gim_trimesh_locks_work_data(GIM_TRIMESH * trimesh);
+
+
+//! unlocks the trimesh
+/*!
+\post unlocks m_tri_index_buffer and m_transformed_vertex_buffer.
+\param trimesh
+*/
+void gim_trimesh_unlocks_work_data(GIM_TRIMESH * trimesh);
+
+//! Updates m_transformed_vertex_buffer
+/*!
+\pre m_transformed_vertex_buffer must be unlocked
+*/
+void gim_trimesh_update_vertices(GIM_TRIMESH * trimesh);
+
+//! Updates m_aabbset and m_planes_cache_bitset
+/*!
+\pre gim_trimesh_locks_work_data must be called before
+*/
+void gim_trimesh_update_aabbset(GIM_TRIMESH * trimesh);
+
+//! Calls before perfom collisions. Updates the trimesh if needed
+/*!
+\post If gim_trimesh_needs_update returns 1, then it calls  gim_trimesh_update_vertices and gim_trimesh_update_aabbset
+*/
+void gim_trimesh_update(GIM_TRIMESH * trimesh);
+
+//! Set the transform of a trimesh
+/*!
+\post This function calls to gim_trimesh_post_update
+*/
+void gim_trimesh_set_tranform(GIM_TRIMESH * trimesh, mat4f transform);
+
+//! Fetch triangle data
+/*!
+\pre gim_trimesh_locks_work_data must be called before
+*/
+void gim_trimesh_get_triangle_data(GIM_TRIMESH * trimesh, GUINT triangle_index, GIM_TRIANGLE_DATA * tri_data);
+
+//! Fetch triangle vertices
+/*!
+\pre gim_trimesh_locks_work_data must be called before
+*/
+void gim_trimesh_get_triangle_vertices(GIM_TRIMESH * trimesh, GUINT triangle_index, vec3f v1,vec3f v2,vec3f v3);
+
+//! Trimesh Trimesh Collisions
+/*!
+Before use this function you must update each trimesh:
+\code
+gim_trimesh_update(TriMesh1);
+gim_trimesh_update(TriMesh2);
+\endcode
+Then you must use the trimesh collision in this way:
+\code
+int collide_trimeshes(GIM_TRIMESH * TriMesh1, GIM_TRIMESH * TriMesh2)
+{
+    //Create contact list
+    GDYNAMIC_ARRAY trimeshcontacts;
+    GIM_CREATE_CONTACT_LIST(trimeshcontacts);
+
+    //Collide trimeshes
+    gim_trimesh_trimesh_collision(TriMesh1,TriMesh2,&trimeshcontacts);
+
+    if(trimeshcontacts.m_size == 0) //do  nothing
+    {
+        GIM_DYNARRAY_DESTROY(trimeshcontacts);//clean contact array
+        return 0;
+    }
+
+    //Getting a pointer to the contact array
+    GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
+
+    int contactcount = trimeshcontacts.m_size;
+    int i;
+    //Process contacts
+    for (i=0;i<contactcount ;i++)
+    {
+        //Do something with the contact (ptrimeshcontacts)
+        ......
+        ......
+        // Like creating joints or anything else
+        ......
+        ......
+        ptrimeshcontacts++;
+    }
+    GIM_DYNARRAY_DESTROY(trimeshcontacts);
+    return contactcount;
+}
+\endcode
+In each contact
+<ul>
+<li> m_handle1 points to trimesh1.
+<li> m_handle2 points to trimesh2.
+<li> m_feature1 Is a triangle index of trimesh1.
+<li> m_feature2 Is a triangle index of trimesh2.
+</ul>
+
+\param trimesh1 Collider
+\param trimesh2 Collidee
+\param contacts A GIM_CONTACT array. Must be initialized
+*/
+void gim_trimesh_trimesh_collision(GIM_TRIMESH * trimesh1, GIM_TRIMESH * trimesh2, GDYNAMIC_ARRAY * contacts);
+
+
+//! Trimesh Sphere Collisions
+/*!
+Before use this function you must update the trimesh:
+\code
+gim_trimesh_update(trimesh);
+\endcode
+Then you must use this function in this way:
+\code
+int collide_trimesh_sphere(GIM_TRIMESH * trimesh, vec3f center,GREAL radius)
+{
+    //Create contact list
+    GDYNAMIC_ARRAY trimeshcontacts;
+    GIM_CREATE_CONTACT_LIST(trimeshcontacts);
+
+    //Collide trimeshes
+    gim_trimesh_sphere_collision(trimesh,center,radius,&trimeshcontacts);
+
+    if(trimeshcontacts.m_size == 0) //do  nothing
+    {
+        GIM_DYNARRAY_DESTROY(trimeshcontacts);//clean contact array
+        return 0;
+    }
+
+    //Getting a pointer to the contact array
+    GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
+
+    int contactcount = trimeshcontacts.m_size;
+    int i;
+    //Process contacts
+    for (i=0;i<contactcount ;i++)
+    {
+        //Do something with the contact (ptrimeshcontacts)
+        ......
+        ......
+        // Like creating joints or anything else
+        ......
+        ......
+        ptrimeshcontacts++;
+    }
+    GIM_DYNARRAY_DESTROY(trimeshcontacts);
+    return contactcount;
+}
+\endcode
+
+In each contact
+<ul>
+<li> m_handle1 points to trimesh.
+<li> m_handle2 points to NULL.
+<li> m_feature1 Is a triangle index of trimesh.
+</ul>
+
+\param trimesh
+\param center
+\param radius
+\param contacts A GIM_CONTACT array. Must be initialized
+*/
+void gim_trimesh_sphere_collision(GIM_TRIMESH * trimesh,vec3f center,GREAL radius, GDYNAMIC_ARRAY * contacts);
+
+
+//! Trimesh Capsule collision
+/*!
+Find the closest primitive collided by the ray.
+
+Before use this function you must update the trimesh:
+\code
+gim_trimesh_update(trimesh);
+\endcode
+Then you must use this function in this way:
+\code
+int collide_trimesh_capsule(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule)
+{
+    //Create contact list
+    GDYNAMIC_ARRAY trimeshcontacts;
+    GIM_CREATE_CONTACT_LIST(trimeshcontacts);
+
+    //Collide trimeshes
+    gim_trimesh_capsule_collision(trimesh,capsule,&trimeshcontacts);
+
+    if(trimeshcontacts.m_size == 0) //do  nothing
+    {
+        GIM_DYNARRAY_DESTROY(trimeshcontacts);//clean contact array
+        return 0;
+    }
+
+    //Getting a pointer to the contact array
+    GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
+
+    int contactcount = trimeshcontacts.m_size;
+    int i;
+    //Process contacts
+    for (i=0;i<contactcount ;i++)
+    {
+        //Do something with the contact (ptrimeshcontacts)
+        ......
+        ......
+        // Like creating joints or anything else
+        ......
+        ......
+        ptrimeshcontacts++;
+    }
+    GIM_DYNARRAY_DESTROY(trimeshcontacts);
+    return contactcount;
+}
+\endcode
+
+In each contact
+<ul>
+<li> m_handle1 points to trimesh.
+<li> m_handle2 points to NULL.
+<li> m_feature1 Is a triangle index of trimesh.
+</ul>
+
+\param trimesh
+\param capsule
+\param contacts A GIM_CONTACT array. Must be initialized
+*/
+void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts);
+
+
+///Function for create Trimesh Plane  collision result
+#define GIM_CREATE_TRIMESHPLANE_CONTACTS(dynarray) GIM_DYNARRAY_CREATE(vec4f,dynarray,G_ARRAY_GROW_SIZE)
+
+//! Trimesh Plane Collisions
+/*!
+
+Before use this function you must update the trimesh:
+\code
+gim_trimesh_update(trimesh);
+\endcode
+Then you must use this function in this way:
+\code
+int collide_trimesh_plane(GIM_TRIMESH * trimesh, vec4f plane)
+{
+    //Create contact list
+    GDYNAMIC_ARRAY tri_plane_contacts;
+    GIM_CREATE_TRIMESHPLANE_CONTACTS(tri_plane_contacts);
+
+    //Collide trimeshes
+    gim_trimesh_plane_collision(trimesh,plane,&tri_plane_contacts);
+
+    if(tri_plane_contacts.m_size == 0) //do  nothing
+    {
+        GIM_DYNARRAY_DESTROY(tri_plane_contacts);//clean contact array
+        return 0;
+    }
+
+    //Getting a pointer to the contact array
+    vec4f * planecontacts = GIM_DYNARRAY_POINTER(vec4f,tri_plane_contacts);
+
+    int contactcount = tri_plane_contacts.m_size;
+    int i;
+    //Process contacts
+    for (i=0;i<contactcount ;i++)
+    {
+        vec3f contactpoint;
+        GREAL contactdis;
+
+        VEC_COPY(contactpoint,planecontacts[i]); //Get contact point
+        contactdis = planecontacts[i][3]; // Get distance depth
+
+        //Do something with the contact
+        ......
+        ......
+        // Like creating joints or anything else
+        ......
+        ......
+    }
+    GIM_DYNARRAY_DESTROY(tri_plane_contacts);
+    return contactcount;
+}
+\endcode
+
+In each contact the 3 first coordinates refers to the contact point, the fourth refers to the distance depth and the normal is the normal of the plane.
+
+\param trimesh
+\param plane vec4f plane
+\param contacts A vec4f array. Must be initialized (~100). Each element have the coordinate point in the first 3 elements, and vec4f[3] has the penetration depth.
+*/
+void gim_trimesh_plane_collision(GIM_TRIMESH * trimesh,vec4f plane, GDYNAMIC_ARRAY * contacts);
+
+
+//! Trimesh Ray Collisions
+/*!
+\param trimesh
+\param origin
+\param dir
+\param tmax
+\param contact
+\return 1 if the ray collides, else 0
+*/
+int gim_trimesh_ray_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact);
+
+
+//! Trimesh Ray Collisions closest
+/*!
+Find the closest primitive collided by the ray
+\param trimesh
+\param origin
+\param dir
+\param tmax
+\param contact
+\return 1 if the ray collides, else 0
+*/
+int gim_trimesh_ray_closest_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact);
+
+//! @}
+
+
+
+#endif // GIM_TRIMESH_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gimpact.h
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gimpact.h	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gimpact.h	(revision 216)
@@ -0,0 +1,45 @@
+#ifndef GIMPACT_H_INCLUDED
+#define GIMPACT_H_INCLUDED
+
+/*! \file gimpact.h
+\author Francisco León
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_trimesh.h"
+
+/*! \defgroup GIMPACT_INIT
+*/
+//! @{
+//! Call this for initialize GIMPACT system structures.
+void gimpact_init();
+//! Call this for clean GIMPACT system structures.
+void gimpact_terminate();
+//! @}
+#endif // GIMPACT_H_INCLUDED
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_boxpruning.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_boxpruning.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_boxpruning.cpp	(revision 216)
@@ -0,0 +1,514 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_boxpruning.h"
+
+
+
+//! Allocate memory for all aabb set.
+void gim_aabbset_alloc(GIM_AABB_SET * aabbset, GUINT count)
+{
+    aabbset->m_count = count;
+    aabbset->m_boxes = (aabb3f *)gim_alloc(sizeof(aabb3f)*count);
+
+    if(count<GIM_MIN_SORTED_BIPARTITE_PRUNING_BOXES)
+    {
+        aabbset->m_maxcoords = 0;
+        aabbset->m_sorted_mincoords = 0;
+    }
+    else
+    {
+        aabbset->m_maxcoords = (GUINT *)gim_alloc(sizeof(GUINT)*aabbset->m_count );
+        aabbset->m_sorted_mincoords = (GIM_RSORT_TOKEN *)gim_alloc(sizeof(GIM_RSORT_TOKEN)*aabbset->m_count);
+    }
+    aabbset->m_shared = 0;
+    INVALIDATE_AABB(aabbset->m_global_bound);
+}
+
+//! Destroys the aabb set.
+void gim_aabbset_destroy(GIM_AABB_SET * aabbset)
+{
+    aabbset->m_count = 0;
+    if(aabbset->m_shared==0)
+    {
+        gim_free(aabbset->m_boxes,0);
+        gim_free(aabbset->m_maxcoords,0);
+        gim_free(aabbset->m_sorted_mincoords,0);
+    }
+    aabbset->m_boxes = 0;
+    aabbset->m_sorted_mincoords = 0;
+    aabbset->m_maxcoords = 0;
+}
+
+void gim_aabbset_calc_global_bound(GIM_AABB_SET * aabbset)
+{
+    aabb3f * paabb = aabbset->m_boxes;
+    aabb3f * globalbox = &aabbset->m_global_bound;
+    AABB_COPY((*globalbox),(*paabb));
+
+    GUINT count = aabbset->m_count-1;
+    paabb++;
+    while(count)
+    {
+        MERGEBOXES(*globalbox,*paabb)
+        paabb++;
+        count--;
+    }
+}
+
+
+//! Sorts the boxes for box prunning.
+/*!
+1) find the integer representation of the aabb coords
+2) Sorts the min coords
+3) Calcs the global bound
+\pre aabbset must be allocated. And the boxes must be already set.
+\param aabbset
+\param calc_global_bound If 1 , calcs the global bound
+\post If aabbset->m_sorted_mincoords == 0, then it allocs the sorted coordinates
+*/
+void gim_aabbset_sort(GIM_AABB_SET * aabbset, char calc_global_bound)
+{
+    if(aabbset->m_sorted_mincoords == 0)
+    {//allocate
+        aabbset->m_maxcoords = (GUINT *)gim_alloc(sizeof(GUINT)*aabbset->m_count );
+        aabbset->m_sorted_mincoords = (GIM_RSORT_TOKEN *)gim_alloc(sizeof(GIM_RSORT_TOKEN)*aabbset->m_count);
+    }
+
+    GUINT i, count = aabbset->m_count;
+    aabb3f * paabb = aabbset->m_boxes;
+    GUINT * maxcoords = aabbset->m_maxcoords;
+    GIM_RSORT_TOKEN * sorted_tokens = aabbset->m_sorted_mincoords;
+
+    if(count<860)//Calibrated on a Pentium IV
+    {
+        //Sort by quick sort
+            //Calculate keys
+        for(i=0;i<count;i++)
+        {
+            GIM_CONVERT_VEC3F_GUINT_XZ_UPPER(paabb[i].maxX,paabb[i].maxZ,maxcoords[i]);
+            GIM_CONVERT_VEC3F_GUINT_XZ(paabb[i].minX,paabb[i].minZ,sorted_tokens[i].m_key);
+            sorted_tokens[i].m_value = i;
+        }
+        GIM_QUICK_SORT_ARRAY(GIM_RSORT_TOKEN , sorted_tokens, count, RSORT_TOKEN_COMPARATOR,GIM_DEF_EXCHANGE_MACRO);
+    }
+    else
+    {
+        //Sort by radix sort
+        GIM_RSORT_TOKEN * unsorted = (GIM_RSORT_TOKEN *)gim_alloc(sizeof(GIM_RSORT_TOKEN )*count);
+        //Calculate keys
+        for(i=0;i<count;i++)
+        {
+            GIM_CONVERT_VEC3F_GUINT_XZ_UPPER(paabb[i].maxX,paabb[i].maxZ,maxcoords[i]);
+            GIM_CONVERT_VEC3F_GUINT_XZ(paabb[i].minX,paabb[i].minZ,unsorted[i].m_key);
+            unsorted[i].m_value = i;
+        }
+        GIM_RADIX_SORT_RTOKENS(unsorted,sorted_tokens,count);
+        gim_free(unsorted,0);
+    }
+
+    if(calc_global_bound) gim_aabbset_calc_global_bound(aabbset);
+}
+
+//utility macros
+
+/*#define PUSH_PAIR(i,j,pairset)\
+{\
+    GIM_PAIR _pair={i,j};\
+    GIM_DYNARRAY_PUSH_ITEM(GIM_PAIR,pairset,_pair);\
+}*/
+
+#define PUSH_PAIR(i,j,pairset)\
+{\
+    GIM_DYNARRAY_PUSH_EMPTY(GIM_PAIR,pairset);\
+    GIM_PAIR * _pair = GIM_DYNARRAY_POINTER(GIM_PAIR,pairset) + (pairset).m_size - 1;\
+    _pair->m_index1 = i;\
+    _pair->m_index2 = j;\
+}
+
+#define PUSH_PAIR_INV(i,j,pairset)\
+{\
+    GIM_DYNARRAY_PUSH_EMPTY(GIM_PAIR,pairset);\
+    GIM_PAIR * _pair = GIM_DYNARRAY_POINTER(GIM_PAIR,pairset) + (pairset).m_size - 1;\
+    _pair->m_index1 = j;\
+    _pair->m_index2 = i;\
+}
+
+#define FIND_OVERLAPPING_FOWARD(\
+ curr_index,\
+ test_count,\
+ test_aabb,\
+ max_coord_uint,\
+ sorted_tokens,\
+ aabbarray,\
+ pairset,\
+ push_pair_macro)\
+{\
+    GUINT _i = test_count;\
+    char _intersected;\
+    GIM_RSORT_TOKEN * _psorted_tokens = sorted_tokens;\
+    while(max_coord_uint >= _psorted_tokens->m_key && _i>0)\
+    {\
+        AABBCOLLISION(_intersected,test_aabb,aabbarray[_psorted_tokens->m_value]);\
+    	if(_intersected)\
+    	{\
+    	    push_pair_macro(curr_index, _psorted_tokens->m_value,pairset);\
+    	}\
+    	_psorted_tokens++;\
+    	_i--;\
+    }\
+}
+
+//! log(N) Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+/*!
+\pre aabbset must be allocated and sorted, the boxes must be already set.
+\param aabbset Must be sorted. Global bound isn't required
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_self_intersections_sorted(GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collision_pairs)
+{
+    collision_pairs->m_size = 0;
+    GUINT count = aabbset->m_count;
+    aabb3f * paabb = aabbset->m_boxes;
+    GUINT * maxcoords = aabbset->m_maxcoords;
+    GIM_RSORT_TOKEN * sorted_tokens = aabbset->m_sorted_mincoords;
+    aabb3f test_aabb;
+    while(count>1)
+    {
+        ///current cache variables
+        GUINT  curr_index = sorted_tokens->m_value;
+        GUINT max_coord_uint = maxcoords[curr_index];
+        AABB_COPY(test_aabb,paabb[curr_index]);
+
+        ///next pairs
+        sorted_tokens++;
+        count--;
+    	FIND_OVERLAPPING_FOWARD( curr_index, count, test_aabb, max_coord_uint, sorted_tokens , paabb, (*collision_pairs),PUSH_PAIR);
+    }
+}
+
+//! NxN Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+/*!
+\pre aabbset must be allocated, the boxes must be already set.
+\param aabbset Global bound isn't required. Doen't need to be sorted.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_self_intersections_brute_force(GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collision_pairs)
+{
+    collision_pairs->m_size = 0;
+    GUINT i,j;
+    GUINT count = aabbset->m_count;
+    aabb3f * paabb = aabbset->m_boxes;
+    char intersected;
+    for (i=0;i< count-1 ;i++ )
+    {
+        for (j=i+1;j<count ;j++ )
+        {
+            AABBCOLLISION(intersected,paabb[i],paabb[j]);
+            if(intersected)
+            {
+                PUSH_PAIR(i,j,(*collision_pairs));
+            }
+        }
+    }
+}
+
+//! log(N) Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+/*!
+\pre aabbset1 and aabbset2 must be allocated and sorted, the boxes must be already set.
+\param aabbset1 Must be sorted, Global bound is required.
+\param aabbset2 Must be sorted, Global bound is required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_bipartite_intersections_sorted(GIM_AABB_SET * aabbset1, GIM_AABB_SET * aabbset2, GDYNAMIC_ARRAY * collision_pairs)
+{
+    char intersected;
+    collision_pairs->m_size = 0;
+
+    AABBCOLLISION(intersected,aabbset1->m_global_bound,aabbset2->m_global_bound);
+    if(intersected == 0) return;
+
+    GUINT count1 = aabbset1->m_count;
+    aabb3f * paabb1 = aabbset1->m_boxes;
+    GUINT * maxcoords1 = aabbset1->m_maxcoords;
+    GIM_RSORT_TOKEN * sorted_tokens1 = aabbset1->m_sorted_mincoords;
+
+    GUINT count2 = aabbset2->m_count;
+    aabb3f * paabb2 = aabbset2->m_boxes;
+    GUINT * maxcoords2 = aabbset2->m_maxcoords;
+    GIM_RSORT_TOKEN * sorted_tokens2 = aabbset2->m_sorted_mincoords;
+
+    GUINT  curr_index;
+
+    GUINT max_coord_uint;
+    aabb3f test_aabb;
+
+    //Classify boxes
+    //Find  Set intersection
+    aabb3f int_abbb;
+    BOXINTERSECTION(aabbset1->m_global_bound,aabbset2->m_global_bound, int_abbb);
+
+    //Clasify set 1
+    GIM_RSORT_TOKEN * classified_tokens1 = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*count1);
+    GUINT i,classified_count1 = 0,classified_count2 = 0;
+
+
+    for (i=0;i<count1;i++ )
+    {
+        curr_index = sorted_tokens1[i].m_value;
+        AABBCOLLISION(intersected,paabb1[curr_index],int_abbb);
+    	if(intersected)
+    	{
+    	    classified_tokens1[classified_count1] = sorted_tokens1[i];
+    	    classified_count1++;
+    	}
+    }
+
+    if(classified_count1==0)
+    {
+        gim_free(classified_tokens1 ,0);
+        return; // no pairs
+    }
+
+    //Clasify set 2
+    GIM_RSORT_TOKEN * classified_tokens2 = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*count2);
+
+    for (i=0;i<count2;i++ )
+    {
+        curr_index = sorted_tokens2[i].m_value;
+        AABBCOLLISION(intersected,paabb2[curr_index],int_abbb);
+    	if(intersected)
+    	{
+    	    classified_tokens2[classified_count2] = sorted_tokens2[i];
+    	    classified_count2++;
+    	}
+    }
+
+    if(classified_count2==0)
+    {
+        gim_free(classified_tokens1 ,0);
+        gim_free(classified_tokens2 ,0);
+        return; // no pairs
+    }
+
+    sorted_tokens1 = classified_tokens1;
+    sorted_tokens2 = classified_tokens2;
+
+    while(classified_count1>0&&classified_count2>0)
+    {
+        if(sorted_tokens1->m_key <= sorted_tokens2->m_key)
+        {
+            ///current cache variables
+            curr_index = sorted_tokens1->m_value;
+            max_coord_uint = maxcoords1[curr_index];
+            AABB_COPY(test_aabb,paabb1[curr_index]);
+            ///next pairs
+            sorted_tokens1++;
+            classified_count1--;
+            FIND_OVERLAPPING_FOWARD( curr_index, classified_count2, test_aabb, max_coord_uint, sorted_tokens2 , paabb2, (*collision_pairs), PUSH_PAIR);
+        }
+        else ///Switch test
+        {
+            ///current cache variables
+            curr_index = sorted_tokens2->m_value;
+            max_coord_uint = maxcoords2[curr_index];
+            AABB_COPY(test_aabb,paabb2[curr_index]);
+            ///next pairs
+            sorted_tokens2++;
+            classified_count2--;
+            FIND_OVERLAPPING_FOWARD( curr_index, classified_count1, test_aabb, max_coord_uint, sorted_tokens1 , paabb1, (*collision_pairs), PUSH_PAIR_INV );
+        }
+    }
+    gim_free(classified_tokens1 ,0);
+    gim_free(classified_tokens2 ,0);
+}
+
+//! NxM Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+/*!
+\pre aabbset1 and aabbset2 must be allocated and sorted, the boxes must be already set.
+\param aabbset1 Must be sorted, Global bound is required.
+\param aabbset2 Must be sorted, Global bound is required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_bipartite_intersections_brute_force(GIM_AABB_SET * aabbset1,GIM_AABB_SET * aabbset2, GDYNAMIC_ARRAY * collision_pairs)
+{
+    char intersected;
+    collision_pairs->m_size = 0;
+    AABBCOLLISION(intersected,aabbset1->m_global_bound,aabbset2->m_global_bound);
+    if(intersected == 0) return;
+
+    aabb3f int_abbb;
+    //Find  Set intersection
+    BOXINTERSECTION(aabbset1->m_global_bound,aabbset2->m_global_bound, int_abbb);
+    //Clasify set 1
+    GUINT i,j;
+    GUINT classified_count = 0;
+
+    GUINT count = aabbset1->m_count;
+    aabb3f * paabb1 = aabbset1->m_boxes;
+    aabb3f * paabb2 = aabbset2->m_boxes;
+
+    GUINT * classified = (GUINT *) gim_alloc(sizeof(GUINT)*count);
+
+    for (i=0;i<count;i++ )
+    {
+        AABBCOLLISION(intersected,paabb1[i],int_abbb);
+    	if(intersected)
+    	{
+    	    classified[classified_count] = i;
+    	    classified_count++;
+    	}
+    }
+
+    if(classified_count==0) return; // no pairs
+
+    //intesect set2
+    count = aabbset2->m_count;
+    for (i=0;i<count;i++)
+    {
+        AABBCOLLISION(intersected,paabb2[i],int_abbb);
+        if(intersected)
+        {
+            for (j=0;j<classified_count;j++)
+            {
+                AABBCOLLISION(intersected,paabb2[i],paabb1[classified[j]]);
+                if(intersected)
+                {
+                    PUSH_PAIR(classified[j],i,(*collision_pairs));
+                }
+            }
+        }
+    }
+    gim_free(classified,0);
+}
+
+
+//! Initalizes the set. Sort Boxes if needed.
+/*!
+\pre aabbset must be allocated. And the boxes must be already set.
+\post If the set has less of GIM_MIN_SORTED_BIPARTITE_PRUNING_BOXES boxes, only calcs the global box,
+ else it Sorts the entire set( Only applicable for large sets)
+*/
+void gim_aabbset_update(GIM_AABB_SET * aabbset)
+{
+    if(aabbset->m_count < GIM_MIN_SORTED_BIPARTITE_PRUNING_BOXES)
+    {//Brute force approach
+        gim_aabbset_calc_global_bound(aabbset);
+    }
+    else
+    {//Sorted force approach
+        gim_aabbset_sort(aabbset,1);
+    }
+}
+
+//! Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+/*!
+This function sorts the set and then it calls to gim_aabbset_self_intersections_brute_force or gim_aabbset_self_intersections_sorted.
+
+\param aabbset Set of boxes. Sorting isn't required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+\pre aabbset must be allocated and initialized.
+\post If aabbset->m_count >= GIM_MIN_SORTED_PRUNING_BOXES, then it calls to gim_aabbset_sort and then to gim_aabbset_self_intersections_sorted.
+*/
+void gim_aabbset_self_intersections(GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collision_pairs)
+{
+    if(aabbset->m_count < GIM_MIN_SORTED_PRUNING_BOXES)
+    {//Brute force approach
+        gim_aabbset_self_intersections_brute_force(aabbset,collision_pairs);
+    }
+    else
+    {//Sorted force approach
+        gim_aabbset_sort(aabbset,0);
+        gim_aabbset_self_intersections_sorted(aabbset,collision_pairs);
+    }
+}
+
+//! Collides two sets. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+/*!
+\pre aabbset1 and aabbset2 must be allocated and updated. See .
+\param aabbset1 Must be sorted, Global bound is required.
+\param aabbset2 Must be sorted, Global bound is required.
+\param collision_pairs Array of GIM_PAIR elements. Must be initialized before (Reserve size ~ 100)
+*/
+void gim_aabbset_bipartite_intersections(GIM_AABB_SET * aabbset1, GIM_AABB_SET * aabbset2, GDYNAMIC_ARRAY * collision_pairs)
+{
+    if(aabbset1->m_sorted_mincoords == 0||aabbset2->m_sorted_mincoords == 0)
+    {//Brute force approach
+        gim_aabbset_bipartite_intersections_brute_force(aabbset1,aabbset2,collision_pairs);
+    }
+    else
+    {//Sorted force approach
+        gim_aabbset_bipartite_intersections_sorted(aabbset1,aabbset2,collision_pairs);
+    }
+}
+
+void gim_aabbset_box_collision(aabb3f *test_aabb, GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collided)
+{
+    collided->m_size = 0;
+    char intersected;
+    AABBCOLLISION(intersected,aabbset->m_global_bound,(*test_aabb));
+    if(intersected == 0) return;
+
+    GUINT i;
+    GUINT count = aabbset->m_count;
+    aabb3f * paabb = aabbset->m_boxes;
+    aabb3f _testaabb;
+    AABB_COPY(_testaabb,*test_aabb);
+
+    for (i=0;i< count;i++ )
+    {
+        AABBCOLLISION(intersected,paabb[i],_testaabb);
+        if(intersected)
+        {
+            GIM_DYNARRAY_PUSH_ITEM(GUINT,(*collided),i);
+        }
+    }
+}
+
+void gim_aabbset_ray_collision(vec3f vorigin,vec3f vdir, GREAL tmax, GIM_AABB_SET * aabbset, GDYNAMIC_ARRAY * collided)
+{
+    collided->m_size = 0;
+    char intersected;
+    GREAL tparam = 0;
+    BOX_INTERSECTS_RAY(aabbset->m_global_bound, vorigin, vdir, tparam, tmax,intersected);
+    if(intersected==0) return;
+
+    GUINT i;
+    GUINT count = aabbset->m_count;
+    aabb3f * paabb = aabbset->m_boxes;
+
+    for (i=0;i< count;i++ )
+    {
+        BOX_INTERSECTS_RAY(paabb[i], vorigin, vdir, tparam, tmax,intersected);
+        if(intersected)
+        {
+            GIM_DYNARRAY_PUSH_ITEM(GUINT,(*collided),i);
+        }
+    }
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_contact.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_contact.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_contact.cpp	(revision 216)
@@ -0,0 +1,132 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_contact.h"
+
+void gim_merge_contacts(GDYNAMIC_ARRAY * source_contacts,
+					GDYNAMIC_ARRAY * dest_contacts)
+{
+    dest_contacts->m_size = 0;
+
+	GUINT source_count = source_contacts->m_size;
+	GIM_CONTACT * psource_contacts	= GIM_DYNARRAY_POINTER(GIM_CONTACT,(*source_contacts));
+	//create keys
+	GIM_RSORT_TOKEN * keycontacts = (GIM_RSORT_TOKEN * )gim_alloc(sizeof(GIM_RSORT_TOKEN)*source_count);
+
+    GUINT i;
+	for(i=0;i<source_count;i++)
+	{
+		keycontacts[i].m_value = i;
+		GIM_CALC_KEY_CONTACT(psource_contacts[i].m_point,keycontacts[i].m_key);
+	}
+
+	//sort keys
+	GIM_QUICK_SORT_ARRAY(GIM_RSORT_TOKEN , keycontacts, source_count, RSORT_TOKEN_COMPARATOR,GIM_DEF_EXCHANGE_MACRO);
+
+	// Merge contacts
+	GIM_CONTACT * pcontact = 0;
+	GIM_CONTACT * scontact = 0;
+	GUINT key,last_key=0;
+
+	for(i=0;i<source_contacts->m_size;i++)
+	{
+	    key = keycontacts[i].m_key;
+		scontact = &psource_contacts[keycontacts[i].m_value];
+
+		if(i>0 && last_key ==  key)
+		{
+			//merge contact
+			if(pcontact->m_depth > scontact->m_depth + CONTACT_DIFF_EPSILON)
+			{
+			    GIM_COPY_CONTACTS(pcontact, scontact);
+			}
+		}
+		else
+		{//add new contact
+		    GIM_DYNARRAY_PUSH_EMPTY(GIM_CONTACT,(*dest_contacts));
+            pcontact = GIM_DYNARRAY_POINTER_LAST(GIM_CONTACT,(*dest_contacts));
+		    GIM_COPY_CONTACTS(pcontact, scontact);
+        }
+		last_key = key;
+	}
+	gim_free(keycontacts,0);
+}
+
+void gim_merge_contacts_unique(GDYNAMIC_ARRAY * source_contacts,
+					GDYNAMIC_ARRAY * dest_contacts)
+{
+    dest_contacts->m_size = 0;
+    //Traverse the source contacts
+	GUINT source_count = source_contacts->m_size;
+	if(source_count==0) return;
+
+	GIM_CONTACT * psource_contacts	= GIM_DYNARRAY_POINTER(GIM_CONTACT,(*source_contacts));
+
+	//add the unique contact
+	GIM_CONTACT * pcontact = 0;
+    GIM_DYNARRAY_PUSH_EMPTY(GIM_CONTACT,(*dest_contacts));
+    pcontact = GIM_DYNARRAY_POINTER_LAST(GIM_CONTACT,(*dest_contacts));
+    //set the first contact
+    GIM_COPY_CONTACTS(pcontact, psource_contacts);
+
+    if(source_count==1) return;
+    //scale the first contact
+    VEC_SCALE(pcontact->m_normal,pcontact->m_depth,pcontact->m_normal);
+
+    psource_contacts++;
+
+	//Average the contacts
+    GUINT i;
+	for(i=1;i<source_count;i++)
+	{
+	    VEC_SUM(pcontact->m_point,pcontact->m_point,psource_contacts->m_point);
+	    VEC_ACCUM(pcontact->m_normal,psource_contacts->m_depth,psource_contacts->m_normal);
+	    psource_contacts++;
+	}
+
+	GREAL divide_average = 1.0f/((GREAL)source_count);
+
+	VEC_SCALE(pcontact->m_point,divide_average,pcontact->m_point);
+
+	pcontact->m_depth = VEC_DOT(pcontact->m_normal,pcontact->m_normal)*divide_average;
+	GIM_SQRT(pcontact->m_depth,pcontact->m_depth);
+
+	VEC_NORMALIZE(pcontact->m_normal);
+
+	/*GREAL normal_len;
+    VEC_INV_LENGTH(pcontact->m_normal,normal_len);
+	VEC_SCALE(pcontact->m_normal,normal_len,pcontact->m_normal);
+
+    //Deep = LEN(normal)/SQRT(source_count)
+    GIM_SQRT(divide_average,divide_average);
+	pcontact->m_depth = divide_average/normal_len;
+	*/
+}
+
+
+
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_math.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_math.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_math.cpp	(revision 216)
@@ -0,0 +1,60 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_math.h"
+#include "stdlib.h"
+#include "time.h"
+
+
+GREAL gim_inv_sqrt(GREAL f)
+{
+    GREAL r;
+    GIM_INV_SQRT(f,r);
+    return r;
+}
+
+GREAL gim_sqrt(GREAL f)
+{
+    GREAL r;
+    GIM_SQRT(f,r);
+    return r;
+}
+
+//!Initializes mathematical functions
+void gim_init_math()
+{
+    srand( static_cast< unsigned int >( time( 0 ) ) );
+}
+
+//! Generates an unit random
+GREAL gim_unit_random()
+{
+    GREAL rn = static_cast< GREAL >( rand() );
+    rn/=(GREAL)RAND_MAX;
+    return rn;
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_memory.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_memory.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_memory.cpp	(revision 216)
@@ -0,0 +1,848 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "GIMPACT/gim_memory.h"
+#include "stdlib.h"
+#include "malloc.h"
+//#include "mm_malloc.h"
+
+static gim_alloc_function *g_allocfn = 0;
+static gim_alloca_function *g_allocafn = 0;
+static gim_realloc_function *g_reallocfn = 0;
+static gim_free_function *g_freefn = 0;
+
+// buffer managers
+#define MAX_BUFFER_MANAGERS 16
+static GBUFFER_MANAGER_DATA g_buffer_managers[MAX_BUFFER_MANAGERS];
+static GUINT g_buffer_managers_count = 0;
+
+#define VALIDATE_BUFFER_MANAGER(buffer_manager_id)\
+    if(buffer_manager_id>=MAX_BUFFER_MANAGERS) return G_BUFFER_OP_INVALID;\
+    GBUFFER_MANAGER_DATA * bm_data;\
+    gim_get_buffer_manager_data(buffer_manager_id,&bm_data);\
+    if(bm_data == 0) return G_BUFFER_OP_INVALID;\
+
+#define VALIDATE_BUFFER_ID_PT(buffer_id)\
+    VALIDATE_BUFFER_MANAGER(buffer_id->m_buffer_manager_id)\
+    if(buffer_id->m_buffer_id>=bm_data->m_buffer_array.m_size) return G_BUFFER_OP_INVALID;\
+    GBUFFER_DATA * pbuffer = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);\
+    pbuffer += buffer_id->m_buffer_id;\
+    if(pbuffer->m_buffer_handle==0) return G_BUFFER_OP_INVALID;\
+
+
+void GIM_BUFFER_ARRAY_DESTROY(GBUFFER_ARRAY & array_data)
+{
+    gim_buffer_array_unlock(&array_data);
+    gim_buffer_free(&(array_data).m_buffer_id);
+}
+
+void GIM_DYNARRAY_DESTROY(GDYNAMIC_ARRAY & array_data)
+{
+    if(array_data.m_pdata != 0)
+    {
+        gim_free(array_data.m_pdata,0);
+        array_data.m_reserve_size = 0;
+        array_data.m_size = 0;
+        array_data.m_pdata = 0;
+    }
+}
+
+void gim_set_alloc_handler (gim_alloc_function *fn)
+{
+  g_allocfn = fn;
+}
+
+void gim_set_alloca_handler (gim_alloca_function *fn)
+{
+  g_allocafn = fn;
+}
+
+void gim_set_realloc_handler (gim_realloc_function *fn)
+{
+  g_reallocfn = fn;
+}
+
+void gim_set_free_handler (gim_free_function *fn)
+{
+  g_freefn = fn;
+}
+
+gim_alloc_function *gim_get_alloc_handler()
+{
+  return g_allocfn;
+}
+
+gim_alloca_function *gim_get_alloca_handler()
+{
+  return g_allocafn;
+}
+
+
+gim_realloc_function *gim_get_realloc_handler ()
+{
+  return g_reallocfn;
+}
+
+
+gim_free_function  *gim_get_free_handler ()
+{
+  return g_freefn;
+}
+
+
+void * gim_alloc(size_t size)
+{
+   void * ptr = 0;
+   ptr = malloc(size);
+  /*if (g_allocfn) ptr = g_allocfn(size); else ptr = malloc(size);//_mm_malloc(size,0);*/
+  if(ptr==0)
+  {
+      float * fp = 0;
+      *fp = 0.0f;
+  }
+  return ptr;
+}
+
+void * gim_alloca(size_t size)
+{
+  if (g_allocafn) return g_allocafn(size); else return alloca(size);
+}
+
+
+void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
+{
+  /*if (g_reallocfn) return g_reallocfn(ptr,oldsize,newsize);
+  else return realloc(ptr,newsize);*/
+  //return realloc(ptr,newsize);
+	void * newptr = gim_alloc(newsize);
+	size_t copysize = newsize> oldsize? oldsize: newsize;
+	memcpy(newptr,ptr,copysize);
+	gim_free(ptr,oldsize);
+	return newptr;
+}
+
+void gim_free(void *ptr, size_t size)
+{
+  if (!ptr) return;
+  if (g_freefn)
+  {
+       g_freefn(ptr,size);
+  }
+  else
+  {
+      free(ptr);//_mm_free(ptr);
+  }
+}
+
+///******************************* BUFFER MANAGERS ******************************///
+
+//!** Basic buffer prototyoe functions
+
+GUINT _system_buffer_alloc_function(GUINT size,int usage)
+{
+    void * newdata = gim_alloc(size);
+    memset(newdata,0,size);
+    return (GUINT)(newdata);
+}
+
+GUINT _system_buffer_alloc_data_function(const void * pdata,GUINT size,int usage)
+{
+    void * newdata = gim_alloc(size);
+    memcpy(newdata,pdata,size);
+    return (GUINT)(newdata);
+}
+
+GUINT _system_buffer_realloc_function(GUINT buffer_handle,GUINT oldsize,int old_usage,GUINT newsize,int new_usage)
+{
+    void * newdata = gim_realloc((void *)buffer_handle,oldsize,newsize);
+    return (GUINT)(newdata);
+}
+
+void _system_buffer_free_function(GUINT buffer_handle,GUINT size)
+{
+    gim_free((void*)buffer_handle,size);
+}
+
+char * _system_lock_buffer_function(GUINT buffer_handle,int access)
+{
+    return (char * )(buffer_handle);
+}
+
+
+void _system_unlock_buffer_function(GUINT buffer_handle)
+{
+}
+
+void _system_download_from_buffer_function(
+        GUINT source_buffer_handle,
+		GUINT source_pos,
+		void * destdata,
+		GUINT copysize)
+{
+    char * pdata;
+	pdata = (char *)source_buffer_handle;
+	memcpy(destdata,pdata+source_pos,copysize);
+}
+
+void  _system_upload_to_buffer_function(
+        GUINT dest_buffer_handle,
+		GUINT dest_pos,
+		void * sourcedata,
+		GUINT copysize)
+{
+    char * pdata;
+	pdata = (char * )dest_buffer_handle;
+	memcpy(pdata+dest_pos,sourcedata,copysize);
+}
+
+void  _system_copy_buffers_function(
+		GUINT source_buffer_handle,
+		GUINT source_pos,
+		GUINT dest_buffer_handle,
+		GUINT dest_pos,
+		GUINT copysize)
+{
+    char * pdata1,*pdata2;
+	pdata1 = (char *)source_buffer_handle;
+	pdata2 = (char *)dest_buffer_handle;
+	memcpy(pdata2+dest_pos,pdata1+source_pos,copysize);
+}
+
+GUINT _shared_buffer_alloc_function(GUINT size,int usage)
+{
+    return 0;
+}
+
+GUINT _shared_buffer_alloc_data_function(const void * pdata,GUINT size,int usage)
+{
+    return (GUINT)pdata;
+}
+
+GUINT _shared_buffer_realloc_function(GUINT buffer_handle,GUINT oldsize,int old_usage,GUINT newsize,int new_usage)
+{
+    return 0;
+}
+
+void _shared_buffer_free_function(GUINT buffer_handle,GUINT size)
+{
+}
+
+//!** Buffer manager operations
+void gim_create_buffer_manager(GBUFFER_MANAGER_PROTOTYPE * prototype,GUINT buffer_manager_id)
+{
+    GBUFFER_MANAGER_DATA * bm_data;
+    bm_data = &g_buffer_managers[buffer_manager_id];
+
+    if(bm_data->m_active==0)
+    {
+        if(g_buffer_managers_count<=buffer_manager_id)
+        {
+            g_buffer_managers_count = buffer_manager_id+1;
+        }
+    }
+    else
+    {
+        gim_destroy_buffer_manager(buffer_manager_id);
+    }
+    bm_data->m_active = 1;
+    //CREATE ARRAYS
+    GIM_DYNARRAY_CREATE(GBUFFER_DATA,bm_data->m_buffer_array,G_ARRAY_GROW_SIZE);
+    GIM_DYNARRAY_CREATE(GUINT,bm_data->m_free_positions,G_ARRAY_GROW_SIZE);
+    //INIT PROTOTYPE
+    bm_data->m_prototype.alloc_data_fn = prototype->alloc_data_fn;
+    bm_data->m_prototype.alloc_fn = prototype->alloc_fn;
+    bm_data->m_prototype.copy_buffers_fn = prototype->copy_buffers_fn;
+    bm_data->m_prototype.download_from_buffer_fn = prototype->download_from_buffer_fn;
+    bm_data->m_prototype.free_fn = prototype->free_fn;
+    bm_data->m_prototype.lock_buffer_fn = prototype->lock_buffer_fn;
+    bm_data->m_prototype.realloc_fn = prototype->realloc_fn;
+    bm_data->m_prototype.unlock_buffer_fn = prototype->unlock_buffer_fn;
+    bm_data->m_prototype.upload_to_buffer_fn = prototype->upload_to_buffer_fn;
+}
+
+GUINT gim_get_buffer_manager_count()
+{
+    return g_buffer_managers_count;
+}
+void gim_destroy_buffer_manager(GUINT buffer_manager_id)
+{
+    GBUFFER_MANAGER_DATA * bm_data;
+    gim_get_buffer_manager_data(buffer_manager_id,&bm_data);
+    if(bm_data == 0) return;
+    //Destroy all buffers
+
+    GBUFFER_DATA * buffers = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);
+    GUINT i, buffer_count = bm_data->m_buffer_array.m_size;
+    for (i=0;i<buffer_count ;i++ )
+    {
+    	if(buffers[i].m_buffer_handle!=0) //Is active
+    	{
+    	    // free handle
+    	    bm_data->m_prototype.free_fn(buffers[i].m_buffer_handle,buffers[i].m_size);
+    	}
+    }
+
+    //destroy buffer array
+    GIM_DYNARRAY_DESTROY(bm_data->m_buffer_array);
+    //destroy free positions
+    GIM_DYNARRAY_DESTROY(bm_data->m_free_positions);
+    //Mark as innactive
+    bm_data->m_active = 0;
+}
+void gim_get_buffer_manager_data(GUINT buffer_manager_id,GBUFFER_MANAGER_DATA ** pbm_data)
+{
+    GBUFFER_MANAGER_DATA * bm_data;
+    bm_data = &g_buffer_managers[buffer_manager_id];
+
+    if(bm_data->m_active==0)
+    {
+        *pbm_data = 0;
+    }
+    else
+    {
+        *pbm_data = bm_data;
+    }
+}
+
+void gim_init_buffer_managers()
+{
+    GUINT i;
+    for (i=0;i<MAX_BUFFER_MANAGERS;i++)
+    {
+        g_buffer_managers[i].m_active = 0;
+        g_buffer_managers[i].m_buffer_array.m_pdata = 0;
+        g_buffer_managers[i].m_buffer_array.m_reserve_size = 0;
+        g_buffer_managers[i].m_buffer_array.m_size = 0;
+        g_buffer_managers[i].m_free_positions.m_pdata = 0;
+        g_buffer_managers[i].m_free_positions.m_reserve_size = 0;
+        g_buffer_managers[i].m_free_positions.m_size = 0;
+    }
+    g_buffer_managers_count = 0;
+    // Add the two most important buffer managers
+    GBUFFER_MANAGER_PROTOTYPE prototype;
+
+    //add system buffer manager
+    prototype.alloc_data_fn = _system_buffer_alloc_data_function;
+    prototype.alloc_fn = _system_buffer_alloc_function;
+    prototype.copy_buffers_fn = _system_copy_buffers_function;
+    prototype.download_from_buffer_fn = _system_download_from_buffer_function;
+    prototype.free_fn = _system_buffer_free_function;
+    prototype.lock_buffer_fn = _system_lock_buffer_function;
+    prototype.realloc_fn = _system_buffer_realloc_function;
+    prototype.unlock_buffer_fn = _system_unlock_buffer_function;
+    prototype.upload_to_buffer_fn = _system_upload_to_buffer_function;
+
+    gim_create_buffer_manager(&prototype,G_BUFFER_MANAGER_SYSTEM );
+
+    //add zhared buffer manager
+    prototype.alloc_data_fn = _shared_buffer_alloc_data_function;
+    prototype.alloc_fn = _shared_buffer_alloc_function;
+    prototype.free_fn = _shared_buffer_free_function;
+    gim_create_buffer_manager(&prototype,G_BUFFER_MANAGER_SHARED);
+}
+
+void gim_terminate_buffer_managers()
+{
+    GUINT i;
+    for (i=0;i<g_buffer_managers_count;i++)
+    {
+        gim_destroy_buffer_manager(i);
+    }
+    g_buffer_managers_count = 0;
+}
+
+//!** Nuffer operations
+
+void GET_AVALIABLE_BUFFER_ID(GBUFFER_MANAGER_DATA * buffer_manager, GUINT & buffer_id)
+{
+    if(buffer_manager->m_free_positions.m_size>0)\
+    {
+        GUINT * _pointer = GIM_DYNARRAY_POINTER(GUINT,buffer_manager->m_free_positions);
+        buffer_id = _pointer[buffer_manager->m_free_positions.m_size-1];
+        GIM_DYNARRAY_POP_ITEM(buffer_manager->m_free_positions);
+    }
+    else
+    {
+        buffer_id = buffer_manager->m_buffer_array.m_size;
+        GIM_DYNARRAY_PUSH_EMPTY(GBUFFER_DATA,buffer_manager->m_buffer_array);
+    }
+}
+
+GINT _validate_buffer_id(GBUFFER_ID * buffer_id,GBUFFER_DATA ** ppbuffer,GBUFFER_MANAGER_DATA ** pbm_data)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    *ppbuffer = pbuffer;
+    *pbm_data = bm_data;
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GUINT gim_create_buffer(
+    GUINT buffer_manager_id,
+    GUINT buffer_size,
+    int usage,
+    GBUFFER_ID * buffer_id)
+{
+    VALIDATE_BUFFER_MANAGER(buffer_manager_id)
+
+    GUINT newbufferhandle = bm_data->m_prototype.alloc_fn(buffer_size,usage);
+    if(newbufferhandle==0) return G_BUFFER_OP_INVALID;
+
+    GET_AVALIABLE_BUFFER_ID(bm_data,buffer_id->m_buffer_id);
+    buffer_id->m_buffer_manager_id = buffer_manager_id;
+
+    GBUFFER_DATA * pbuffer = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);
+    pbuffer += buffer_id->m_buffer_id ;
+    pbuffer->m_buffer_handle = newbufferhandle;
+    pbuffer->m_size = buffer_size;
+    pbuffer->m_usage = usage;
+    pbuffer->m_lock_count = 0;
+    pbuffer->m_refcount = 0;
+    pbuffer->m_mapped_pointer = 0;
+
+    //set shadow buffer if needed
+
+    if(usage == G_MU_STATIC_READ ||
+			usage == G_MU_STATIC_READ_DYNAMIC_WRITE||
+			usage == G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
+    {
+        gim_create_common_buffer(buffer_size,&pbuffer->m_shadow_buffer);
+    }
+    else
+    {
+        pbuffer->m_shadow_buffer.m_buffer_id = G_UINT_INFINITY;
+        pbuffer->m_shadow_buffer.m_buffer_manager_id = G_UINT_INFINITY;
+    }
+    return G_BUFFER_OP_SUCCESS;
+}
+
+
+GUINT gim_create_buffer_from_data(
+    GUINT buffer_manager_id,
+    const void * pdata,
+    GUINT buffer_size,
+    int usage,
+    GBUFFER_ID * buffer_id)
+{
+    VALIDATE_BUFFER_MANAGER(buffer_manager_id)
+
+    GUINT newbufferhandle = bm_data->m_prototype.alloc_data_fn(pdata,buffer_size,usage);
+    if(newbufferhandle==0) return G_BUFFER_OP_INVALID;
+
+    GET_AVALIABLE_BUFFER_ID(bm_data,buffer_id->m_buffer_id);
+    buffer_id->m_buffer_manager_id = buffer_manager_id;
+
+    GBUFFER_DATA * pbuffer = GIM_DYNARRAY_POINTER(GBUFFER_DATA,bm_data->m_buffer_array);
+    pbuffer += buffer_id->m_buffer_id ;
+    pbuffer->m_buffer_handle = newbufferhandle;
+    pbuffer->m_size = buffer_size;
+    pbuffer->m_usage = usage;
+    pbuffer->m_lock_count = 0;
+    pbuffer->m_mapped_pointer = 0;
+    pbuffer->m_refcount = 0;
+
+    //set shadow buffer if needed
+
+    if(usage == G_MU_STATIC_READ ||
+			usage == G_MU_STATIC_READ_DYNAMIC_WRITE||
+			usage == G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
+    {
+        gim_create_common_buffer_from_data(pdata,buffer_size,&pbuffer->m_shadow_buffer);
+    }
+    else
+    {
+        pbuffer->m_shadow_buffer.m_buffer_id = G_UINT_INFINITY;
+        pbuffer->m_shadow_buffer.m_buffer_manager_id = G_UINT_INFINITY;
+    }
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GUINT gim_create_common_buffer(GUINT buffer_size, GBUFFER_ID * buffer_id)
+{
+    return gim_create_buffer(G_BUFFER_MANAGER_SYSTEM,buffer_size,G_MU_DYNAMIC_READ_WRITE,buffer_id);
+}
+
+GUINT gim_create_common_buffer_from_data(
+    const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id)
+{
+    return gim_create_buffer_from_data(G_BUFFER_MANAGER_SYSTEM,pdata,buffer_size,G_MU_DYNAMIC_READ_WRITE,buffer_id);
+}
+
+GUINT gim_create_shared_buffer_from_data(
+    const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id)
+{
+    return gim_create_buffer_from_data(G_BUFFER_MANAGER_SHARED,pdata,buffer_size,G_MU_DYNAMIC_READ_WRITE,buffer_id);
+}
+
+GINT gim_buffer_realloc(GBUFFER_ID * buffer_id,GUINT newsize)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    if(pbuffer->m_lock_count>0) return G_BUFFER_OP_INVALID;
+    GUINT newhandle = bm_data->m_prototype.realloc_fn(pbuffer->m_buffer_handle,pbuffer->m_size,pbuffer->m_usage,newsize,pbuffer->m_usage);
+    if(newhandle==0) return G_BUFFER_OP_INVALID;
+    pbuffer->m_buffer_handle = newhandle;
+    //realloc shadow buffer if any
+    gim_buffer_realloc(&pbuffer->m_shadow_buffer,newsize);
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_buffer_add_ref(GBUFFER_ID * buffer_id)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    pbuffer->m_refcount++;
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_buffer_free(GBUFFER_ID * buffer_id)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    if(pbuffer->m_lock_count>0) return G_BUFFER_OP_INVALID;
+    if(pbuffer->m_refcount>0) pbuffer->m_refcount--;
+    if(pbuffer->m_refcount>0) return G_BUFFER_OP_STILLREFCOUNTED;
+
+    bm_data->m_prototype.free_fn(pbuffer->m_buffer_handle,pbuffer->m_size);
+    //destroy shadow buffer if needed
+    gim_buffer_free(&pbuffer->m_shadow_buffer);
+    // Obtain a free slot index for a new buffer
+    GIM_DYNARRAY_PUSH_ITEM(GUINT,bm_data->m_free_positions,buffer_id->m_buffer_id);
+	pbuffer->m_buffer_handle = 0;
+	pbuffer->m_size = 0;
+	pbuffer->m_shadow_buffer.m_buffer_id = G_UINT_INFINITY;
+    pbuffer->m_shadow_buffer.m_buffer_manager_id = G_UINT_INFINITY;
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_lock_buffer(GBUFFER_ID * buffer_id,int access,char ** map_pointer)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    if(pbuffer->m_lock_count>0)
+    {
+        if(pbuffer->m_access!=access) return G_BUFFER_OP_INVALID;
+        pbuffer->m_lock_count++;
+        *map_pointer = pbuffer->m_mapped_pointer;
+        return G_BUFFER_OP_SUCCESS;
+    }
+
+    pbuffer->m_access = access;
+
+    GUINT result;
+    if(pbuffer->m_usage==G_MU_STATIC_WRITE)
+	{
+		*map_pointer = 0;///no access
+		return G_BUFFER_OP_INVALID;
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_READ)
+	{
+		if(pbuffer->m_access == G_MA_READ_ONLY)
+		{
+			result = gim_lock_buffer(&pbuffer->m_shadow_buffer,access,map_pointer);
+			if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+			pbuffer->m_mapped_pointer = *map_pointer;
+			pbuffer->m_lock_count++;
+		}
+		else
+		{
+			*map_pointer = 0;
+			return G_BUFFER_OP_INVALID;
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE)
+	{
+		if(pbuffer->m_access == G_MA_READ_ONLY)
+		{
+			result = gim_lock_buffer(&pbuffer->m_shadow_buffer,access,map_pointer);
+			if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+			pbuffer->m_mapped_pointer = *map_pointer;
+			pbuffer->m_lock_count++;
+		}
+		else if(pbuffer->m_access == G_MA_WRITE_ONLY)
+		{
+		    pbuffer->m_mapped_pointer = bm_data->m_prototype.lock_buffer_fn(pbuffer->m_buffer_handle,access);
+            *map_pointer = pbuffer->m_mapped_pointer;
+			pbuffer->m_lock_count++;
+		}
+		else if(pbuffer->m_access == G_MA_READ_WRITE)
+		{
+			*map_pointer = 0;
+			return G_BUFFER_OP_INVALID;
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
+	{
+		result = gim_lock_buffer(&pbuffer->m_shadow_buffer,access,map_pointer);
+        if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+        pbuffer->m_mapped_pointer = *map_pointer;
+        pbuffer->m_lock_count++;
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_WRITE_DYNAMIC_READ)
+	{
+		if(pbuffer->m_access == G_MA_READ_ONLY)
+		{
+			pbuffer->m_mapped_pointer = bm_data->m_prototype.lock_buffer_fn(pbuffer->m_buffer_handle,access);
+            *map_pointer = pbuffer->m_mapped_pointer;
+			pbuffer->m_lock_count++;
+		}
+		else
+		{
+			*map_pointer = 0;
+			return G_BUFFER_OP_INVALID;
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_DYNAMIC_READ_WRITE)
+	{
+		pbuffer->m_mapped_pointer = bm_data->m_prototype.lock_buffer_fn(pbuffer->m_buffer_handle,access);
+        *map_pointer = pbuffer->m_mapped_pointer;
+        pbuffer->m_lock_count++;
+	}
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_unlock_buffer(GBUFFER_ID * buffer_id)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    if(pbuffer->m_lock_count==0) return G_BUFFER_OP_INVALID;
+
+    if(pbuffer->m_lock_count>1)
+    {
+        pbuffer->m_lock_count--;
+        return G_BUFFER_OP_SUCCESS;
+    }
+
+
+    GUINT result;
+    if(pbuffer->m_usage==G_MU_STATIC_WRITE)
+	{
+		pbuffer->m_mapped_pointer = 0;
+        pbuffer->m_lock_count=0;
+        return G_BUFFER_OP_INVALID;
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_READ)
+	{
+		if(pbuffer->m_access == G_MA_READ_ONLY)
+		{
+			result = gim_unlock_buffer(&pbuffer->m_shadow_buffer);
+			if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+			pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+		}
+		else
+		{
+			pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+			return G_BUFFER_OP_INVALID;
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE)
+	{
+		if(pbuffer->m_access == G_MA_READ_ONLY)
+		{
+			result = gim_unlock_buffer(&pbuffer->m_shadow_buffer);
+			if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+			pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+		}
+		else if(pbuffer->m_access == G_MA_WRITE_ONLY)
+		{
+		    bm_data->m_prototype.unlock_buffer_fn(pbuffer->m_buffer_handle);
+            pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+		}
+		else if(pbuffer->m_access == G_MA_READ_WRITE)
+		{
+			pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+			return G_BUFFER_OP_INVALID;
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_READ_DYNAMIC_WRITE_COPY)
+	{
+	    result = gim_unlock_buffer(&pbuffer->m_shadow_buffer);
+        if(result!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+        pbuffer->m_mapped_pointer = 0;
+        pbuffer->m_lock_count=0;
+	    if(pbuffer->m_access == G_MA_WRITE_ONLY||pbuffer->m_access == G_MA_READ_WRITE)
+		{
+		    gim_copy_buffers(&pbuffer->m_shadow_buffer,0,buffer_id,0,pbuffer->m_size);
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_STATIC_WRITE_DYNAMIC_READ)
+	{
+		if(pbuffer->m_access == G_MA_READ_ONLY)
+		{
+			bm_data->m_prototype.unlock_buffer_fn(pbuffer->m_buffer_handle);
+            pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+		}
+		else
+		{
+			pbuffer->m_mapped_pointer = 0;
+			pbuffer->m_lock_count=0;
+			return G_BUFFER_OP_INVALID;
+		}
+	}
+	else if(pbuffer->m_usage==G_MU_DYNAMIC_READ_WRITE)
+	{
+		bm_data->m_prototype.unlock_buffer_fn(pbuffer->m_buffer_handle);
+        pbuffer->m_mapped_pointer = 0;
+        pbuffer->m_lock_count=0;
+	}
+	return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_get_buffer_size(GBUFFER_ID * buffer_id,GUINT * buffer_size)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    *buffer_size =  pbuffer->m_size;
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_get_buffer_is_locked(GBUFFER_ID * buffer_id,GUINT * lock_count)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    *lock_count =  pbuffer->m_lock_count;
+    return G_BUFFER_OP_SUCCESS;
+}
+
+
+GINT gim_download_from_buffer(
+        GBUFFER_ID * buffer_id,
+		GUINT source_pos,
+		void * destdata,
+		GUINT copysize)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    bm_data->m_prototype.download_from_buffer_fn(
+        pbuffer->m_buffer_handle,source_pos,destdata,copysize);
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT  gim_upload_to_buffer(
+		GBUFFER_ID * buffer_id,
+		GUINT dest_pos,
+		void * sourcedata,
+		GUINT copysize)
+{
+    VALIDATE_BUFFER_ID_PT(buffer_id)
+    bm_data->m_prototype.upload_to_buffer_fn(
+        pbuffer->m_buffer_handle,dest_pos,sourcedata,copysize);
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT  gim_copy_buffers(
+		GBUFFER_ID * source_buffer_id,
+		GUINT source_pos,
+		GBUFFER_ID * dest_buffer_id,
+		GUINT dest_pos,
+		GUINT copysize)
+{
+    GBUFFER_MANAGER_DATA * bm_data1,* bm_data2;
+    GBUFFER_DATA * pbuffer1, * pbuffer2;
+    void * tempdata;
+    if(_validate_buffer_id(source_buffer_id,&pbuffer1,&bm_data1)!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+
+    if(_validate_buffer_id(dest_buffer_id,&pbuffer2,&bm_data2)!= G_BUFFER_OP_SUCCESS) return G_BUFFER_OP_INVALID;
+
+    if((source_buffer_id->m_buffer_manager_id == dest_buffer_id->m_buffer_manager_id)||
+        (source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SYSTEM && dest_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SHARED)||
+        (source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SHARED && dest_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SYSTEM)
+    )
+    {//smooth copy
+        bm_data1->m_prototype.copy_buffers_fn(pbuffer1->m_buffer_handle,source_pos,pbuffer2->m_buffer_handle,dest_pos,copysize);
+    }
+    else if(source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SYSTEM || source_buffer_id->m_buffer_manager_id == G_BUFFER_MANAGER_SHARED)
+    {
+        //hard copy
+        tempdata = (void *)pbuffer1->m_buffer_handle;
+        //upload data
+        bm_data2->m_prototype.upload_to_buffer_fn(pbuffer2->m_buffer_handle,dest_pos,
+            tempdata,
+            copysize);
+    }
+    else
+    {
+        //very hard copy
+        void * tempdata = gim_alloc(copysize);
+        //download data
+        bm_data1->m_prototype.download_from_buffer_fn(pbuffer1->m_buffer_handle,source_pos,
+            tempdata,
+            copysize);
+
+        //upload data
+        bm_data2->m_prototype.upload_to_buffer_fn(pbuffer2->m_buffer_handle,dest_pos,
+            tempdata,
+            copysize);
+        //delete temp buffer
+        gim_free(tempdata,copysize);
+    }
+    return G_BUFFER_OP_SUCCESS;
+}
+
+GINT gim_buffer_array_lock(GBUFFER_ARRAY * array_data, int access)
+{
+    if(array_data->m_buffer_data != 0) return G_BUFFER_OP_SUCCESS;
+    GINT result = gim_lock_buffer(&array_data->m_buffer_id,access,&array_data->m_buffer_data);
+    if(result!= G_BUFFER_OP_SUCCESS) return result;
+    array_data->m_buffer_data += array_data->m_byte_offset;
+    return result;
+}
+
+GINT gim_buffer_array_unlock(GBUFFER_ARRAY * array_data)
+{
+    if(array_data->m_buffer_data == 0) return G_BUFFER_OP_SUCCESS;
+    GINT result = gim_unlock_buffer(&array_data->m_buffer_id);
+    if(result!= G_BUFFER_OP_SUCCESS) return result;
+    array_data->m_buffer_data = 0;
+    return result;
+}
+
+void gim_buffer_array_copy_ref(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY  * dest_data)
+{
+    dest_data->m_buffer_id.m_buffer_id = source_data->m_buffer_id.m_buffer_id;
+    dest_data->m_buffer_id.m_buffer_manager_id = source_data->m_buffer_id.m_buffer_manager_id;
+    dest_data->m_buffer_data = 0;
+    dest_data->m_byte_stride = source_data->m_byte_stride;
+    dest_data->m_byte_offset = source_data->m_byte_offset;
+    dest_data->m_element_count = source_data->m_element_count;
+    gim_buffer_add_ref(&dest_data->m_buffer_id);
+}
+
+void gim_buffer_array_copy_value(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY  * dest_data, GUINT buffer_manager_id,int usage)
+{
+    //Create new buffer
+    GUINT buffsize = source_data->m_element_count*source_data->m_byte_stride;
+    gim_create_buffer(buffer_manager_id,buffsize,usage,&dest_data->m_buffer_id);
+
+    //copy ref data
+    dest_data->m_buffer_data = 0;
+    dest_data->m_byte_stride = source_data->m_byte_stride;
+    dest_data->m_byte_offset = 0;
+    dest_data->m_element_count = source_data->m_element_count;
+    gim_buffer_add_ref(&dest_data->m_buffer_id);
+    //copy buffers
+    gim_copy_buffers(&source_data->m_buffer_id,source_data->m_byte_offset,&dest_data->m_buffer_id,0,buffsize);
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_tri_tri_overlap.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_tri_tri_overlap.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_tri_tri_overlap.cpp	(revision 216)
@@ -0,0 +1,251 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_trimesh.h"
+
+
+#define FABS(x) (float(fabs(x)))        /* implement as is fastest on your machine */
+
+/* some macros */
+
+#define CLASSIFY_TRIPOINTS_BY_FACE(v1,v2,v3,faceplane,out_of_face)\
+{   \
+    _distances[0] = DISTANCE_PLANE_POINT(faceplane,v1);\
+    _distances[1] =  _distances[0] * DISTANCE_PLANE_POINT(faceplane,v2);\
+    _distances[2] =  _distances[0] * DISTANCE_PLANE_POINT(faceplane,v3); \
+	if(_distances[1]>0.0f && _distances[2]>0.0f)\
+	{\
+	    out_of_face = 1;\
+	}\
+	else\
+	{\
+	    out_of_face = 0;\
+	}\
+}\
+
+/* sort so that a<=b */
+#define SORT(a,b)       \
+             if(a>b)    \
+             {          \
+               float c; \
+               c=a;     \
+               a=b;     \
+               b=c;     \
+             }
+
+
+/* this edge to edge test is based on Franlin Antonio's gem:
+   "Faster Line Segment Intersection", in Graphics Gems III,
+   pp. 199-202 */
+#define EDGE_EDGE_TEST(V0,U0,U1)                      \
+  Bx=U0[i0]-U1[i0];                                   \
+  By=U0[i1]-U1[i1];                                   \
+  Cx=V0[i0]-U0[i0];                                   \
+  Cy=V0[i1]-U0[i1];                                   \
+  f=Ay*Bx-Ax*By;                                      \
+  d=By*Cx-Bx*Cy;                                      \
+  if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f))  \
+  {                                                   \
+    e=Ax*Cy-Ay*Cx;                                    \
+    if(f>0)                                           \
+    {                                                 \
+      if(e>=0 && e<=f) return 1;                      \
+    }                                                 \
+    else                                              \
+    {                                                 \
+      if(e<=0 && e>=f) return 1;                      \
+    }                                                 \
+  }
+
+#define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
+{                                              \
+  float Ax,Ay,Bx,By,Cx,Cy,e,d,f;               \
+  Ax=V1[i0]-V0[i0];                            \
+  Ay=V1[i1]-V0[i1];                            \
+  /* test edge U0,U1 against V0,V1 */          \
+  EDGE_EDGE_TEST(V0,U0,U1);                    \
+  /* test edge U1,U2 against V0,V1 */          \
+  EDGE_EDGE_TEST(V0,U1,U2);                    \
+  /* test edge U2,U1 against V0,V1 */          \
+  EDGE_EDGE_TEST(V0,U2,U0);                    \
+}
+
+#define POINT_IN_TRI(V0,U0,U1,U2)           \
+{                                           \
+  float a,b,c,d0,d1,d2;                     \
+  /* is T1 completly inside T2? */          \
+  /* check if V0 is inside tri(U0,U1,U2) */ \
+  a=U1[i1]-U0[i1];                          \
+  b=-(U1[i0]-U0[i0]);                       \
+  c=-a*U0[i0]-b*U0[i1];                     \
+  d0=a*V0[i0]+b*V0[i1]+c;                   \
+                                            \
+  a=U2[i1]-U1[i1];                          \
+  b=-(U2[i0]-U1[i0]);                       \
+  c=-a*U1[i0]-b*U1[i1];                     \
+  d1=a*V0[i0]+b*V0[i1]+c;                   \
+                                            \
+  a=U0[i1]-U2[i1];                          \
+  b=-(U0[i0]-U2[i0]);                       \
+  c=-a*U2[i0]-b*U2[i1];                     \
+  d2=a*V0[i0]+b*V0[i1]+c;                   \
+  if(d0*d1>0.0)                             \
+  {                                         \
+    if(d0*d2>0.0) return 1;                 \
+  }                                         \
+}
+
+int coplanar_tri_tri(GIM_TRIANGLE_DATA *tri1,
+                    GIM_TRIANGLE_DATA *tri2)
+{
+   short i0,i1;
+   /* first project onto an axis-aligned plane, that maximizes the area */
+   /* of the triangles, compute indices: i0,i1. */
+   PLANE_MINOR_AXES(tri1->m_planes.m_planes[0], i0, i1);
+
+    /* test all edges of triangle 1 against the edges of triangle 2 */
+    EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[0],tri1->m_vertices[1],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
+    EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
+    EDGE_AGAINST_TRI_EDGES(tri1->m_vertices[2],tri1->m_vertices[0],tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2]);
+
+    /* finally, test if tri1 is totally contained in tri2 or vice versa */
+    POINT_IN_HULL(tri1->m_vertices[0],(&tri2->m_planes.m_planes[1]),3,i0);
+    if(i0==0) return 1;
+
+    POINT_IN_HULL(tri2->m_vertices[0],(&tri1->m_planes.m_planes[1]),3,i0);
+    if(i0==0) return 1;
+
+    return 0;
+}
+
+
+
+#define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
+{ \
+        if(D0D1>0.0f) \
+        { \
+                /* here we know that D0D2<=0.0 */ \
+            /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
+                A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
+        } \
+        else if(D0D2>0.0f)\
+        { \
+                /* here we know that d0d1<=0.0 */ \
+            A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
+        } \
+        else if(D1*D2>0.0f || D0!=0.0f) \
+        { \
+                /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
+                A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
+        } \
+        else if(D1!=0.0f) \
+        { \
+                A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
+        } \
+        else if(D2!=0.0f) \
+        { \
+                A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
+        } \
+        else \
+        { \
+                /* triangles are coplanar */ \
+                return coplanar_tri_tri(tri1,tri2); \
+        } \
+}\
+
+
+
+int gim_triangle_triangle_overlap(
+							GIM_TRIANGLE_DATA *tri1,
+							GIM_TRIANGLE_DATA *tri2)
+{
+    vec3f _distances;
+    char out_of_face;
+    CLASSIFY_TRIPOINTS_BY_FACE(tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_planes.m_planes[0],out_of_face);
+    if(out_of_face==1) return 0;
+
+    CLASSIFY_TRIPOINTS_BY_FACE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[0],out_of_face);
+    if(out_of_face==1) return 0;
+
+
+    float du0=0,du1=0,du2=0,dv0=0,dv1=0,dv2=0;
+    float D[3];
+    float isect1[2], isect2[2];
+    float du0du1=0,du0du2=0,dv0dv1=0,dv0dv2=0;
+    short index;
+    float vp0,vp1,vp2;
+    float up0,up1,up2;
+    float bb,cc,max;
+
+    /* compute direction of intersection line */
+    VEC_CROSS(D,tri1->m_planes.m_planes[0],tri2->m_planes.m_planes[0]);
+
+    /* compute and index to the largest component of D */
+    max=(float)FABS(D[0]);
+    index=0;
+    bb=(float)FABS(D[1]);
+    cc=(float)FABS(D[2]);
+    if(bb>max) max=bb,index=1;
+    if(cc>max) max=cc,index=2;
+
+     /* this is the simplified projection onto L*/
+     vp0= tri1->m_vertices[0][index];
+     vp1= tri1->m_vertices[1][index];
+     vp2= tri1->m_vertices[2][index];
+
+     up0= tri2->m_vertices[0][index];
+     up1= tri2->m_vertices[1][index];
+     up2= tri2->m_vertices[2][index];
+
+    /* compute interval for triangle 1 */
+    float a,b,c,x0,x1;
+    NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
+
+    /* compute interval for triangle 2 */
+    float d,e,f,y0,y1;
+    NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
+
+    float xx,yy,xxyy,tmp;
+    xx=x0*x1;
+    yy=y0*y1;
+    xxyy=xx*yy;
+
+    tmp=a*xxyy;
+    isect1[0]=tmp+b*x1*yy;
+    isect1[1]=tmp+c*x0*yy;
+
+    tmp=d*xxyy;
+    isect2[0]=tmp+e*xx*y1;
+    isect2[1]=tmp+f*xx*y0;
+
+    SORT(isect1[0],isect1[1]);
+    SORT(isect2[0],isect2[1]);
+
+    if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
+    return 1;
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh.cpp	(revision 216)
@@ -0,0 +1,364 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include <assert.h>
+#include "GIMPACT/gim_trimesh.h"
+
+GUINT gim_trimesh_get_triangle_count(GIM_TRIMESH * trimesh)
+{
+    return trimesh->m_tri_index_buffer.m_element_count/3;
+}
+
+//! Creates the aabb set and the triangles cache
+/*!
+
+\param trimesh
+\param vertex_array
+\param triindex_array
+\param transformed_reply If 1, then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array.
+\post it copies the arrays by reference, and creates the auxiliary data (m_aabbset,m_planes_cache_buffer)
+*/
+void gim_trimesh_create_from_arrays(GIM_TRIMESH * trimesh, GBUFFER_ARRAY * vertex_array, GBUFFER_ARRAY * triindex_array,char transformed_reply)
+{
+    assert(trimesh);
+    assert(vertex_array);
+    assert(triindex_array);
+    gim_buffer_array_copy_ref(vertex_array,&trimesh->m_source_vertex_buffer);
+    gim_buffer_array_copy_ref(triindex_array,&trimesh->m_tri_index_buffer);
+
+    trimesh->m_mask = GIM_TRIMESH_NEED_UPDATE;//needs update
+    //Create the transformed vertices
+    if(transformed_reply==1)
+    {
+        trimesh->m_mask |= GIM_TRIMESH_TRANSFORMED_REPLY;
+        gim_buffer_array_copy_value(vertex_array,&trimesh->m_transformed_vertex_buffer,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE);
+    }
+    else
+    {
+        gim_buffer_array_copy_ref(vertex_array,&trimesh->m_transformed_vertex_buffer);
+    }
+    //create the box set
+    GUINT facecount = gim_trimesh_get_triangle_count(trimesh);
+
+    gim_aabbset_alloc(&trimesh->m_aabbset,facecount);
+    //create the planes cache
+    GIM_DYNARRAY_CREATE_SIZED(GIM_TRIPLANES_CACHE,trimesh->m_planes_cache_buffer,facecount);
+    //Create the bitset
+    GIM_BITSET_CREATE_SIZED(trimesh->m_planes_cache_bitset,facecount);
+    //Callback is 0
+    trimesh->m_update_callback = 0;
+    //set to identity
+    IDENTIFY_MATRIX_4X4(trimesh->m_transform);
+}
+
+
+
+//! Create a trimesh from vertex array and an index array
+/*!
+
+\param trimesh An uninitialized GIM_TRIMESH  structure
+\param vertex_array A buffer to a vec3f array
+\param vertex_count
+\param triindex_array
+\param index_count
+\param copy_vertices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data.
+\param copy_indices If 1, it copies the source vertices in another buffer. Else (0) it constructs a reference to the data.
+\param transformed_reply If , then the m_transformed_vertices is a reply of the source vertices. Else it just be a reference to the original array.
+*/
+void gim_trimesh_create_from_data(GIM_TRIMESH * trimesh, vec3f * vertex_array, GUINT vertex_count,char copy_vertices, GUINT * triindex_array, GUINT index_count,char copy_indices,char transformed_reply)
+{
+    GBUFFER_ARRAY buffer_vertex_array;
+    GBUFFER_ARRAY buffer_triindex_array;
+
+    //Create vertices
+    if(copy_vertices == 1)
+    {
+        gim_create_common_buffer_from_data(vertex_array, vertex_count*sizeof(vec3f), &buffer_vertex_array.m_buffer_id);
+    }
+    else//Create a shared buffer
+    {
+        gim_create_shared_buffer_from_data(vertex_array, vertex_count*sizeof(vec3f), &buffer_vertex_array.m_buffer_id);
+    }
+    GIM_BUFFER_ARRAY_INIT_TYPE(vec3f,buffer_vertex_array,buffer_vertex_array.m_buffer_id,vertex_count);
+
+
+    //Create vertices
+    if(copy_indices == 1)
+    {
+        gim_create_common_buffer_from_data(triindex_array, index_count*sizeof(GUINT), &buffer_triindex_array.m_buffer_id);
+    }
+    else//Create a shared buffer
+    {
+        gim_create_shared_buffer_from_data(triindex_array, index_count*sizeof(GUINT), &buffer_triindex_array.m_buffer_id);
+    }
+    GIM_BUFFER_ARRAY_INIT_TYPE(GUINT,buffer_triindex_array,buffer_triindex_array.m_buffer_id,index_count);
+
+    gim_trimesh_create_from_arrays(trimesh, &buffer_vertex_array, &buffer_triindex_array,transformed_reply);
+
+    ///always call this after create a buffer_array
+    GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array);
+    GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array);
+}
+
+//! Clears auxiliary data and releases buffer arrays
+void gim_trimesh_destroy(GIM_TRIMESH * trimesh)
+{
+    gim_aabbset_destroy(&trimesh->m_aabbset);
+
+    GIM_DYNARRAY_DESTROY(trimesh->m_planes_cache_buffer);
+    GIM_DYNARRAY_DESTROY(trimesh->m_planes_cache_bitset);
+
+    GIM_BUFFER_ARRAY_DESTROY(trimesh->m_transformed_vertex_buffer);
+    GIM_BUFFER_ARRAY_DESTROY(trimesh->m_source_vertex_buffer);
+    GIM_BUFFER_ARRAY_DESTROY(trimesh->m_tri_index_buffer);
+}
+
+//! Copies two meshes
+/*!
+\pre dest_trimesh shouldn't be created
+\post dest_trimesh will be created
+\param source_trimesh
+\param dest_trimesh
+\param copy_by_reference If 1, it attach a reference to the source vertices, else it copies the vertices
+\param transformed_reply IF 1, then it forces the m_trasnformed_vertices to be  a reply of the source vertices
+*/
+void gim_trimesh_copy(GIM_TRIMESH * source_trimesh,GIM_TRIMESH * dest_trimesh, char copy_by_reference, char transformed_reply)
+{
+    if(copy_by_reference==1)
+    {
+        gim_trimesh_create_from_arrays(dest_trimesh, &source_trimesh->m_source_vertex_buffer, &source_trimesh->m_tri_index_buffer,transformed_reply);
+    }
+    else
+    {
+        GBUFFER_ARRAY buffer_vertex_array;
+        GBUFFER_ARRAY buffer_triindex_array;
+
+        gim_buffer_array_copy_value(&source_trimesh->m_source_vertex_buffer,&buffer_vertex_array,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE);
+
+        gim_buffer_array_copy_value(&source_trimesh->m_tri_index_buffer,&buffer_triindex_array,G_BUFFER_MANAGER_SYSTEM,G_MU_DYNAMIC_READ_WRITE);
+
+        gim_trimesh_create_from_arrays(dest_trimesh, &buffer_vertex_array, &buffer_triindex_array,transformed_reply);
+
+        ///always call this after create a buffer_array
+        GIM_BUFFER_ARRAY_DESTROY(buffer_vertex_array);
+        GIM_BUFFER_ARRAY_DESTROY(buffer_triindex_array);
+    }
+}
+
+//! Locks the trimesh for working with it
+/*!
+\post locks m_tri_index_buffer and m_transformed_vertex_buffer.
+\param trimesh
+*/
+void gim_trimesh_locks_work_data(GIM_TRIMESH * trimesh)
+{
+    GINT res;
+    res=gim_buffer_array_lock(&trimesh->m_tri_index_buffer,G_MA_READ_ONLY);
+    assert(res==G_BUFFER_OP_SUCCESS);
+    res=gim_buffer_array_lock(&trimesh->m_transformed_vertex_buffer,G_MA_READ_ONLY);
+    assert(res==G_BUFFER_OP_SUCCESS);
+}
+
+//! unlocks the trimesh
+/*!
+\post unlocks m_tri_index_buffer and m_transformed_vertex_buffer.
+\param trimesh
+*/
+void gim_trimesh_unlocks_work_data(GIM_TRIMESH * trimesh)
+{
+    gim_buffer_array_unlock(&trimesh->m_tri_index_buffer);
+    gim_buffer_array_unlock(&trimesh->m_transformed_vertex_buffer);
+}
+
+
+//! Returns 1 if the m_transformed_vertex_buffer is a reply of m_source_vertex_buffer
+char gim_trimesh_has_tranformed_reply(GIM_TRIMESH * trimesh)
+{
+    if(trimesh->m_mask&GIM_TRIMESH_TRANSFORMED_REPLY) return 1;
+    return 0;
+}
+
+//! Returns 1 if the trimesh needs to update their aabbset and the planes cache.
+char gim_trimesh_needs_update(GIM_TRIMESH * trimesh)
+{
+    if(trimesh->m_mask&GIM_TRIMESH_NEED_UPDATE) return 1;
+    return 0;
+}
+
+//! Change the state of the trimesh for force it to update
+/*!
+Call it after made changes to the trimesh.
+\post gim_trimesh_need_update(trimesh) will return 1
+*/
+void gim_trimesh_post_update(GIM_TRIMESH * trimesh)
+{
+    trimesh->m_mask |= GIM_TRIMESH_NEED_UPDATE;
+}
+
+//kernel
+#define MULT_MAT_VEC4_KERNEL(_mat,_src,_dst) MAT_DOT_VEC_3X4((_dst),(_mat),(_src))
+
+//! Updates m_transformed_vertex_buffer
+/*!
+\pre m_transformed_vertex_buffer must be unlocked
+*/
+void gim_trimesh_update_vertices(GIM_TRIMESH * trimesh)
+{
+    if(gim_trimesh_has_tranformed_reply(trimesh) == 0) return; //Don't perform transformation
+
+    //Vertices
+    GBUFFER_ARRAY * psource_vertex_buffer = &trimesh->m_source_vertex_buffer;
+    GBUFFER_ARRAY * ptransformed_vertex_buffer = &trimesh->m_transformed_vertex_buffer;
+    //Temp transform
+    mat4f transform;
+    COPY_MATRIX_4X4(transform,trimesh->m_transform);
+
+    GIM_PROCESS_BUFFER_ARRAY(transform,(*psource_vertex_buffer),(*ptransformed_vertex_buffer),MULT_MAT_VEC4_KERNEL,vec3f,vec3f);
+}
+
+//! Updates m_aabbset and m_planes_cache_bitset
+/*!
+\pre gim_trimesh_locks_work_data must be called before
+*/
+void gim_trimesh_update_aabbset(GIM_TRIMESH * trimesh)
+{
+    vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);
+    assert(transformed_vertices);
+
+    GUINT * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT,trimesh->m_tri_index_buffer,0);
+    assert(triangle_indices);
+    // box set
+    aabb3f * paabb = trimesh->m_aabbset.m_boxes;
+    GUINT triangle_count = gim_trimesh_get_triangle_count(trimesh);
+    float * v1,*v2,*v3;
+    GUINT i;
+    for (i=0; i<triangle_count;i++)
+    {
+        v1 = &transformed_vertices[triangle_indices[0]][0];
+        v2 = &transformed_vertices[triangle_indices[1]][0];
+        v3 = &transformed_vertices[triangle_indices[2]][0];
+        COMPUTEAABB_FOR_TRIANGLE((*paabb),v1,v2,v3);
+        triangle_indices+=3;
+        paabb++;
+    }
+    //Clear planes cache
+    GIM_BITSET_CLEAR_ALL(trimesh->m_planes_cache_bitset);
+    //Sorts set
+    gim_aabbset_update(&trimesh->m_aabbset);
+}
+
+//! Updates the trimesh if needed
+/*!
+\post If gim_trimesh_needs_update returns 1, then it calls  gim_trimesh_update_vertices and gim_trimesh_update_aabbset
+*/
+void gim_trimesh_update(GIM_TRIMESH * trimesh)
+{
+    if(gim_trimesh_needs_update(trimesh)==0) return;
+    gim_trimesh_update_vertices(trimesh);
+    gim_trimesh_locks_work_data(trimesh);
+    gim_trimesh_update_aabbset(trimesh);
+    gim_trimesh_unlocks_work_data(trimesh);
+
+    //Clear update flag
+     trimesh->m_mask &= ~GIM_TRIMESH_NEED_UPDATE;
+}
+
+void gim_trimesh_set_tranform(GIM_TRIMESH * trimesh, mat4f transform)
+{
+    GREAL diff = 0.0f;
+    float * originaltrans = &trimesh->m_transform[0][0];
+    float * newtrans = &transform[0][0];
+    GUINT i;
+    for (i=0;i<16;i++)
+    {
+    	diff += fabs(originaltrans[i]-newtrans[i]);
+    }
+
+//    if(IS_ZERO(diff)) return ;///don't need to update
+    if(diff< 0.00001f) return ;///don't need to update
+
+    COPY_MATRIX_4X4(trimesh->m_transform,transform);
+
+    gim_trimesh_post_update(trimesh);
+}
+
+void gim_trimesh_get_triangle_data(GIM_TRIMESH * trimesh, GUINT triangle_index, GIM_TRIANGLE_DATA * tri_data)
+{
+    vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);
+
+    GUINT * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT,trimesh->m_tri_index_buffer,triangle_index*3);
+
+
+    //Copy the vertices
+    VEC_COPY(tri_data->m_vertices[0],transformed_vertices[triangle_indices[0]]);
+    VEC_COPY(tri_data->m_vertices[1],transformed_vertices[triangle_indices[1]]);
+    VEC_COPY(tri_data->m_vertices[2],transformed_vertices[triangle_indices[2]]);
+
+    //Get the planes
+    GIM_TRIPLANES_CACHE * planes = GIM_DYNARRAY_POINTER(GIM_TRIPLANES_CACHE,trimesh->m_planes_cache_buffer);
+    planes += triangle_index;
+
+    //verify planes cache
+    GUINT bit_eval;
+    GIM_BITSET_GET(trimesh->m_planes_cache_bitset,triangle_index,bit_eval);
+    if(bit_eval == 0)// Needs to calc the planes
+    {
+        //Calc the face plane
+        TRIANGLE_PLANE(tri_data->m_vertices[0],tri_data->m_vertices[1],tri_data->m_vertices[2],planes->m_planes[0]);
+        //Calc the edge 1
+        EDGE_PLANE(tri_data->m_vertices[0],tri_data->m_vertices[1],(planes->m_planes[0]),(planes->m_planes[1]));
+
+        //Calc the edge 2
+        EDGE_PLANE(tri_data->m_vertices[1],tri_data->m_vertices[2],(planes->m_planes[0]),(planes->m_planes[2]));
+
+        //Calc the edge 3
+        EDGE_PLANE(tri_data->m_vertices[2],tri_data->m_vertices[0],(planes->m_planes[0]), (planes->m_planes[3]));
+
+        //mark
+        GIM_BITSET_SET(trimesh->m_planes_cache_bitset,triangle_index);
+    }
+
+
+    VEC_COPY_4((tri_data->m_planes.m_planes[0]),(planes->m_planes[0]));//face plane
+    VEC_COPY_4((tri_data->m_planes.m_planes[1]),(planes->m_planes[1]));//edge1
+    VEC_COPY_4((tri_data->m_planes.m_planes[2]),(planes->m_planes[2]));//edge2
+    VEC_COPY_4((tri_data->m_planes.m_planes[3]),(planes->m_planes[3]));//edge3
+}
+
+void gim_trimesh_get_triangle_vertices(GIM_TRIMESH * trimesh, GUINT triangle_index, vec3f v1,vec3f v2,vec3f v3)
+{
+    vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);
+
+    GUINT * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT,trimesh->m_tri_index_buffer,triangle_index*3);
+
+    //Copy the vertices
+    VEC_COPY(v1,transformed_vertices[triangle_indices[0]]);
+    VEC_COPY(v2,transformed_vertices[triangle_indices[1]]);
+    VEC_COPY(v3,transformed_vertices[triangle_indices[2]]);
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_capsule_collision.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_capsule_collision.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_capsule_collision.cpp	(revision 216)
@@ -0,0 +1,279 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_trimesh.h"
+
+//! Utility function for find the closest point between a segment and a triangle
+/*!
+
+\param triangle
+\param s1
+\param s2
+\param contacts Contains the closest points on the segment (1,2), and the normal points to segment, and m_depth contains the distance
+
+\post The contacts array is not set to 0. It adds aditional contacts
+*/
+void gim_closest_point_triangle_segment(GIM_TRIANGLE_DATA * triangle, vec3f s1,vec3f s2, GDYNAMIC_ARRAY * contacts)
+{
+    vec3f segment_points[4];
+    vec3f closest_points[2];
+    GUINT intersection_type, out_edge= 10;
+    GREAL dis, dis_temp,perpend;
+    vec4f sdiff;
+
+    dis = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s1);
+    dis_temp = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s2);
+
+    if(dis<=0.0f && dis_temp<=0.0f) return;
+
+    VEC_DIFF(sdiff,s2,s1);
+    perpend = VEC_DOT(sdiff,triangle->m_planes.m_planes[0]);
+
+    if(!IS_ZERO(perpend)) // Not perpendicular
+    {
+        if(dis<dis_temp)
+        {
+            VEC_COPY(closest_points[0],s1);
+        }
+        else
+        {
+            dis = dis_temp;
+            VEC_COPY(closest_points[0],s2);
+        }
+
+        //Testing segment vertices over triangle
+        if(dis>=0.0f && dis_temp>=0.0f)
+        {
+            POINT_IN_HULL(closest_points[0],(&triangle->m_planes.m_planes[1]),3,out_edge);
+
+            if(out_edge==0)//Point over face
+            {
+                GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
+                return;
+            }
+        }
+        else
+        {
+
+            PLANE_CLIP_SEGMENT(s1,s2,triangle->m_planes.m_planes[0],closest_points[1]);
+
+            POINT_IN_HULL(closest_points[1],(&triangle->m_planes.m_planes[1]),3,out_edge);
+
+            if(out_edge==0)//Point over face
+            {
+                GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
+                return;
+            }
+        }
+
+    }
+    else // Perpendicular Face
+    {
+        //out_edge=10
+        //Clip segment by triangle
+    //    Edge1
+        PLANE_CLIP_SEGMENT_CLOSEST(s1,s2,triangle->m_planes.m_planes[1],segment_points[0],segment_points[1],intersection_type);
+        if(intersection_type==0||intersection_type==1)
+        {
+            out_edge = 0;
+            VEC_COPY(closest_points[0],segment_points[0]);
+        }
+        else
+        {
+            //Edge2
+            PLANE_CLIP_SEGMENT_CLOSEST(segment_points[0],segment_points[1],triangle->m_planes.m_planes[2],segment_points[2],segment_points[3],intersection_type);
+            if(intersection_type==0||intersection_type==1)
+            {
+                out_edge = 1;
+                VEC_COPY(closest_points[0],segment_points[3]);
+            }
+            else
+            {
+                //Edge3
+                PLANE_CLIP_SEGMENT_CLOSEST(segment_points[2],segment_points[3],triangle->m_planes.m_planes[3],closest_points[0],closest_points[1],intersection_type);
+                if(intersection_type==0||intersection_type==1)
+                {
+                    out_edge = 2;
+                }
+            }
+        }
+        //POST closest_points[0] and closest_points[1] are inside the triangle, if out_edge>2
+        if(out_edge>2) // Over triangle
+        {
+            dis = VEC_DOT(closest_points[0],triangle->m_planes.m_planes[0]);
+            GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
+            GIM_PUSH_CONTACT((*contacts),closest_points[1] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
+            return;
+        }
+    }
+
+    //Find closest edges
+    out_edge = 10;
+    dis = G_REAL_INFINITY;
+    GUINT i;
+    for(i=0;i<3;i++)
+    {
+        SEGMENT_COLLISION(s1,s2,triangle->m_vertices[i],triangle->m_vertices[(i+1)%3],segment_points[0],segment_points[1]);
+        VEC_DIFF(sdiff,segment_points[0],segment_points[1]);
+        dis_temp = VEC_DOT(sdiff,sdiff);
+        if(dis_temp< dis)
+        {
+            dis = dis_temp;
+            out_edge = i;
+            VEC_COPY(closest_points[0],segment_points[0]);
+            VEC_COPY(closest_points[1],sdiff);//normal
+        }
+    }
+    if(out_edge>2) return ;// ???? ASSERT this please
+
+    if(IS_ZERO(dis))
+    {
+        //Set face plane
+        GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,0.0f,0, 0, 0,0);
+
+    }
+    else
+    {
+        GIM_SQRT(dis,dis);
+        VEC_SCALE(closest_points[1],(1.0f/dis),closest_points[1]);//normal
+        GIM_PUSH_CONTACT((*contacts),closest_points[0] ,closest_points[1],dis,0, 0, 0,0);
+    }
+}
+
+
+//! Utility function for find the closest point between a capsule and a triangle
+/*!
+
+\param triangle
+\param capsule
+\param contacts Contains the closest points on the capsule, and the normal points to triangle
+
+\post The contacts array is not set to 0. It adds aditional contacts
+*/
+int gim_triangle_capsule_collision(GIM_TRIANGLE_DATA * triangle, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
+{
+    GUINT old_contact_size = contacts->m_size;
+    gim_closest_point_triangle_segment(triangle,capsule->m_point1,capsule->m_point2,contacts);
+    GIM_CONTACT * pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,(*contacts));
+    pcontact+= old_contact_size;
+
+    if(pcontact->m_depth > capsule->m_radius)
+    {
+        contacts->m_size = old_contact_size;
+        return 0;
+    }
+
+    vec3f vec;
+    while(old_contact_size<contacts->m_size)
+    {
+        //Scale the normal for pointing to triangle
+        VEC_SCALE(pcontact->m_normal,-1.0f,pcontact->m_normal);
+        //Fix the contact point
+        VEC_SCALE(vec,capsule->m_radius,pcontact->m_normal);
+        VEC_SUM(pcontact->m_point,vec,pcontact->m_point);
+        //Fix the depth
+        pcontact->m_depth = capsule->m_radius - pcontact->m_depth;
+
+        pcontact++;
+        old_contact_size++;
+    }
+
+    return 1;
+}
+
+
+//! Trimesh Capsule collision
+/*!
+Find the closest primitive collided by the ray
+\param trimesh
+\param capsule
+\param contact
+\param contacts A GIM_CONTACT array. Must be initialized
+*/
+void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
+{
+    contacts->m_size = 0;
+
+    aabb3f test_aabb;
+    CALC_CAPSULE_AABB((*capsule),test_aabb);
+
+	GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_BOXQUERY_LIST(collision_result);
+
+	gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result);
+
+	if(collision_result.m_size==0)
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	}
+
+	//collide triangles
+	//Locks trimesh
+	gim_trimesh_locks_work_data(trimesh);
+	 //dummy contacts
+    GDYNAMIC_ARRAY dummycontacts;
+    GIM_CREATE_CONTACT_LIST(dummycontacts);
+
+	int cresult;
+	unsigned int i;
+	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
+	GIM_TRIANGLE_DATA tri_data;
+	GUINT old_contact_size;
+	GIM_CONTACT * pcontact;
+
+	for(i=0;i<collision_result.m_size;i++)
+	{
+	    old_contact_size = dummycontacts.m_size;
+		gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
+		cresult = gim_triangle_capsule_collision(&tri_data, capsule, &dummycontacts);
+		if(cresult!=0)
+		{
+		    pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,dummycontacts);
+            pcontact+= old_contact_size;
+		    while(old_contact_size<dummycontacts.m_size)
+            {
+                pcontact->m_handle1 = trimesh;
+                pcontact->m_handle2 = capsule;
+                pcontact->m_feature1 = boxesresult[i];
+                pcontact->m_feature2 = 0;
+                pcontact++;
+                old_contact_size++;
+            }
+		}
+	}
+	///unlocks
+	gim_trimesh_unlocks_work_data(trimesh);
+	///Destroy box result
+	GIM_DYNARRAY_DESTROY(collision_result);
+
+	 //merge contacts
+    gim_merge_contacts(&dummycontacts,contacts);
+
+    //Destroy dummy
+    GIM_DYNARRAY_DESTROY(dummycontacts);
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_ray_collision.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_ray_collision.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_ray_collision.cpp	(revision 216)
@@ -0,0 +1,140 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_trimesh.h"
+
+
+//! Trimesh Ray Collisions
+/*!
+
+\param trimesh
+\param contact
+\return 1 if the ray collides, else 0
+*/
+int gim_trimesh_ray_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact)
+{
+    GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_BOXQUERY_LIST(collision_result);
+
+	gim_aabbset_ray_collision(origin,dir,tmax,&trimesh->m_aabbset,&collision_result);
+
+	if(collision_result.m_size==0)
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	    return 0;
+	}
+
+	//collide triangles
+
+	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
+	GIM_TRIANGLE_DATA  tridata;
+	vec3f pout;
+	GREAL tparam,u,v;
+	char does_intersect;
+
+	gim_trimesh_locks_work_data(trimesh);
+
+	for(unsigned int i=0;i<collision_result.m_size;i++)
+	{
+		gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tridata);
+
+		RAY_TRIANGLE_INTERSECTION(origin,dir,tridata.m_vertices[0],tridata.m_vertices[1],tridata.m_vertices[2],tridata.m_planes.m_planes[0],pout,u,v,tparam,tmax,does_intersect);
+		if(does_intersect)
+		{
+		    contact->tparam = tparam;
+		    contact->u = u;
+		    contact->v = v;
+		    contact->m_face_id = boxesresult[i];
+		    VEC_COPY(contact->m_point,pout);
+		    VEC_COPY(contact->m_normal,tridata.m_planes.m_planes[0]);
+
+		    gim_trimesh_unlocks_work_data(trimesh);
+            GIM_DYNARRAY_DESTROY(collision_result);
+		    return 1;
+		}
+	}
+
+	gim_trimesh_unlocks_work_data(trimesh);
+	GIM_DYNARRAY_DESTROY(collision_result);
+	return 0;//no collisiion
+}
+
+
+//! Trimesh Ray Collisions closest
+/*!
+Find the closest primitive collided by the ray
+\param trimesh
+\param contact
+\return 1 if the ray collides, else 0
+*/
+int gim_trimesh_ray_closest_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact)
+{
+    GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_BOXQUERY_LIST(collision_result);
+
+	gim_aabbset_ray_collision(origin,dir,tmax,&trimesh->m_aabbset,&collision_result);
+
+	if(collision_result.m_size==0)
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	    return 0;
+	}
+
+	//collide triangles
+
+	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
+	GIM_TRIANGLE_DATA  tridata;
+	vec3f pout;
+	GREAL tparam,u,v;
+	char does_intersect;
+	contact->tparam = tmax + 0.1f;
+
+
+	gim_trimesh_locks_work_data(trimesh);
+
+	for(unsigned int i=0;i<collision_result.m_size;i++)
+	{
+		gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tridata);
+
+		RAY_TRIANGLE_INTERSECTION(origin,dir,tridata.m_vertices[0],tridata.m_vertices[1],tridata.m_vertices[2],tridata.m_planes.m_planes[0],pout,u,v,tparam,tmax,does_intersect);
+		if(does_intersect && (tparam < contact->tparam))
+		{
+            contact->tparam = tparam;
+		    contact->u = u;
+		    contact->v = v;
+		    contact->m_face_id = boxesresult[i];
+		    VEC_COPY(contact->m_point,pout);
+		    VEC_COPY(contact->m_normal,tridata.m_planes.m_planes[0]);
+		}
+	}
+
+	gim_trimesh_unlocks_work_data(trimesh);
+	GIM_DYNARRAY_DESTROY(collision_result);
+	if(contact->tparam > tmax) return 0;
+	return 1;
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_sphere_collision.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_sphere_collision.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_sphere_collision.cpp	(revision 216)
@@ -0,0 +1,196 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_trimesh.h"
+
+int gim_triangle_sphere_collision(
+							GIM_TRIANGLE_DATA *tri,
+							vec3f center, GREAL radius,
+							GIM_TRIANGLE_CONTACT_DATA * contact_data)
+{
+    contact_data->m_point_count = 0;
+
+    //Find Face plane distance
+    GREAL  dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[0],center);
+    if(dis>radius) return 0; //out
+    if(dis<-radius) return 0;//Out of triangle
+    contact_data->m_penetration_depth = dis;
+
+    //Find the most edge
+    GUINT most_edge = 4;//no edge
+    GREAL max_dis = 0.0f;
+    dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[1],center);
+    if(dis>radius) return 0;//Out of triangle
+    if(dis>0.0f)
+    {
+        max_dis = dis;
+        most_edge = 0;
+    }
+
+    dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[2],center);
+    if(dis>radius) return 0;//Out of triangle
+    if(dis>max_dis)// && dis>0.0f)
+    {
+        max_dis = dis;
+        most_edge = 1;
+    }
+
+    dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[3],center);
+    if(dis>radius) return 0;//Out of triangle
+    if(dis>max_dis)// && dis>0.0f)
+    {
+        max_dis = dis;
+        most_edge = 2;
+    }
+
+    if(most_edge == 4) //Box is into triangle
+    {
+        //contact_data->m_penetration_depth = dis is set above
+        //Find Face plane point
+        VEC_COPY(contact_data->m_separating_normal,tri->m_planes.m_planes[0]);
+        //Find point projection on plane
+        if(contact_data->m_penetration_depth>=0.0f)
+        {
+            VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
+        }
+        else
+        {
+            VEC_SCALE(contact_data->m_points[0],radius,contact_data->m_separating_normal);
+        }
+        contact_data->m_penetration_depth = radius - contact_data->m_penetration_depth;
+
+        VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
+        //Scale normal for pointing to triangle
+        VEC_SCALE(contact_data->m_separating_normal,-1.0f,contact_data->m_separating_normal);
+        contact_data->m_point_count = 1;
+        return 1;
+    }
+    //find the edge
+    vec3f e1,e2;
+    VEC_COPY(e1,tri->m_vertices[most_edge]);
+    VEC_COPY(e2,tri->m_vertices[(most_edge+1)%3]);
+
+    CLOSEST_POINT_ON_SEGMENT(contact_data->m_points[0],center,e1,e2);
+    //find distance
+    VEC_DIFF(e1,center,contact_data->m_points[0]);
+    VEC_LENGTH(e1,dis);
+    if(dis>radius) return 0;
+
+    contact_data->m_penetration_depth = radius - dis;
+
+    if(IS_ZERO(dis))
+    {
+        VEC_COPY(contact_data->m_separating_normal,tri->m_planes.m_planes[most_edge+1]);
+        VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
+        VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
+    }
+    else
+    {
+        VEC_SCALE(contact_data->m_separating_normal,1.0f/dis,e1);
+        VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
+        VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
+    }
+
+    //Scale normal for pointing to triangle
+    VEC_SCALE(contact_data->m_separating_normal,-1.0f,contact_data->m_separating_normal);
+
+    contact_data->m_point_count = 1;
+    return 1;
+
+}
+
+//! Trimesh Sphere Collisions
+/*!
+In each contact
+<ul>
+<li> m_handle1 points to trimesh.
+<li> m_handle2 points to NULL.
+<li> m_feature1 Is a triangle index of trimesh.
+</ul>
+
+\param trimesh
+\param center
+\param radius
+\param contacts A GIM_CONTACT array. Must be initialized
+*/
+void gim_trimesh_sphere_collision(GIM_TRIMESH * trimesh,vec3f center,GREAL radius, GDYNAMIC_ARRAY * contacts)
+{
+    contacts->m_size = 0;
+
+    aabb3f test_aabb;
+	test_aabb.minX = center[0]-radius;
+	test_aabb.maxX = center[0]+radius;
+	test_aabb.minY = center[1]-radius;
+	test_aabb.maxY = center[1]+radius;
+	test_aabb.minZ = center[2]-radius;
+	test_aabb.maxZ = center[2]+radius;
+
+	GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_BOXQUERY_LIST(collision_result);
+
+	gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result);
+
+	if(collision_result.m_size==0)
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	}
+
+	//collide triangles
+	//Locks trimesh
+	gim_trimesh_locks_work_data(trimesh);
+	 //dummy contacts
+    GDYNAMIC_ARRAY dummycontacts;
+    GIM_CREATE_CONTACT_LIST(dummycontacts);
+
+	int cresult;
+	unsigned int i;
+	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
+	GIM_TRIANGLE_CONTACT_DATA tri_contact_data;
+	GIM_TRIANGLE_DATA tri_data;
+
+	for(i=0;i<collision_result.m_size;i++)
+	{
+		gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
+		cresult = gim_triangle_sphere_collision(&tri_data,center,radius,&tri_contact_data);
+		if(cresult!=0)
+		{
+		    GIM_PUSH_CONTACT(dummycontacts, tri_contact_data.m_points[0],tri_contact_data.m_separating_normal ,tri_contact_data.m_penetration_depth,trimesh, 0, boxesresult[i],0);
+		}
+	}
+	///unlocks
+	gim_trimesh_unlocks_work_data(trimesh);
+	///Destroy box result
+	GIM_DYNARRAY_DESTROY(collision_result);
+
+	 //merge contacts
+    gim_merge_contacts(&dummycontacts,contacts);
+
+    //Destroy dummy
+    GIM_DYNARRAY_DESTROY(dummycontacts);
+}
+
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_trimesh_collision.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gim_trimesh_trimesh_collision.cpp	(revision 216)
@@ -0,0 +1,348 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gim_trimesh.h"
+
+#define CLASSIFY_TRI_BY_FACE(v1,v2,v3,faceplane,out_of_face)\
+{   \
+    _distances[0] = DISTANCE_PLANE_POINT(faceplane,v1);\
+    _distances[1] =  _distances[0] * DISTANCE_PLANE_POINT(faceplane,v2);\
+    _distances[2] =  _distances[0] * DISTANCE_PLANE_POINT(faceplane,v3); \
+	if(_distances[1]>0.0f && _distances[2]>0.0f)\
+	{\
+	    out_of_face = 1;\
+	}\
+	else\
+	{\
+	    out_of_face = 0;\
+	}\
+}\
+
+
+//! Receives the 3 edge planes
+#define MOST_DEEP_POINTS(plane,points,point_count,deep_points,deep_points_count,maxdeep)\
+{\
+    maxdeep=-1000.0f;\
+    GUINT _k;\
+	GREAL _dist;\
+	deep_points_count = 0;\
+	for(_k=0;_k<point_count;_k++)\
+	{\
+	    _dist = -DISTANCE_PLANE_POINT(plane,points[_k]);\
+		if(_dist>maxdeep)\
+		{\
+			maxdeep = _dist;\
+			_max_candidates[0] = _k;\
+			deep_points_count=1;\
+		}\
+		else if((_dist+G_EPSILON)>=maxdeep)\
+		{\
+		    _max_candidates[deep_points_count] = _k;\
+			deep_points_count++;\
+		}\
+	}\
+	if(maxdeep<0.0f)\
+    {\
+        deep_points_count = 0;\
+    }\
+    else\
+    {\
+        for(_k=0;_k<deep_points_count;_k++)\
+        {\
+            VEC_COPY(deep_points[_k],points[_max_candidates[_k]]);\
+        }\
+    }\
+}\
+
+//! Receives the 3 edge planes
+#define CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri_points,tri_edge_planes, clipped_points, clipped_point_count)\
+{\
+    clipped_point_count = 0;    \
+    _temp_clip_count = 0;\
+    PLANE_CLIP_POLYGON(tri_edge_planes[0],tri_points,3,_temp_clip,_temp_clip_count,MAX_TRI_CLIPPING);\
+    if(_temp_clip_count>0)\
+    {\
+        _temp_clip_count2 = 0;\
+        PLANE_CLIP_POLYGON(tri_edge_planes[1],_temp_clip,_temp_clip_count,_temp_clip2,_temp_clip_count2,MAX_TRI_CLIPPING);\
+        if(_temp_clip_count2>0)\
+        {\
+            PLANE_CLIP_POLYGON(tri_edge_planes[2],_temp_clip2,_temp_clip_count2,clipped_points,clipped_point_count,MAX_TRI_CLIPPING);\
+        }\
+    }\
+}\
+
+
+
+int _gim_triangle_triangle_collision(
+							GIM_TRIANGLE_DATA *tri1,
+							GIM_TRIANGLE_DATA *tri2,
+							GIM_TRIANGLE_CONTACT_DATA * contact_data)
+{
+    //Cache variables for triangle intersection
+    GUINT _max_candidates[MAX_TRI_CLIPPING];
+    vec3f _temp_clip[MAX_TRI_CLIPPING];
+    GUINT _temp_clip_count = 0;
+    vec3f _temp_clip2[MAX_TRI_CLIPPING];
+    GUINT _temp_clip_count2 = 0;
+    vec3f clipped_points2[MAX_TRI_CLIPPING];
+    vec3f deep_points2[MAX_TRI_CLIPPING];
+    vec3f clipped_points1[MAX_TRI_CLIPPING];
+    vec3f deep_points1[MAX_TRI_CLIPPING];
+
+
+
+    //State variabnles
+	GUINT mostdir=0;
+	GUINT clipped2_count=0;
+
+	//Clip tri2 by tri1 edges
+
+	CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri2->m_vertices,(&tri1->m_planes.m_planes[1]), clipped_points2, clipped2_count);
+
+	if(clipped2_count == 0 )
+	{
+	     return 0;//Reject
+	}
+
+	//find most deep interval face1
+	GUINT deep2_count=0;
+
+	GREAL maxdeep;
+
+	MOST_DEEP_POINTS((tri1->m_planes.m_planes[0]), clipped_points2, clipped2_count, deep_points2, deep2_count, maxdeep);
+	if(deep2_count==0)
+	{
+//	    *perror = 0.0f;
+	     return 0;//Reject
+	}
+
+	//Normal pointing to triangle1
+	VEC_SCALE(contact_data->m_separating_normal,-1.0f,(tri1->m_planes.m_planes[0]));
+
+
+	//Clip tri1 by tri2 edges
+
+	GUINT clipped1_count=0;
+
+	CLIP_TRI_POINTS_BY_TRI_EDGE_PLANES(tri1->m_vertices,(&tri2->m_planes.m_planes[1]), clipped_points1, clipped1_count);
+
+	if(clipped2_count == 0 )
+	{
+//	    *perror = 0.0f;
+	     return 0;//Reject
+	}
+
+
+	//find interval face2
+	GUINT deep1_count=0;
+
+	GREAL dist;
+
+	MOST_DEEP_POINTS((tri2->m_planes.m_planes[0]), clipped_points1, clipped1_count, deep_points1, deep1_count, dist);
+
+	if(deep1_count==0)
+	{
+//	    *perror = 0.0f;
+	    return 0;
+	}
+
+	if(dist<maxdeep)
+	{
+		maxdeep = dist;
+		mostdir = 1;
+		VEC_COPY(contact_data->m_separating_normal,(tri2->m_planes.m_planes[0]));
+	}
+	//set deep
+	contact_data->m_penetration_depth = maxdeep;
+
+	////check most dir for contacts
+	if(mostdir==0)
+	{
+	    contact_data->m_point_count = deep2_count;
+	    for(mostdir=0;mostdir<deep2_count;mostdir++)
+	    {
+	        VEC_COPY(contact_data->m_points[mostdir] ,deep_points2[mostdir]);
+	    }
+	}
+	else
+	{
+		contact_data->m_point_count = deep1_count;
+	    for(mostdir=0;mostdir<deep1_count;mostdir++)
+	    {
+	        VEC_COPY(contact_data->m_points[mostdir] ,deep_points1[mostdir]);
+	    }
+	}
+	return 1;
+}
+
+
+
+//! Finds the contact points from a collision of two triangles
+/*!
+Returns the contact points, the penetration depth and the separating normal of the collision
+between two triangles. The normal is pointing toward triangle 1 from triangle 2
+*/
+int gim_triangle_triangle_collision(
+							GIM_TRIANGLE_DATA *tri1,
+							GIM_TRIANGLE_DATA *tri2,
+							GIM_TRIANGLE_CONTACT_DATA * contact_data)
+{
+    vec3f _distances;
+    char out_of_face=0;
+
+    CLASSIFY_TRI_BY_FACE(tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_planes.m_planes[0],out_of_face);
+    if(out_of_face==1) return 0;
+
+    CLASSIFY_TRI_BY_FACE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[0],out_of_face);
+    if(out_of_face==1) return 0;
+
+    return _gim_triangle_triangle_collision(tri1,tri2,contact_data);
+}
+
+//! Trimesh Trimesh Collisions
+/*!
+
+In each contact
+<ul>
+<li> m_handle1 points to trimesh1.
+<li> m_handle2 points to trimesh2.
+<li> m_feature1 Is a triangle index of trimesh1.
+<li> m_feature2 Is a triangle index of trimesh2.
+</ul>
+
+\param trimesh1 Collider
+\param trimesh2 Collidee
+\param contacts A GIM_CONTACT array. Must be initialized
+*/
+void gim_trimesh_trimesh_collision(GIM_TRIMESH * trimesh1, GIM_TRIMESH * trimesh2, GDYNAMIC_ARRAY * contacts)
+{
+    contacts->m_size = 0;
+    GDYNAMIC_ARRAY collision_pairs;
+    GIM_CREATE_PAIR_SET(collision_pairs)
+
+    gim_aabbset_bipartite_intersections(&trimesh1->m_aabbset,&trimesh2->m_aabbset,&collision_pairs);
+
+    if(collision_pairs.m_size==0)
+    {
+        GIM_DYNARRAY_DESTROY(collision_pairs);
+         return; //no collisioin
+    }
+
+    //Locks meshes
+    gim_trimesh_locks_work_data(trimesh1);
+    gim_trimesh_locks_work_data(trimesh2);
+
+
+    //pair pointer
+    GIM_PAIR *pairs = GIM_DYNARRAY_POINTER(GIM_PAIR,collision_pairs);
+    //dummy contacts
+    GDYNAMIC_ARRAY dummycontacts;
+    GIM_CREATE_CONTACT_LIST(dummycontacts);
+
+    //Auxiliary triangle data
+    GIM_TRIANGLE_CONTACT_DATA tri_contact_data;
+    GIM_TRIANGLE_DATA tri1data,tri2data;
+
+
+    GUINT i, ti1,ti2,ci;
+    int colresult;
+    for (i=0;i<collision_pairs.m_size; i++)
+    {
+        ti1 = pairs[i].m_index1;
+        ti2 = pairs[i].m_index2;
+        //Get triangles data
+        gim_trimesh_get_triangle_data(trimesh1,ti1,&tri1data);
+        gim_trimesh_get_triangle_data(trimesh2,ti2,&tri2data);
+
+        //collide triangles
+        colresult = gim_triangle_triangle_collision(&tri1data,&tri2data,&tri_contact_data);
+        if(colresult == 1)
+        {
+            //Add contacts
+            for (ci=0;ci<tri_contact_data.m_point_count ;ci++ )
+            {
+                GIM_PUSH_CONTACT(dummycontacts, tri_contact_data.m_points[ci],tri_contact_data.m_separating_normal ,tri_contact_data.m_penetration_depth,trimesh1, trimesh2, ti1, ti2);
+            }
+        }
+    }
+
+    if(dummycontacts.m_size == 0) //reject
+    {
+        GIM_DYNARRAY_DESTROY(dummycontacts);
+        GIM_DYNARRAY_DESTROY(collision_pairs);
+        return;
+    }
+    //merge contacts
+    gim_merge_contacts(&dummycontacts,contacts);
+
+    //Terminate
+    GIM_DYNARRAY_DESTROY(dummycontacts);
+    GIM_DYNARRAY_DESTROY(collision_pairs);
+
+    //Unlocks meshes
+    gim_trimesh_unlocks_work_data(trimesh1);
+    gim_trimesh_unlocks_work_data(trimesh2);
+}
+
+
+//! Trimesh Plane Collisions
+/*!
+
+\param trimesh
+\param plane vec4f plane
+\param contacts A vec4f array. Must be initialized (~100). Each element have the coordinate point in the first 3 elements, and vec4f[3] has the penetration depth.
+*/
+void gim_trimesh_plane_collision(GIM_TRIMESH * trimesh,vec4f plane, GDYNAMIC_ARRAY * contacts)
+{
+    contacts->m_size = 0;
+    char classify;
+    PLANE_CLASSIFY_BOX(plane,trimesh->m_aabbset.m_global_bound,classify);
+    if(classify>1) return; // in front of plane
+
+    //Locks mesh
+    gim_trimesh_locks_work_data(trimesh);
+    //Get vertices
+    GUINT i, vertcount = trimesh->m_transformed_vertex_buffer.m_element_count;
+    vec3f * vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);
+
+    GREAL dist;
+    vec4f * result_contact;
+
+    for (i=0;i<vertcount;i++)
+    {
+        dist = DISTANCE_PLANE_POINT(plane,vertices[i]);
+        if(dist<=0.0f)
+        {
+             GIM_DYNARRAY_PUSH_EMPTY(vec4f,(*contacts));
+             result_contact = GIM_DYNARRAY_POINTER_LAST(vec4f,(*contacts));
+             VEC_COPY((*result_contact),vertices[i]);
+             (*result_contact)[3] = -dist;
+        }
+    }
+    gim_trimesh_unlocks_work_data(trimesh);
+}
Index: /code/branches/ode/ode-0.9/GIMPACT/src/gimpact.cpp
===================================================================
--- /code/branches/ode/ode-0.9/GIMPACT/src/gimpact.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/GIMPACT/src/gimpact.cpp	(revision 216)
@@ -0,0 +1,39 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "GIMPACT/gimpact.h"
+
+void gimpact_init()
+{
+    gim_init_math();
+    gim_init_buffer_managers();
+}
+void gimpact_terminate()
+{
+    gim_terminate_buffer_managers();
+}
Index: /code/branches/ode/ode-0.9/INSTALL.txt
===================================================================
--- /code/branches/ode/ode-0.9/INSTALL.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/INSTALL.txt	(revision 216)
@@ -0,0 +1,118 @@
+As of version 0.6, ODE has two new build systems, one for Visual Studio
+and another for just about everything else. 
+
+1. Building with Visual Studio
+2. Building with Autotools (Linux, OS X, etc.)
+3. Building with Code::Blocks
+4. Building with Something Else
+
+ 
+1. BUILDING WITH VISUAL STUDIO (2002 and up)
+
+ If you downloaded the source code from Subversion you must first copy 
+ the file build/config-default.h to include/ode/config.h. If you 
+ downloaded a source code package from SourceForge this has already 
+ been done for you.
+ 
+ The directory ode/build contains project files for all supported versions
+ of Visual Studio. Open the appropriate solution for your version, build,
+ and go! 
+ 
+ Single-precision math is used by default. If you would like to switch to
+ doubles instead, edit ode/include/ode/config.h and replace 
+ 
+   #define dSINGLE 1
+   
+ with the line
+ 
+   #define dDOUBLE 1
+   
+ and the rebuild everything.
+ 
+ Note that Visual Studio 6 is no longer supported; please upgrade to 
+ Visual Studio 2005 C++ Express (it's free!).
+  
+ 
+2. BUILDING WITH AUTOTOOLS (Linux, OS X, etc.)
+
+ If you downloaded the source code from Subversion you must bootstrap the
+ process by running the command:
+ 
+   $ sh autogen.sh
+   
+ If you downloaded a source code package from SourceForge this has 
+ already been done for you. You may see some "underquoted definition" 
+ warnings depending on your platform, these are (for now) harmless 
+ warnings regarding scripts from other m4 installed packages.
+ 
+ Run the configure script to autodetect your build environment.
+ 
+   $ ./configure
+    
+ By default this will build ODE as a static library with single-precision
+ math, trimesh support, and debug symbols enabled. You can modify these 
+ defaults by passing additional parameters to configure. For a full list 
+ of available options, type
+ 
+   $ ./configure --help
+   
+ Some of the more popular options are
+ 
+   --enable-double-precision enable double-precision math
+   --with-trimesh=none disables the trimesh support
+   --with-trimesh=opcode use OPCODE for trimesh code
+   --with-trimesh=gimpact use GIMPACT for trimesh code
+
+   --enable-release builds an optimized library
+   --enabled-shared builds a shared library
+    
+ Once configure has run successfully, build and install ODE:
+ 
+   $ make
+   $ make install
+    
+ The latter command will also create an `ode-config` script which you can
+ use to pass cflags and ldflags to your projects. run `ode-config` from a
+ command prompt to find out how it works.
+ 
+ In addition the option `--with-arch=` allows the user to pass the -march
+ flag to GCC, in order to tune the library for a particular architecture.
+ The arguments for --with-arch are listed on this page for -mtune: 
+    
+ http://gcc.gnu.org/onlinedocs/gcc-3.4.1/gcc/i386-and-x86-64-Options.html#i386%20and%20x86-64%20Options
+ 
+ Note that the link points to posible values for Intel processors, but 
+ other processors are also supported, check the page for your particular
+ processor to see what parameters can be passed to -march in your case.
+
+ 
+3. Building with Code::Blocks
+
+ Because Code::Blocks supports so many different platforms, we do not
+ provide workspaces. Instead, use Premake (http://www.premake.sourceforge.net/)
+ to create a workspace tailored for your platform and project.
+ 
+ Download Premake and place it on your system path (or anywhere convenient).
+ Then create a workspace like so:
+ 
+   $ cd ode/build
+   $ premake --with-tests --target cb-gcc
+   
+ To see a complete list of options:
+ 
+   $ cd ode/build
+   $ premake --help
+   
+   
+4. Building with Something Else
+
+ ODE uses the Premake tool to provide support for several different toolsets.
+ Premake adds support for new toolsets on a regular basis, so yours might be
+ supported. Check the Premake website at http://premake.sourceforge.net/, 
+ and then follow the directions for Code::Blocks above, substituting your
+ toolset target in place of `cb-gcc`.
+ 
+ 
+ 
+
+ 
Index: /code/branches/ode/ode-0.9/LICENSE-BSD.TXT
===================================================================
--- /code/branches/ode/ode-0.9/LICENSE-BSD.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/LICENSE-BSD.TXT	(revision 216)
@@ -0,0 +1,34 @@
+
+This is the BSD-style license for the Open Dynamics Engine
+----------------------------------------------------------
+
+Open Dynamics Engine
+Copyright (c) 2001-2007, Russell L. Smith.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+Neither the names of ODE's copyright owner nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: /code/branches/ode/ode-0.9/LICENSE.TXT
===================================================================
--- /code/branches/ode/ode-0.9/LICENSE.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/LICENSE.TXT	(revision 216)
@@ -0,0 +1,511 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
Index: /code/branches/ode/ode-0.9/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/Makefile.am	(revision 216)
@@ -0,0 +1,37 @@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+libtool: $(LIBTOOL_DEPS)
+	$(SHELL) ./config.status --recheck
+
+if ENABLE_DEMOS
+SUBDIRS = include drawstuff ode tests
+else
+SUBDIRS = include ode tests
+endif
+
+bin_SCRIPTS = ode-config
+
+# Utility rule for making a release
+release: dist dist-bz2 dist-zip
+	@echo Created release packages for ${PACKAGE}-${VERSION}.
+
+# Rules for creating .tar.bz2 and .zip packages
+dist-bz2: ${PACKAGE}-${VERSION}.tar.gz
+	gzip -dc ${PACKAGE}-${VERSION}.tar.gz | bzip2 > ${PACKAGE}-${VERSION}.tar.bz2
+
+dist-zip: ${PACKAGE}-${VERSION}.tar.gz
+	tar -zxf ${PACKAGE}-${VERSION}.tar.gz && \
+	zip -r ${PACKAGE}-${VERSION}.zip ${PACKAGE}-${VERSION} && \
+	rm -rf ${PACKAGE}-${VERSION}
+
+if USE_SONAME
+install-exec-hook:
+	ln -s $(libdir)/@ODE_SONAME@.@ODE_REVISION@.@ODE_AGE@ \
+	$(libdir)/libode.so
+	ln -s $(libdir)/@ODE_SONAME@.@ODE_REVISION@.@ODE_AGE@ \
+	$(libdir)/@ODE_SONAME@
+	ln -s $(libdir)/@ODE_SONAME@.@ODE_REVISION@.@ODE_AGE@ \
+	$(libdir)/@ODE_SONAME@.@ODE_REVISION@
+	/sbin/ldconfig
+else
+install-exec-hook:
+endif
Index: /code/branches/ode/ode-0.9/Makefile.deps
===================================================================
--- /code/branches/ode/ode-0.9/Makefile.deps	(revision 216)
+++ /code/branches/ode/ode-0.9/Makefile.deps	(revision 216)
@@ -0,0 +1,1845 @@
+ode/src/array.o: \
+  ode/src/array.cpp \
+  include/ode/config.h \
+  include/ode/memory.h \
+  include/ode/error.h \
+  ode/src/array.h
+ode/src/error.o: \
+  ode/src/error.cpp \
+  include/ode/config.h \
+  include/ode/error.h
+ode/src/memory.o: \
+  ode/src/memory.cpp \
+  include/ode/config.h \
+  include/ode/memory.h \
+  include/ode/error.h
+ode/src/obstack.o: \
+  ode/src/obstack.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/memory.h \
+  ode/src/obstack.h \
+  ode/src/objects.h \
+  include/ode/mass.h \
+  ode/src/array.h
+ode/src/odemath.o: \
+  ode/src/odemath.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/odemath.h
+ode/src/matrix.o: \
+  ode/src/matrix.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/matrix.h
+ode/src/misc.o: \
+  ode/src/misc.cpp \
+  include/ode/config.h \
+  include/ode/misc.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/matrix.h
+ode/src/rotation.o: \
+  ode/src/rotation.cpp \
+  include/ode/rotation.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/compatibility.h \
+  include/ode/odemath.h
+ode/src/mass.o: \
+  ode/src/mass.cpp \
+  include/ode/config.h \
+  include/ode/mass.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h
+ode/src/ode.o: \
+  ode/src/ode.cpp \
+  ode/src/objects.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  include/ode/ode.h \
+  include/ode/compatibility.h \
+  include/ode/contact.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  ode/src/joint.h \
+  ode/src/obstack.h \
+  ode/src/step.h \
+  ode/src/quickstep.h \
+  ode/src/util.h
+ode/src/step.o: \
+  ode/src/step.cpp \
+  ode/src/objects.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/joint.h \
+  include/ode/contact.h \
+  ode/src/obstack.h \
+  include/ode/odemath.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/timer.h \
+  include/ode/matrix.h \
+  ode/src/lcp.h \
+  ode/src/util.h
+ode/src/stepfast.o: \
+  ode/src/stepfast.cpp \
+  ode/src/objects.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/joint.h \
+  include/ode/contact.h \
+  ode/src/obstack.h \
+  include/ode/objects.h \
+  include/ode/odemath.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/timer.h \
+  include/ode/matrix.h \
+  include/ode/misc.h \
+  ode/src/lcp.h \
+  ode/src/step.h \
+  ode/src/util.h
+ode/src/quickstep.o: \
+  ode/src/quickstep.cpp \
+  ode/src/objects.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/joint.h \
+  include/ode/contact.h \
+  ode/src/obstack.h \
+  include/ode/odemath.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/timer.h \
+  include/ode/matrix.h \
+  ode/src/lcp.h \
+  ode/src/util.h
+ode/src/util.o: \
+  ode/src/util.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  ode/src/objects.h \
+  ode/src/array.h \
+  ode/src/joint.h \
+  ode/src/obstack.h \
+  ode/src/util.h
+ode/src/lcp.o: \
+  ode/src/lcp.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  ode/src/lcp.h \
+  include/ode/matrix.h \
+  include/ode/misc.h \
+  ode/src/mat.h \
+  include/ode/timer.h
+ode/src/joint.o: \
+  ode/src/joint.cpp \
+  include/ode/odemath.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/matrix.h \
+  ode/src/joint.h \
+  ode/src/objects.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  include/ode/contact.h \
+  ode/src/obstack.h
+ode/src/timer.o: \
+  ode/src/timer.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/timer.h
+ode/src/mat.o: \
+  ode/src/mat.cpp \
+  include/ode/config.h \
+  include/ode/misc.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/matrix.h \
+  include/ode/memory.h \
+  ode/src/mat.h
+ode/src/testing.o: \
+  ode/src/testing.cpp \
+  include/ode/config.h \
+  include/ode/misc.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/memory.h \
+  ode/src/testing.h \
+  ode/src/array.h
+ode/src/export-dif.o: \
+  ode/src/export-dif.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  ode/src/objects.h \
+  ode/src/array.h \
+  ode/src/joint.h \
+  ode/src/obstack.h \
+  ode/src/collision_kernel.h
+ode/src/collision_kernel.o: \
+  ode/src/collision_kernel.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/matrix.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/objects.h \
+  include/ode/mass.h \
+  include/ode/contact.h \
+  ode/src/collision_kernel.h \
+  include/ode/collision.h \
+  include/ode/collision_space.h \
+  include/ode/collision_trimesh.h \
+  ode/src/objects.h \
+  include/ode/memory.h \
+  ode/src/array.h \
+  ode/src/collision_util.h \
+  ode/src/collision_std.h \
+  ode/src/collision_transform.h \
+  ode/src/collision_trimesh_internal.h
+ode/src/collision_util.o: \
+  ode/src/collision_util.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/collision.h \
+  include/ode/collision_space.h \
+  include/ode/contact.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odemath.h \
+  ode/src/collision_util.h
+ode/src/collision_std.o: \
+  ode/src/collision_std.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/collision.h \
+  include/ode/collision_space.h \
+  include/ode/contact.h \
+  include/ode/collision_trimesh.h \
+  include/ode/matrix.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/odemath.h \
+  ode/src/collision_kernel.h \
+  ode/src/objects.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/collision_std.h \
+  ode/src/collision_util.h
+ode/src/collision_space.o: \
+  ode/src/collision_space.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/matrix.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/contact.h \
+  include/ode/collision_trimesh.h \
+  ode/src/collision_kernel.h \
+  ode/src/objects.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/collision_space_internal.h
+ode/src/collision_transform.o: \
+  ode/src/collision_transform.cpp \
+  include/ode/collision.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/collision_space.h \
+  include/ode/contact.h \
+  include/ode/collision_trimesh.h \
+  include/ode/matrix.h \
+  include/ode/rotation.h \
+  include/ode/compatibility.h \
+  include/ode/odemath.h \
+  ode/src/collision_transform.h \
+  ode/src/collision_kernel.h \
+  ode/src/objects.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/collision_util.h
+ode/src/collision_quadtreespace.o: \
+  ode/src/collision_quadtreespace.cpp \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h \
+  include/ode/matrix.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/contact.h \
+  include/ode/collision_trimesh.h \
+  ode/src/collision_kernel.h \
+  ode/src/objects.h \
+  include/ode/memory.h \
+  include/ode/mass.h \
+  ode/src/array.h \
+  ode/src/collision_space_internal.h
+ode/src/OPC_AABBCollider.o: \
+  OPCODE/OPC_AABBCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_BoxBoxOverlap.h \
+  OPCODE/OPC_TriBoxOverlap.h
+ode/src/OPC_AABBTree.o: \
+  OPCODE/OPC_AABBTree.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_BaseModel.o: \
+  OPCODE/OPC_BaseModel.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_BoxPruning.o: \
+  OPCODE/OPC_BoxPruning.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_Collider.o: \
+  OPCODE/OPC_Collider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_Common.o: \
+  OPCODE/OPC_Common.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_HybridModel.o: \
+  OPCODE/OPC_HybridModel.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_LSSCollider.o: \
+  OPCODE/OPC_LSSCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_LSSAABBOverlap.h \
+  OPCODE/OPC_LSSTriOverlap.h
+ode/src/OPC_MeshInterface.o: \
+  OPCODE/OPC_MeshInterface.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_Model.o: \
+  OPCODE/OPC_Model.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_OBBCollider.o: \
+  OPCODE/OPC_OBBCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_BoxBoxOverlap.h \
+  OPCODE/OPC_TriBoxOverlap.h
+ode/src/Opcode.o: \
+  OPCODE/Opcode.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_OptimizedTree.o: \
+  OPCODE/OPC_OptimizedTree.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_Picking.o: \
+  OPCODE/OPC_Picking.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_PlanesCollider.o: \
+  OPCODE/OPC_PlanesCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_PlanesAABBOverlap.h \
+  OPCODE/OPC_PlanesTriOverlap.h
+ode/src/OPC_RayCollider.o: \
+  OPCODE/OPC_RayCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_RayAABBOverlap.h \
+  OPCODE/OPC_RayTriOverlap.h
+ode/src/OPC_SphereCollider.o: \
+  OPCODE/OPC_SphereCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_SphereAABBOverlap.h \
+  OPCODE/OPC_SphereTriOverlap.h
+ode/src/OPC_SweepAndPrune.o: \
+  OPCODE/OPC_SweepAndPrune.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_TreeBuilders.o: \
+  OPCODE/OPC_TreeBuilders.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/OPC_TreeCollider.o: \
+  OPCODE/OPC_TreeCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h \
+  OPCODE/OPC_BoxBoxOverlap.h \
+  OPCODE/OPC_TriBoxOverlap.h \
+  OPCODE/OPC_TriTriOverlap.h
+ode/src/OPC_VolumeCollider.o: \
+  OPCODE/OPC_VolumeCollider.cpp \
+  OPCODE/Stdafx.h \
+  OPCODE/Opcode.h \
+  OPCODE/OPC_IceHook.h \
+  OPCODE/Ice/IcePreprocessor.h \
+  OPCODE/Ice/IceTypes.h \
+  OPCODE/Ice/IceFPU.h \
+  OPCODE/Ice/IceMemoryMacros.h \
+  OPCODE/Ice/IceUtils.h \
+  OPCODE/Ice/IceContainer.h \
+  OPCODE/Ice/IcePairs.h \
+  OPCODE/Ice/IceRevisitedRadix.h \
+  OPCODE/Ice/IceRandom.h \
+  OPCODE/Ice/IceAxes.h \
+  OPCODE/Ice/IcePoint.h \
+  OPCODE/Ice/IceHPoint.h \
+  OPCODE/Ice/IceMatrix3x3.h \
+  OPCODE/Ice/IceMatrix4x4.h \
+  OPCODE/Ice/IcePlane.h \
+  OPCODE/Ice/IceRay.h \
+  OPCODE/Ice/IceIndexedTriangle.h \
+  OPCODE/Ice/IceTriangle.h \
+  OPCODE/Ice/IceTriList.h \
+  OPCODE/Ice/IceAABB.h \
+  OPCODE/Ice/IceOBB.h \
+  OPCODE/Ice/IceBoundingSphere.h \
+  OPCODE/Ice/IceSegment.h \
+  OPCODE/Ice/IceLSS.h \
+  OPCODE/OPC_Settings.h \
+  OPCODE/OPC_Common.h \
+  OPCODE/OPC_MeshInterface.h \
+  OPCODE/OPC_TreeBuilders.h \
+  OPCODE/OPC_AABBTree.h \
+  OPCODE/OPC_OptimizedTree.h \
+  OPCODE/OPC_BaseModel.h \
+  OPCODE/OPC_Model.h \
+  OPCODE/OPC_HybridModel.h \
+  OPCODE/OPC_Collider.h \
+  OPCODE/OPC_VolumeCollider.h \
+  OPCODE/OPC_TreeCollider.h \
+  OPCODE/OPC_RayCollider.h \
+  OPCODE/OPC_SphereCollider.h \
+  OPCODE/OPC_OBBCollider.h \
+  OPCODE/OPC_AABBCollider.h \
+  OPCODE/OPC_LSSCollider.h \
+  OPCODE/OPC_PlanesCollider.h \
+  OPCODE/OPC_Picking.h \
+  OPCODE/OPC_BoxPruning.h \
+  OPCODE/OPC_SweepAndPrune.h
+ode/src/fastldlt.o: \
+  ode/src/fastldlt.c \
+  include/ode/matrix.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h
+ode/src/fastlsolve.o: \
+  ode/src/fastlsolve.c \
+  include/ode/matrix.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h
+ode/src/fastltsolve.o: \
+  ode/src/fastltsolve.c \
+  include/ode/matrix.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h
+ode/src/fastdot.o: \
+  ode/src/fastdot.c \
+  include/ode/matrix.h \
+  include/ode/common.h \
+  include/ode/config.h \
+  include/ode/error.h
+drawstuff/src/drawstuff.o: \
+  drawstuff/src/drawstuff.cpp \
+  include/ode/config.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h \
+  drawstuff/src/internal.h
+drawstuff/src/x11.o: \
+  drawstuff/src/x11.cpp \
+  include/ode/config.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h \
+  drawstuff/src/internal.h
+ode/test/test_ode.o: \
+  ode/test/test_ode.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h
+ode/test/test_chain2.o: \
+  ode/test/test_chain2.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_hinge.o: \
+  ode/test/test_hinge.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_slider.o: \
+  ode/test/test_slider.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_collision.o: \
+  ode/test/test_collision.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_boxstack.o: \
+  ode/test/test_boxstack.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_buggy.o: \
+  ode/test/test_buggy.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_crash.o: \
+  ode/test/test_crash.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_joints.o: \
+  ode/test/test_joints.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_space.o: \
+  ode/test/test_space.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_I.o: \
+  ode/test/test_I.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_step.o: \
+  ode/test/test_step.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_friction.o: \
+  ode/test/test_friction.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_space_stress.o: \
+  ode/test/test_space_stress.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_trimesh.o: \
+  ode/test/test_trimesh.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+ode/test/test_moving_trimesh.o: \
+  ode/test/test_moving_trimesh.cpp \
+  include/ode/ode.h \
+  include/ode/config.h \
+  include/ode/compatibility.h \
+  include/ode/common.h \
+  include/ode/error.h \
+  include/ode/contact.h \
+  include/ode/memory.h \
+  include/ode/odemath.h \
+  include/ode/matrix.h \
+  include/ode/timer.h \
+  include/ode/rotation.h \
+  include/ode/mass.h \
+  include/ode/misc.h \
+  include/ode/objects.h \
+  include/ode/odecpp.h \
+  include/ode/collision_space.h \
+  include/ode/collision.h \
+  include/ode/collision_trimesh.h \
+  include/ode/odecpp_collision.h \
+  include/ode/export-dif.h \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
+drawstuff/dstest/dstest.o: \
+  drawstuff/dstest/dstest.cpp \
+  include/drawstuff/drawstuff.h \
+  include/drawstuff/version.h
Index: /code/branches/ode/ode-0.9/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/Makefile.in	(revision 216)
@@ -0,0 +1,665 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = .
+DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
+	$(srcdir)/Makefile.in $(srcdir)/ode-config.in \
+	$(top_srcdir)/configure config.guess config.sub depcomp \
+	install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES = ode-config
+am__installdirs = "$(DESTDIR)$(bindir)"
+binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
+SCRIPTS = $(bin_SCRIPTS)
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = include ode tests drawstuff
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+@ENABLE_DEMOS_FALSE@SUBDIRS = include ode tests
+@ENABLE_DEMOS_TRUE@SUBDIRS = include drawstuff ode tests
+bin_SCRIPTS = ode-config
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+	@:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+	      cd $(srcdir) && $(AUTOMAKE) --foreign  \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+ode-config: $(top_builddir)/config.status $(srcdir)/ode-config.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binSCRIPTS: $(bin_SCRIPTS)
+	@$(NORMAL_INSTALL)
+	test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+	@list='$(bin_SCRIPTS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  if test -f $$d$$p; then \
+	    f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+	    echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+	    $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-binSCRIPTS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_SCRIPTS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+	  echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(bindir)/$$f"; \
+	done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d $(distdir) || mkdir $(distdir)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r $(distdir)
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+	$(am__remove_distdir)
+
+dist-tarZ: distdir
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__remove_distdir)
+
+dist-shar: distdir
+	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+	$(am__remove_distdir)
+
+dist dist-all: distdir
+	tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+	$(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	esac
+	chmod -R a-w $(distdir); chmod a+w $(distdir)
+	mkdir $(distdir)/_build
+	mkdir $(distdir)/_inst
+	chmod a-w $(distdir)
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && cd $(distdir)/_build \
+	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+	$(am__remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@cd $(distuninstallcheck_dir) \
+	&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(SCRIPTS)
+installdirs: installdirs-recursive
+installdirs-am:
+	for dir in "$(DESTDIR)$(bindir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-binSCRIPTS
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binSCRIPTS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-exec-am install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am am--refresh check check-am clean clean-generic \
+	ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+	dist-shar dist-tarZ dist-zip distcheck distclean \
+	distclean-generic distclean-tags distcleancheck distdir \
+	distuninstallcheck dvi dvi-am html html-am info info-am \
+	install install-am install-binSCRIPTS install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-exec-hook install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs installdirs-am \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-binSCRIPTS
+
+libtool: $(LIBTOOL_DEPS)
+	$(SHELL) ./config.status --recheck
+
+# Utility rule for making a release
+release: dist dist-bz2 dist-zip
+	@echo Created release packages for ${PACKAGE}-${VERSION}.
+
+# Rules for creating .tar.bz2 and .zip packages
+dist-bz2: ${PACKAGE}-${VERSION}.tar.gz
+	gzip -dc ${PACKAGE}-${VERSION}.tar.gz | bzip2 > ${PACKAGE}-${VERSION}.tar.bz2
+
+dist-zip: ${PACKAGE}-${VERSION}.tar.gz
+	tar -zxf ${PACKAGE}-${VERSION}.tar.gz && \
+	zip -r ${PACKAGE}-${VERSION}.zip ${PACKAGE}-${VERSION} && \
+	rm -rf ${PACKAGE}-${VERSION}
+
+@USE_SONAME_TRUE@install-exec-hook:
+@USE_SONAME_TRUE@	ln -s $(libdir)/@ODE_SONAME@.@ODE_REVISION@.@ODE_AGE@ \
+@USE_SONAME_TRUE@	$(libdir)/libode.so
+@USE_SONAME_TRUE@	ln -s $(libdir)/@ODE_SONAME@.@ODE_REVISION@.@ODE_AGE@ \
+@USE_SONAME_TRUE@	$(libdir)/@ODE_SONAME@
+@USE_SONAME_TRUE@	ln -s $(libdir)/@ODE_SONAME@.@ODE_REVISION@.@ODE_AGE@ \
+@USE_SONAME_TRUE@	$(libdir)/@ODE_SONAME@.@ODE_REVISION@
+@USE_SONAME_TRUE@	/sbin/ldconfig
+@USE_SONAME_FALSE@install-exec-hook:
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceAABB.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceAABB.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceAABB.cpp	(revision 216)
@@ -0,0 +1,405 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains AABB-related code.
+ *	\file		IceAABB.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	AABB class.
+ *	\class		AABB
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the sum of two AABBs.
+ *	\param		aabb	[in] the other AABB
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABB& AABB::Add(const AABB& aabb)
+{
+	// Compute new min & max values
+	Point Min;	GetMin(Min);
+	Point Tmp;	aabb.GetMin(Tmp);
+	Min.Min(Tmp);
+
+	Point Max;	GetMax(Max);
+	aabb.GetMax(Tmp);
+	Max.Max(Tmp);
+
+	// Update this
+	SetMinMax(Min, Max);
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Makes a cube from the AABB.
+ *	\param		cube	[out] the cube AABB
+ *	\return		cube edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float AABB::MakeCube(AABB& cube) const
+{
+	Point Ext;	GetExtents(Ext);
+	float Max = Ext.Max();
+
+	Point Cnt;	GetCenter(Cnt);
+	cube.SetCenterExtents(Cnt, Point(Max, Max, Max));
+	return Max;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Makes a sphere from the AABB.
+ *	\param		sphere	[out] sphere containing the AABB
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABB::MakeSphere(Sphere& sphere) const
+{
+	GetExtents(sphere.mCenter);
+	sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f;	// To make sure sphere::Contains(*this)	succeeds
+	GetCenter(sphere.mCenter);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks a box is inside another box.
+ *	\param		box		[in] the other AABB
+ *	\return		true if current box is inside input box
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABB::IsInside(const AABB& box) const
+{
+	if(box.GetMin(0)>GetMin(0))	return false;
+	if(box.GetMin(1)>GetMin(1))	return false;
+	if(box.GetMin(2)>GetMin(2))	return false;
+	if(box.GetMax(0)<GetMax(0))	return false;
+	if(box.GetMax(1)<GetMax(1))	return false;
+	if(box.GetMax(2)<GetMax(2))	return false;
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the AABB planes.
+ *	\param		planes	[out] 6 planes surrounding the box
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABB::ComputePlanes(Plane* planes)	const
+{
+	// Checkings
+	if(!planes)	return false;
+
+	Point Center, Extents;
+	GetCenter(Center);
+	GetExtents(Extents);
+
+	// Writes normals
+	planes[0].n = Point(1.0f, 0.0f, 0.0f);
+	planes[1].n = Point(-1.0f, 0.0f, 0.0f);
+	planes[2].n = Point(0.0f, 1.0f, 0.0f);
+	planes[3].n = Point(0.0f, -1.0f, 0.0f);
+	planes[4].n = Point(0.0f, 0.0f, 1.0f);
+	planes[5].n = Point(0.0f, 0.0f, -1.0f);
+
+	// Compute a point on each plane
+	Point p0 = Point(Center.x+Extents.x, Center.y, Center.z);
+	Point p1 = Point(Center.x-Extents.x, Center.y, Center.z);
+	Point p2 = Point(Center.x, Center.y+Extents.y, Center.z);
+	Point p3 = Point(Center.x, Center.y-Extents.y, Center.z);
+	Point p4 = Point(Center.x, Center.y, Center.z+Extents.z);
+	Point p5 = Point(Center.x, Center.y, Center.z-Extents.z);
+
+	// Compute d
+	planes[0].d = -(planes[0].n|p0);
+	planes[1].d = -(planes[1].n|p1);
+	planes[2].d = -(planes[2].n|p2);
+	planes[3].d = -(planes[3].n|p3);
+	planes[4].d = -(planes[4].n|p4);
+	planes[5].d = -(planes[5].n|p5);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the aabb points.
+ *	\param		pts	[out] 8 box points
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABB::ComputePoints(Point* pts)	const
+{
+	// Checkings
+	if(!pts)	return false;
+
+	// Get box corners
+	Point min;	GetMin(min);
+	Point max;	GetMax(max);
+
+	//     7+------+6			0 = ---
+	//     /|     /|			1 = +--
+	//    / |    / |			2 = ++-
+	//   / 4+---/--+5			3 = -+-
+	// 3+------+2 /    y   z	4 = --+
+	//  | /    | /     |  /		5 = +-+
+	//  |/     |/      |/		6 = +++
+	// 0+------+1      *---x	7 = -++
+
+	// Generate 8 corners of the bbox
+	pts[0] = Point(min.x, min.y, min.z);
+	pts[1] = Point(max.x, min.y, min.z);
+	pts[2] = Point(max.x, max.y, min.z);
+	pts[3] = Point(min.x, max.y, min.z);
+	pts[4] = Point(min.x, min.y, max.z);
+	pts[5] = Point(max.x, min.y, max.z);
+	pts[6] = Point(max.x, max.y, max.z);
+	pts[7] = Point(min.x, max.y, max.z);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets vertex normals.
+ *	\param		pts	[out] 8 box points
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const Point* AABB::GetVertexNormals()	const
+{
+	static float VertexNormals[] = 
+	{
+		-INVSQRT3,	-INVSQRT3,	-INVSQRT3,
+		INVSQRT3,	-INVSQRT3,	-INVSQRT3,
+		INVSQRT3,	INVSQRT3,	-INVSQRT3,
+		-INVSQRT3,	INVSQRT3,	-INVSQRT3,
+		-INVSQRT3,	-INVSQRT3,	INVSQRT3,
+		INVSQRT3,	-INVSQRT3,	INVSQRT3,
+		INVSQRT3,	INVSQRT3,	INVSQRT3,
+		-INVSQRT3,	INVSQRT3,	INVSQRT3
+	};
+	return (const Point*)VertexNormals;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns edges.
+ *	\return		24 indices (12 edges) indexing the list returned by ComputePoints()
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const udword* AABB::GetEdges() const
+{
+	static udword Indices[] = {
+	0, 1,	1, 2,	2, 3,	3, 0,
+	7, 6,	6, 5,	5, 4,	4, 7,
+	1, 5,	6, 2,
+	3, 7,	4, 0
+	};
+	return Indices;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns edge normals.
+ *	\return		edge normals in local space
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const Point* AABB::GetEdgeNormals() const
+{
+	static float EdgeNormals[] = 
+	{
+		0,			-INVSQRT2,	-INVSQRT2,	// 0-1
+		INVSQRT2,	0,			-INVSQRT2,	// 1-2
+		0,			INVSQRT2,	-INVSQRT2,	// 2-3
+		-INVSQRT2,	0,			-INVSQRT2,	// 3-0
+
+		0,			INVSQRT2,	INVSQRT2,	// 7-6
+		INVSQRT2,	0,			INVSQRT2,	// 6-5
+		0,			-INVSQRT2,	INVSQRT2,	// 5-4
+		-INVSQRT2,	0,			INVSQRT2,	// 4-7
+
+		INVSQRT2,	-INVSQRT2,	0,			// 1-5
+		INVSQRT2,	INVSQRT2,	0,			// 6-2
+		-INVSQRT2,	INVSQRT2,	0,			// 3-7
+		-INVSQRT2,	-INVSQRT2,	0			// 4-0
+	};
+	return (const Point*)EdgeNormals;
+}
+
+// ===========================================================================
+//  (C) 1996-98 Vienna University of Technology
+// ===========================================================================
+//  NAME:       bboxarea
+//  TYPE:       c++ code
+//  PROJECT:    Bounding Box Area
+//  CONTENT:    Computes area of 2D projection of 3D oriented bounding box
+//  VERSION:    1.0
+// ===========================================================================
+//  AUTHORS:    ds      Dieter Schmalstieg
+//              ep      Erik Pojar
+// ===========================================================================
+//  HISTORY:
+//
+//  19-sep-99 15:23:03  ds      last modification
+//  01-dec-98 15:23:03  ep      created
+// ===========================================================================
+
+//----------------------------------------------------------------------------
+// SAMPLE CODE STARTS HERE
+//----------------------------------------------------------------------------
+
+// NOTE: This sample program requires OPEN INVENTOR!
+
+//indexlist: this table stores the 64 possible cases of classification of
+//the eyepoint with respect to the 6 defining planes of the bbox (2^6=64)
+//only 26 (3^3-1, where 1 is "inside" cube) of these cases are valid.
+//the first 6 numbers in each row are the indices of the bbox vertices that
+//form the outline of which we want to compute the area (counterclockwise
+//ordering), the 7th entry means the number of vertices in the outline.
+//there are 6 cases with a single face and and a 4-vertex outline, and
+//20 cases with 2 or 3 faces and a 6-vertex outline. a value of 0 indicates
+//an invalid case.
+
+
+// Original list was made of 7 items, I added an 8th element:
+// - to padd on a cache line
+// - to repeat the first entry to avoid modulos
+//
+// I also replaced original ints with sbytes.
+
+static const sbyte gIndexList[64][8] =
+{
+    {-1,-1,-1,-1,-1,-1,-1,   0}, // 0 inside
+    { 0, 4, 7, 3, 0,-1,-1,   4}, // 1 left
+    { 1, 2, 6, 5, 1,-1,-1,   4}, // 2 right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, // 3 -
+    { 0, 1, 5, 4, 0,-1,-1,   4}, // 4 bottom
+    { 0, 1, 5, 4, 7, 3, 0,   6}, // 5 bottom, left
+    { 0, 1, 2, 6, 5, 4, 0,   6}, // 6 bottom, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, // 7 -
+    { 2, 3, 7, 6, 2,-1,-1,   4}, // 8 top
+    { 0, 4, 7, 6, 2, 3, 0,   6}, // 9 top, left
+    { 1, 2, 3, 7, 6, 5, 1,   6}, //10 top, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //11 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //12 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //13 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //14 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //15 -
+    { 0, 3, 2, 1, 0,-1,-1,   4}, //16 front
+    { 0, 4, 7, 3, 2, 1, 0,   6}, //17 front, left
+    { 0, 3, 2, 6, 5, 1, 0,   6}, //18 front, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //19 -
+    { 0, 3, 2, 1, 5, 4, 0,   6}, //20 front, bottom
+    { 1, 5, 4, 7, 3, 2, 1,   6}, //21 front, bottom, left
+    { 0, 3, 2, 6, 5, 4, 0,   6}, //22 front, bottom, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //23 -
+    { 0, 3, 7, 6, 2, 1, 0,   6}, //24 front, top
+    { 0, 4, 7, 6, 2, 1, 0,   6}, //25 front, top, left
+    { 0, 3, 7, 6, 5, 1, 0,   6}, //26 front, top, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //27 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //28 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //29 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //30 -
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //31 -
+    { 4, 5, 6, 7, 4,-1,-1,   4}, //32 back
+    { 0, 4, 5, 6, 7, 3, 0,   6}, //33 back, left
+    { 1, 2, 6, 7, 4, 5, 1,   6}, //34 back, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //35 -
+    { 0, 1, 5, 6, 7, 4, 0,   6}, //36 back, bottom
+    { 0, 1, 5, 6, 7, 3, 0,   6}, //37 back, bottom, left
+    { 0, 1, 2, 6, 7, 4, 0,   6}, //38 back, bottom, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //39 -
+    { 2, 3, 7, 4, 5, 6, 2,   6}, //40 back, top
+    { 0, 4, 5, 6, 2, 3, 0,   6}, //41 back, top, left
+    { 1, 2, 3, 7, 4, 5, 1,   6}, //42 back, top, right
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //43 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //44 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //45 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //46 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //47 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //48 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //49 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //50 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //51 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //52 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //53 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //54 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //55 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //56 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //57 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //58 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //59 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //60 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //61 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}, //62 invalid
+    {-1,-1,-1,-1,-1,-1,-1,   0}  //63 invalid
+};
+
+const sbyte* AABB::ComputeOutline(const Point& local_eye, sdword& num)	const
+{
+	// Get box corners
+	Point min;	GetMin(min);
+	Point max;	GetMax(max);
+
+	// Compute 6-bit code to classify eye with respect to the 6 defining planes of the bbox
+	int pos = ((local_eye.x < min.x) ?  1 : 0)	// 1 = left
+			+ ((local_eye.x > max.x) ?  2 : 0)	// 2 = right
+			+ ((local_eye.y < min.y) ?  4 : 0)	// 4 = bottom
+			+ ((local_eye.y > max.y) ?  8 : 0)	// 8 = top
+			+ ((local_eye.z < min.z) ? 16 : 0)	// 16 = front
+			+ ((local_eye.z > max.z) ? 32 : 0);	// 32 = back
+
+	// Look up number of vertices in outline
+	num = (sdword)gIndexList[pos][7];
+	// Zero indicates invalid case
+	if(!num) return null;
+
+	return &gIndexList[pos][0];
+}
+
+// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box
+
+//const Point&		eye,		//eye point (in bbox object coordinates)
+//const AABB&			box,		//3d bbox
+//const Matrix4x4&	mat,		//free transformation for bbox
+//float width, float height, int& num)
+float AABB::ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num)	const
+{
+	const sbyte* Outline = ComputeOutline(eye, num);
+	if(!Outline)	return -1.0f;
+
+	// Compute box vertices
+	Point vertexBox[8], dst[8];
+	ComputePoints(vertexBox);
+
+	// Transform all outline corners into 2D screen space
+	for(sdword i=0;i<num;i++)
+	{
+		HPoint Projected;
+		vertexBox[Outline[i]].ProjectToScreen(width, height, mat, Projected);
+		dst[i] = Projected;
+	}
+
+	float Sum = (dst[num-1][0] - dst[0][0]) * (dst[num-1][1] + dst[0][1]);
+
+	for(int i=0; i<num-1; i++)
+		Sum += (dst[i][0] - dst[i+1][0]) * (dst[i][1] + dst[i+1][1]);
+
+	return Sum * 0.5f;	//return computed value corrected by 0.5
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceAABB.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceAABB.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceAABB.h	(revision 216)
@@ -0,0 +1,505 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains AABB-related code. (axis-aligned bounding box)
+ *	\file		IceAABB.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 13, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEAABB_H__
+#define __ICEAABB_H__
+
+	// Forward declarations
+	class Sphere;
+
+//! Declarations of type-independent methods (most of them implemented in the .cpp)
+#define AABB_COMMON_METHODS																											\
+			AABB&			Add(const AABB& aabb);																					\
+			float			MakeCube(AABB& cube)																			const;	\
+			void			MakeSphere(Sphere& sphere)																		const;	\
+			const sbyte*	ComputeOutline(const Point& local_eye, sdword& num)												const;	\
+			float			ComputeBoxArea(const Point& eye, const Matrix4x4& mat, float width, float height, sdword& num)	const;	\
+			bool			IsInside(const AABB& box)																		const;	\
+			bool			ComputePlanes(Plane* planes)																	const;	\
+			bool			ComputePoints(Point* pts)																		const;	\
+			const Point*	GetVertexNormals()																				const;	\
+			const udword*	GetEdges()																						const;	\
+			const Point*	GetEdgeNormals()																				const;	\
+	inline_	BOOL			ContainsPoint(const Point& p)																	const	\
+							{																										\
+								if(p.x > GetMax(0) || p.x < GetMin(0)) return FALSE;												\
+								if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE;												\
+								if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE;												\
+								return TRUE;																						\
+							}
+
+	enum AABBType
+	{
+		AABB_RENDER			= 0,	//!< AABB used for rendering. Not visible == not rendered.
+		AABB_UPDATE			= 1,	//!< AABB used for dynamic updates. Not visible == not updated.
+
+		AABB_FORCE_DWORD	= 0x7fffffff,
+	};
+
+#ifdef USE_MINMAX
+
+	struct ICEMATHS_API ShadowAABB
+	{
+		Point	mMin;
+		Point	mMax;
+	};
+
+	class ICEMATHS_API AABB
+	{
+		public:
+		//! Constructor
+		inline_						AABB()	{}
+		//! Destructor
+		inline_						~AABB()	{}
+
+		//! Type-independent methods
+									AABB_COMMON_METHODS;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from min & max vectors.
+		 *	\param		min			[in] the min point
+		 *	\param		max			[in] the max point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetMinMax(const Point& min, const Point& max)		{ mMin = min;		mMax = max;									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from center & extents vectors.
+		 *	\param		c			[in] the center point
+		 *	\param		e			[in] the extents vector
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetCenterExtents(const Point& c, const Point& e)	{ mMin = c - e;		mMax = c + e;								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an empty AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetEmpty()											{ Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);	mMin = -p; mMax = p;}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups a point AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetPoint(const Point& pt)							{ mMin = mMax = pt;												}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the size of the AABB. The size is defined as the longest extent.
+		 *	\return		the size of the AABB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						float		GetSize()								const		{ Point e; GetExtents(e);	return e.Max();	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Extends the AABB.
+		 *	\param		p	[in] the next point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		Extend(const Point& p)
+									{
+										if(p.x > mMax.x)	mMax.x = p.x;
+										if(p.x < mMin.x)	mMin.x = p.x;
+
+										if(p.y > mMax.y)	mMax.y = p.y;
+										if(p.y < mMin.y)	mMin.y = p.y;
+
+										if(p.z > mMax.z)	mMax.z = p.z;
+										if(p.z < mMin.z)	mMin.z = p.z;
+									}
+		// Data access
+
+		//! Get min point of the box
+		inline_			void		GetMin(Point& min)						const		{ min = mMin;								}
+		//! Get max point of the box
+		inline_			void		GetMax(Point& max)						const		{ max = mMax;								}
+
+		//! Get component of the box's min point along a given axis
+		inline_			float		GetMin(udword axis)						const		{ return mMin[axis];						}
+		//! Get component of the box's max point along a given axis
+		inline_			float		GetMax(udword axis)						const		{ return mMax[axis];						}
+
+		//! Get box center
+		inline_			void		GetCenter(Point& center)				const		{ center = (mMax + mMin)*0.5f;				}
+		//! Get box extents
+		inline_			void		GetExtents(Point& extents)				const		{ extents = (mMax - mMin)*0.5f;				}
+
+		//! Get component of the box's center along a given axis
+		inline_			float		GetCenter(udword axis)					const		{ return (mMax[axis] + mMin[axis])*0.5f;	}
+		//! Get component of the box's extents along a given axis
+		inline_			float		GetExtents(udword axis)					const		{ return (mMax[axis] - mMin[axis])*0.5f;	}
+
+		//! Get box diagonal
+		inline_			void		GetDiagonal(Point& diagonal)			const		{ diagonal = mMax - mMin;					}
+		inline_			float		GetWidth()								const		{ return mMax.x - mMin.x;					}
+		inline_			float		GetHeight()								const		{ return mMax.y - mMin.y;					}
+		inline_			float		GetDepth()								const		{ return mMax.z - mMin.z;					}
+
+		//! Volume
+		inline_			float		GetVolume()								const		{ return GetWidth() * GetHeight() * GetDepth();		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the intersection between two AABBs.
+		 *	\param		a		[in] the other AABB
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a)				const
+									{
+										if(mMax.x < a.mMin.x
+										|| a.mMax.x < mMin.x
+										|| mMax.y < a.mMin.y
+										|| a.mMax.y < mMin.y
+										|| mMax.z < a.mMin.z
+										|| a.mMax.z < mMin.z)	return FALSE;
+
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the 1D-intersection between two AABBs, on a given axis.
+		 *	\param		a		[in] the other AABB
+		 *	\param		axis	[in] the axis (0, 1, 2)
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a, udword axis)	const
+									{
+										if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis])	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
+		 *	Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it)
+		 *	\param		mtx			[in] the transform matrix
+		 *	\param		aabb		[out] the transformed AABB [can be *this]
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void		Rotate(const Matrix4x4& mtx, AABB& aabb)	const
+									{
+										// The three edges transformed: you can efficiently transform an X-only vector
+										// by just getting the "X" column of the matrix
+										Point vx,vy,vz;
+										mtx.GetRow(0, vx);	vx *= (mMax.x - mMin.x);
+										mtx.GetRow(1, vy);	vy *= (mMax.y - mMin.y);
+										mtx.GetRow(2, vz);	vz *= (mMax.z - mMin.z);
+
+										// Transform the min point
+										aabb.mMin = aabb.mMax = mMin * mtx;
+
+										// Take the transformed min & axes and find new extents
+										// Using CPU code in the right place is faster...
+										if(IS_NEGATIVE_FLOAT(vx.x))	aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x;
+										if(IS_NEGATIVE_FLOAT(vx.y))	aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y;
+										if(IS_NEGATIVE_FLOAT(vx.z))	aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z;
+										if(IS_NEGATIVE_FLOAT(vy.x))	aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x;
+										if(IS_NEGATIVE_FLOAT(vy.y))	aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y;
+										if(IS_NEGATIVE_FLOAT(vy.z))	aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z;
+										if(IS_NEGATIVE_FLOAT(vz.x))	aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x;
+										if(IS_NEGATIVE_FLOAT(vz.y))	aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y;
+										if(IS_NEGATIVE_FLOAT(vz.z))	aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the AABB is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		IsValid()	const
+									{
+										// Consistency condition for (Min, Max) boxes: min < max
+										if(mMin.x > mMax.x)	return FALSE;
+										if(mMin.y > mMax.y)	return FALSE;
+										if(mMin.z > mMax.z)	return FALSE;
+										return TRUE;
+									}
+
+		//! Operator for AABB *= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator*=(float s)
+									{
+										Point Center;	GetCenter(Center);
+										Point Extents;	GetExtents(Extents);
+										SetCenterExtents(Center, Extents * s);
+										return *this;
+									}
+
+		//! Operator for AABB /= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator/=(float s)
+									{
+										Point Center;	GetCenter(Center);
+										Point Extents;	GetExtents(Extents);
+										SetCenterExtents(Center, Extents / s);
+										return *this;
+									}
+
+		//! Operator for AABB += Point. Translates the box.
+		inline_			AABB&		operator+=(const Point& trans)
+									{
+										mMin+=trans;
+										mMax+=trans;
+										return *this;
+									}
+		private:
+						Point		mMin;			//!< Min point
+						Point		mMax;			//!< Max point
+	};
+
+#else
+
+	class ICEMATHS_API AABB
+	{
+		public:
+		//! Constructor
+		inline_						AABB()	{}
+		//! Destructor
+		inline_						~AABB()	{}
+
+		//! Type-independent methods
+									AABB_COMMON_METHODS;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from min & max vectors.
+		 *	\param		min			[in] the min point
+		 *	\param		max			[in] the max point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetMinMax(const Point& min, const Point& max)		{ mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f;		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from center & extents vectors.
+		 *	\param		c			[in] the center point
+		 *	\param		e			[in] the extents vector
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetCenterExtents(const Point& c, const Point& e)	{ mCenter = c;	 mExtents = e;									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an empty AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetEmpty()											{ mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups a point AABB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		SetPoint(const Point& pt)							{ mCenter = pt; mExtents.Zero();								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the size of the AABB. The size is defined as the longest extent.
+		 *	\return		the size of the AABB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						float		GetSize()								const		{ return mExtents.Max();					}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Extends the AABB.
+		 *	\param		p	[in] the next point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						void		Extend(const Point& p)
+									{
+										Point Max = mCenter + mExtents;
+										Point Min = mCenter - mExtents;
+
+										if(p.x > Max.x)	Max.x = p.x;
+										if(p.x < Min.x)	Min.x = p.x;
+
+										if(p.y > Max.y)	Max.y = p.y;
+										if(p.y < Min.y)	Min.y = p.y;
+
+										if(p.z > Max.z)	Max.z = p.z;
+										if(p.z < Min.z)	Min.z = p.z;
+
+										SetMinMax(Min, Max);
+									}
+		// Data access
+
+		//! Get min point of the box
+		inline_			void		GetMin(Point& min)						const		{ min = mCenter - mExtents;					}
+		//! Get max point of the box
+		inline_			void		GetMax(Point& max)						const		{ max = mCenter + mExtents;					}
+
+		//! Get component of the box's min point along a given axis
+		inline_			float		GetMin(udword axis)						const		{ return mCenter[axis] - mExtents[axis];	}
+		//! Get component of the box's max point along a given axis
+		inline_			float		GetMax(udword axis)						const		{ return mCenter[axis] + mExtents[axis];	}
+
+		//! Get box center
+		inline_			void		GetCenter(Point& center)				const		{ center = mCenter;							}
+		//! Get box extents
+		inline_			void		GetExtents(Point& extents)				const		{ extents = mExtents;						}
+
+		//! Get component of the box's center along a given axis
+		inline_			float		GetCenter(udword axis)					const		{ return mCenter[axis];						}
+		//! Get component of the box's extents along a given axis
+		inline_			float		GetExtents(udword axis)					const		{ return mExtents[axis];					}
+
+		//! Get box diagonal
+		inline_			void		GetDiagonal(Point& diagonal)			const		{ diagonal = mExtents * 2.0f;				}
+		inline_			float		GetWidth()								const		{ return mExtents.x * 2.0f;					}
+		inline_			float		GetHeight()								const		{ return mExtents.y * 2.0f;					}
+		inline_			float		GetDepth()								const		{ return mExtents.z * 2.0f;					}
+
+		//! Volume
+		inline_			float		GetVolume()								const		{ return mExtents.x * mExtents.y * mExtents.z * 8.0f;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the intersection between two AABBs.
+		 *	\param		a		[in] the other AABB
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a)				const
+									{
+										float tx = mCenter.x - a.mCenter.x;	float ex = a.mExtents.x + mExtents.x;	if(AIR(tx) > IR(ex))	return FALSE;
+										float ty = mCenter.y - a.mCenter.y;	float ey = a.mExtents.y + mExtents.y;	if(AIR(ty) > IR(ey))	return FALSE;
+										float tz = mCenter.z - a.mCenter.z;	float ez = a.mExtents.z + mExtents.z;	if(AIR(tz) > IR(ez))	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	The standard intersection method from Gamasutra. Just here to check its speed against the one above.
+		 *	\param		a		[in] the other AABB
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			bool		GomezIntersect(const AABB& a)
+									{
+										Point	T = mCenter - a.mCenter;	// Vector from A to B
+										return	((fabsf(T.x) <= (a.mExtents.x + mExtents.x))
+												&& (fabsf(T.y) <= (a.mExtents.y + mExtents.y))
+												&& (fabsf(T.z) <= (a.mExtents.z + mExtents.z)));
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the 1D-intersection between two AABBs, on a given axis.
+		 *	\param		a		[in] the other AABB
+		 *	\param		axis	[in] the axis (0, 1, 2)
+		 *	\return		true on intersection
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		Intersect(const AABB& a, udword axis)	const
+									{
+										float t = mCenter[axis] - a.mCenter[axis];
+										float e = a.mExtents[axis] + mExtents[axis];
+										if(AIR(t) > IR(e))	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Recomputes the AABB after an arbitrary transform by a 4x4 matrix.
+		 *	\param		mtx			[in] the transform matrix
+		 *	\param		aabb		[out] the transformed AABB [can be *this]
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void		Rotate(const Matrix4x4& mtx, AABB& aabb)	const
+									{
+										// Compute new center
+										aabb.mCenter = mCenter * mtx;
+
+										// Compute new extents. FPU code & CPU code have been interleaved for improved performance.
+										Point Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x);
+										IR(Ex.x)&=0x7fffffff;	IR(Ex.y)&=0x7fffffff;	IR(Ex.z)&=0x7fffffff;
+
+										Point Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y);
+										IR(Ey.x)&=0x7fffffff;	IR(Ey.y)&=0x7fffffff;	IR(Ey.z)&=0x7fffffff;
+
+										Point Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z);
+										IR(Ez.x)&=0x7fffffff;	IR(Ez.y)&=0x7fffffff;	IR(Ez.z)&=0x7fffffff;
+
+										aabb.mExtents.x = Ex.x + Ey.x + Ez.x;
+										aabb.mExtents.y = Ex.y + Ey.y + Ez.y;
+										aabb.mExtents.z = Ex.z + Ey.z + Ez.z;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the AABB is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL		IsValid()	const
+									{
+										// Consistency condition for (Center, Extents) boxes: Extents >= 0
+										if(IS_NEGATIVE_FLOAT(mExtents.x))	return FALSE;
+										if(IS_NEGATIVE_FLOAT(mExtents.y))	return FALSE;
+										if(IS_NEGATIVE_FLOAT(mExtents.z))	return FALSE;
+										return TRUE;
+									}
+
+		//! Operator for AABB *= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator*=(float s)		{ mExtents*=s;	return *this;	}
+
+		//! Operator for AABB /= float. Scales the extents, keeps same center.
+		inline_			AABB&		operator/=(float s)		{ mExtents/=s;	return *this;	}
+
+		//! Operator for AABB += Point. Translates the box.
+		inline_			AABB&		operator+=(const Point& trans)
+									{
+										mCenter+=trans;
+										return *this;
+									}
+		private:
+						Point		mCenter;			//!< AABB Center
+						Point		mExtents;			//!< x, y and z extents
+	};
+
+#endif
+
+	inline_ void ComputeMinMax(const Point& p, Point& min, Point& max)
+	{
+		if(p.x > max.x)	max.x = p.x;
+		if(p.x < min.x)	min.x = p.x;
+
+		if(p.y > max.y)	max.y = p.y;
+		if(p.y < min.y)	min.y = p.y;
+
+		if(p.z > max.z)	max.z = p.z;
+		if(p.z < min.z)	min.z = p.z;
+	}
+
+	inline_ void ComputeAABB(AABB& aabb, const Point* list, udword nb_pts)
+	{
+		if(list)
+		{
+			Point Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
+			Point Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
+			while(nb_pts--)
+			{
+//				_prefetch(list+1);	// off by one ?
+				ComputeMinMax(*list++, Mini, Maxi);
+			}
+			aabb.SetMinMax(Mini, Maxi);
+		}
+	}
+
+#endif	// __ICEAABB_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceAxes.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceAxes.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceAxes.h	(revision 216)
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains axes definition.
+ *	\file		IceAxes.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEAXES_H__
+#define __ICEAXES_H__
+
+	enum PointComponent
+	{
+		X					= 0,
+		Y					= 1,
+		Z					= 2,
+		W					= 3,
+
+		FORCE_DWORD		= 0x7fffffff
+	};
+
+	enum AxisOrder
+	{
+		AXES_XYZ			= (X)|(Y<<2)|(Z<<4),
+		AXES_XZY			= (X)|(Z<<2)|(Y<<4),
+		AXES_YXZ			= (Y)|(X<<2)|(Z<<4),
+		AXES_YZX			= (Y)|(Z<<2)|(X<<4),
+		AXES_ZXY			= (Z)|(X<<2)|(Y<<4),
+		AXES_ZYX			= (Z)|(Y<<2)|(X<<4),
+
+		AXES_FORCE_DWORD	= 0x7fffffff
+	};
+
+	class ICEMATHS_API Axes
+	{
+		public:
+
+		inline_			Axes(AxisOrder order)
+						{
+							mAxis0 = (order   ) & 3;
+							mAxis1 = (order>>2) & 3;
+							mAxis2 = (order>>4) & 3;
+						}
+		inline_			~Axes()		{}
+
+				udword	mAxis0;
+				udword	mAxis1;
+				udword	mAxis2;
+	};
+
+#endif // __ICEAXES_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceBoundingSphere.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceBoundingSphere.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceBoundingSphere.h	(revision 216)
@@ -0,0 +1,142 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code to compute the minimal bounding sphere.
+ *	\file		IceBoundingSphere.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEBOUNDINGSPHERE_H__
+#define __ICEBOUNDINGSPHERE_H__
+
+	enum BSphereMethod
+	{
+		BS_NONE,
+		BS_GEMS,
+		BS_MINIBALL,
+
+		BS_FORCE_DWORD	= 0x7fffffff
+	};
+
+	class ICEMATHS_API Sphere
+	{
+		public:
+		//! Constructor
+		inline_					Sphere()																		{}
+		//! Constructor
+		inline_					Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius)	{}
+		//! Constructor
+								Sphere(udword nb_verts, const Point* verts);
+		//! Copy constructor
+		inline_					Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius)	{}
+		//! Destructor
+		inline_					~Sphere()																		{}
+
+				BSphereMethod	Compute(udword nb_verts, const Point* verts);
+				bool			FastCompute(udword nb_verts, const Point* verts);
+
+		// Access methods
+		inline_	const Point&	GetCenter()						const		{ return mCenter; }
+		inline_	float			GetRadius()						const		{ return mRadius; }
+
+		inline_	const Point&	Center()						const		{ return mCenter; }
+		inline_	float			Radius()						const		{ return mRadius; }
+
+		inline_	Sphere&			Set(const Point& center, float radius)		{ mCenter = center; mRadius = radius; return *this; }
+		inline_	Sphere&			SetCenter(const Point& center)				{ mCenter = center; return *this; }
+		inline_	Sphere&			SetRadius(float radius)						{ mRadius = radius; return *this; }
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a point is contained within the sphere.
+		 *	\param		p	[in] the point to test
+		 *	\return		true if inside the sphere
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool			Contains(const Point& p)		const
+								{
+									return mCenter.SquareDistance(p) <= mRadius*mRadius;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a sphere is contained within the sphere.
+		 *	\param		sphere	[in] the sphere to test
+		 *	\return		true if inside the sphere
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool			Contains(const Sphere& sphere)	const
+								{
+									// If our radius is the smallest, we can't possibly contain the other sphere
+									if(mRadius < sphere.mRadius)	return false;
+									// So r is always positive or null now
+									float r = mRadius - sphere.mRadius;
+									return mCenter.SquareDistance(sphere.mCenter) <= r*r;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a box is contained within the sphere.
+		 *	\param		aabb	[in] the box to test
+		 *	\return		true if inside the sphere
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_ BOOL			Contains(const AABB& aabb)	const
+								{
+									// I assume if all 8 box vertices are inside the sphere, so does the whole box.
+									// Sounds ok but maybe there's a better way?
+									float R2 = mRadius * mRadius;
+#ifdef USE_MIN_MAX
+									const Point& Max = ((ShadowAABB&)&aabb).mMax;
+									const Point& Min = ((ShadowAABB&)&aabb).mMin;
+#else
+									Point Max; aabb.GetMax(Max);
+									Point Min; aabb.GetMin(Min);
+#endif
+									Point p;
+									p.x=Max.x; p.y=Max.y; p.z=Max.z;	if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Max.x; p.y=Min.y;				if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Max.x; p.y=Max.y; p.z=Min.z;	if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Max.x; p.y=Min.y;				if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
+
+									return TRUE;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if the sphere intersects another sphere
+		 *	\param		sphere	[in] the other sphere
+		 *	\return		true if spheres overlap
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool			Intersect(const Sphere& sphere)	const
+								{
+									float r = mRadius + sphere.mRadius;
+									return mCenter.SquareDistance(sphere.mCenter) <= r*r;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the sphere is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	BOOL			IsValid()	const
+								{
+									// Consistency condition for spheres: Radius >= 0.0f
+									if(mRadius < 0.0f)	return FALSE;
+									return TRUE;
+								}
+		public:
+				Point			mCenter;		//!< Sphere center
+				float			mRadius;		//!< Sphere radius
+	};
+
+#endif // __ICEBOUNDINGSPHERE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.cpp	(revision 216)
@@ -0,0 +1,345 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a simple container class.
+ *	\file		IceContainer.cpp
+ *	\author		Pierre Terdiman
+ *	\date		February, 5, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a list of 32-bits values.
+ *	Use this class when you need to store an unknown number of values. The list is automatically
+ *	resized and can contains 32-bits entities (dwords or floats)
+ *
+ *	\class		Container
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ *	\date		08.15.98
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceCore;
+
+// Static members
+#ifdef CONTAINER_STATS
+udword Container::mNbContainers = 0;
+udword Container::mUsedRam = 0;
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor. No entries allocated there.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
+{
+#ifdef CONTAINER_STATS
+	mNbContainers++;
+	mUsedRam+=sizeof(Container);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor. Also allocates a given number of entries.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor)
+{
+#ifdef CONTAINER_STATS
+	mNbContainers++;
+	mUsedRam+=sizeof(Container);
+#endif
+	SetSize(size);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Copy constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
+{
+#ifdef CONTAINER_STATS
+	mNbContainers++;
+	mUsedRam+=sizeof(Container);
+#endif
+	*this = object;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.	Frees everything and leaves.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container::~Container()
+{
+	Empty();
+#ifdef CONTAINER_STATS
+	mNbContainers--;
+	mUsedRam-=GetUsedRam();
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Clears the container. All stored values are deleted, and it frees used ram.
+ *	\see		Reset()
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container& Container::Empty()
+{
+#ifdef CONTAINER_STATS
+	mUsedRam-=mMaxNbEntries*sizeof(udword);
+#endif
+	DELETEARRAY(mEntries);
+	mCurNbEntries = mMaxNbEntries = 0;
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Resizes the container.
+ *	\param		needed	[in] assume the container can be added at least "needed" values
+ *	\return		true if success.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Resize(udword needed)
+{
+#ifdef CONTAINER_STATS
+	// Subtract previous amount of bytes
+	mUsedRam-=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Get more entries
+	mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2;	// Default nb Entries = 2
+	if(mMaxNbEntries<mCurNbEntries + needed)	mMaxNbEntries = mCurNbEntries + needed;
+
+	// Get some bytes for new entries
+	udword*	NewEntries = new udword[mMaxNbEntries];
+	CHECKALLOC(NewEntries);
+
+#ifdef CONTAINER_STATS
+	// Add current amount of bytes
+	mUsedRam+=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Copy old data if needed
+	if(mCurNbEntries)	CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
+
+	// Delete old data
+	DELETEARRAY(mEntries);
+
+	// Assign new pointer
+	mEntries = NewEntries;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Sets the initial size of the container. If it already contains something, it's discarded.
+ *	\param		nb		[in] Number of entries
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::SetSize(udword nb)
+{
+	// Make sure it's empty
+	Empty();
+
+	// Checkings
+	if(!nb)	return false;
+
+	// Initialize for nb entries
+	mMaxNbEntries = nb;
+
+	// Get some bytes for new entries
+	mEntries = new udword[mMaxNbEntries];
+	CHECKALLOC(mEntries);
+
+#ifdef CONTAINER_STATS
+	// Add current amount of bytes
+	mUsedRam+=mMaxNbEntries*sizeof(udword);
+#endif
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the container and get rid of unused bytes.
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Refit()
+{
+#ifdef CONTAINER_STATS
+	// Subtract previous amount of bytes
+	mUsedRam-=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Get just enough entries
+	mMaxNbEntries = mCurNbEntries;
+	if(!mMaxNbEntries)	return false;
+
+	// Get just enough bytes
+	udword*	NewEntries = new udword[mMaxNbEntries];
+	CHECKALLOC(NewEntries);
+
+#ifdef CONTAINER_STATS
+	// Add current amount of bytes
+	mUsedRam+=mMaxNbEntries*sizeof(udword);
+#endif
+
+	// Copy old data
+	CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
+
+	// Delete old data
+	DELETEARRAY(mEntries);
+
+	// Assign new pointer
+	mEntries = NewEntries;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks whether the container already contains a given value.
+ *	\param		entry			[in] the value to look for in the container
+ *	\param		location		[out] a possible pointer to store the entry location
+ *	\see		Add(udword entry)
+ *	\see		Add(float entry)
+ *	\see		Empty()
+ *	\return		true if the value has been found in the container, else false.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Contains(udword entry, udword* location) const
+{
+	// Look for the entry
+	for(udword i=0;i<mCurNbEntries;i++)
+	{
+		if(mEntries[i]==entry)
+		{
+			if(location)	*location = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Deletes an entry. If the container contains such an entry, it's removed.
+ *	\param		entry		[in] the value to delete.
+ *	\return		true if the value has been found in the container, else false.
+ *	\warning	This method is arbitrary slow (O(n)) and should be used carefully. Insertion order is not preserved.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::Delete(udword entry)
+{
+	// Look for the entry
+	for(udword i=0;i<mCurNbEntries;i++)
+	{
+		if(mEntries[i]==entry)
+		{
+			// Entry has been found at index i. The strategy is to copy the last current entry at index i, and decrement the current number of entries.
+			DeleteIndex(i);
+			return true;
+		}
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Deletes an entry, preserving the insertion order. If the container contains such an entry, it's removed.
+ *	\param		entry		[in] the value to delete.
+ *	\return		true if the value has been found in the container, else false.
+ *	\warning	This method is arbitrary slow (O(n)) and should be used carefully.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Container::DeleteKeepingOrder(udword entry)
+{
+	// Look for the entry
+	for(udword i=0;i<mCurNbEntries;i++)
+	{
+		if(mEntries[i]==entry)
+		{
+			// Entry has been found at index i.
+			// Shift entries to preserve order. You really should use a linked list instead.
+			mCurNbEntries--;
+			for(udword j=i;j<mCurNbEntries;j++)
+			{
+				mEntries[j] = mEntries[j+1];
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the next entry, starting from input one.
+ *	\param		entry		[in/out] On input, the entry to look for. On output, the next entry
+ *	\param		find_mode	[in] wrap/clamp
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container& Container::FindNext(udword& entry, FindMode find_mode)
+{
+	udword Location;
+	if(Contains(entry, &Location))
+	{
+		Location++;
+		if(Location==mCurNbEntries)	Location = find_mode==FIND_WRAP ? 0 : mCurNbEntries-1;
+		entry = mEntries[Location];
+	}
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the previous entry, starting from input one.
+ *	\param		entry		[in/out] On input, the entry to look for. On output, the previous entry
+ *	\param		find_mode	[in] wrap/clamp
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Container& Container::FindPrev(udword& entry, FindMode find_mode)
+{
+	udword Location;
+	if(Contains(entry, &Location))
+	{
+		Location--;
+		if(Location==0xffffffff)	Location = find_mode==FIND_WRAP ? mCurNbEntries-1 : 0;
+		entry = mEntries[Location];
+	}
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the ram used by the container.
+ *	\return		the ram used in bytes.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword Container::GetUsedRam() const
+{
+	return sizeof(Container) + mMaxNbEntries * sizeof(udword);
+}
+
+/*void Container::operator=(const Container& object)
+{
+	SetSize(object.GetNbEntries());
+	CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
+	mCurNbEntries = mMaxNbEntries;
+}*/
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.h	(revision 216)
@@ -0,0 +1,212 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a simple container class.
+ *	\file		IceContainer.h
+ *	\author		Pierre Terdiman
+ *	\date		February, 5, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICECONTAINER_H__
+#define __ICECONTAINER_H__
+
+	#define CONTAINER_STATS
+
+	enum FindMode
+	{
+		FIND_CLAMP,
+		FIND_WRAP,
+
+		FIND_FORCE_DWORD = 0x7fffffff
+	};
+
+	class ICECORE_API Container
+	{
+		public:
+		// Constructor / Destructor
+								Container();
+								Container(const Container& object);
+								Container(udword size, float growth_factor);
+								~Container();
+		// Management
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	A O(1) method to add a value in the container. The container is automatically resized if needed.
+		 *	The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
+		 *	costs a lot more than the call overhead...
+		 *
+		 *	\param		entry		[in] a udword to store in the container
+		 *	\see		Add(float entry)
+		 *	\see		Empty()
+		 *	\see		Contains(udword entry)
+		 *	\return		Self-Reference
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	Container&		Add(udword entry)
+								{
+									// Resize if needed
+									if(mCurNbEntries==mMaxNbEntries)	Resize();
+
+									// Add new entry
+									mEntries[mCurNbEntries++]	= entry;
+									return *this;
+								}
+
+		inline_	Container&		Add(const udword* entries, udword nb)
+								{
+									// Resize if needed
+									if(mCurNbEntries+nb>mMaxNbEntries)	Resize(nb);
+
+									// Add new entry
+									CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
+									mCurNbEntries+=nb;
+									return *this;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	A O(1) method to add a value in the container. The container is automatically resized if needed.
+		 *	The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
+		 *	costs a lot more than the call overhead...
+		 *
+		 *	\param		entry		[in] a float to store in the container
+		 *	\see		Add(udword entry)
+		 *	\see		Empty()
+		 *	\see		Contains(udword entry)
+		 *	\return		Self-Reference
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	Container&		Add(float entry)
+								{
+									// Resize if needed
+									if(mCurNbEntries==mMaxNbEntries)	Resize();
+
+									// Add new entry
+									mEntries[mCurNbEntries++]	= IR(entry);
+									return *this;
+								}
+
+		inline_	Container&		Add(const float* entries, udword nb)
+								{
+									// Resize if needed
+									if(mCurNbEntries+nb>mMaxNbEntries)	Resize(nb);
+
+									// Add new entry
+									CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
+									mCurNbEntries+=nb;
+									return *this;
+								}
+
+		//! Add unique [slow]
+		inline_	Container&		AddUnique(udword entry)
+								{
+									if(!Contains(entry))	Add(entry);
+									return *this;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Clears the container. All stored values are deleted, and it frees used ram.
+		 *	\see		Reset()
+		 *	\return		Self-Reference
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				Container&		Empty();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
+		 *	That's a kind of temporal coherence.
+		 *	\see		Empty()
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	void			Reset()
+								{
+									// Avoid the write if possible
+									// ### CMOV
+									if(mCurNbEntries)	mCurNbEntries = 0;
+								}
+
+		// HANDLE WITH CARE
+		inline_	void			ForceSize(udword size)
+								{
+									mCurNbEntries = size;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Sets the initial size of the container. If it already contains something, it's discarded.
+		 *	\param		nb		[in] Number of entries
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool			SetSize(udword nb);
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Refits the container and get rid of unused bytes.
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool			Refit();
+
+		// Checks whether the container already contains a given value.
+				bool			Contains(udword entry, udword* location=null) const;
+		// Deletes an entry - doesn't preserve insertion order.
+				bool			Delete(udword entry);
+		// Deletes an entry - does preserve insertion order.
+				bool			DeleteKeepingOrder(udword entry);
+		//! Deletes the very last entry.
+		inline_	void			DeleteLastEntry()						{ if(mCurNbEntries)	mCurNbEntries--;			}
+		//! Deletes the entry whose index is given
+		inline_	void			DeleteIndex(udword index)				{ mEntries[index] = mEntries[--mCurNbEntries];	}
+
+		// Helpers
+				Container&		FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
+				Container&		FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
+		// Data access.
+		inline_	udword			GetNbEntries()					const	{ return mCurNbEntries;					}	//!< Returns the current number of entries.
+		inline_	udword			GetEntry(udword i)				const	{ return mEntries[i];					}	//!< Returns ith entry
+		inline_	udword*			GetEntries()					const	{ return mEntries;						}	//!< Returns the list of entries.
+
+		inline_	udword			GetFirst()						const	{ return mEntries[0];					}
+		inline_	udword			GetLast()						const	{ return mEntries[mCurNbEntries-1];		}
+
+		// Growth control
+		inline_	float			GetGrowthFactor()				const	{ return mGrowthFactor;					}	//!< Returns the growth factor
+		inline_	void			SetGrowthFactor(float growth)			{ mGrowthFactor = growth;				}	//!< Sets the growth factor
+		inline_	bool			IsFull()						const	{ return mCurNbEntries==mMaxNbEntries;	}	//!< Checks the container is full
+		inline_	BOOL			IsNotEmpty()					const	{ return mCurNbEntries;					}	//!< Checks the container is empty
+
+		//! Read-access as an array
+		inline_	udword			operator[](udword i)			const	{ ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];	}
+		//! Write-access as an array
+		inline_	udword&			operator[](udword i)					{ ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];	}
+
+		// Stats
+				udword			GetUsedRam()					const;
+
+		//! Operator for "Container A = Container B"
+				//void			operator = (const Container& object);
+
+#ifdef CONTAINER_STATS
+		inline_	udword			GetNbContainers()				const	{ return mNbContainers;		}
+		inline_	udword			GetTotalBytes()					const	{ return mUsedRam;			}
+		private:
+
+		static	udword			mNbContainers;		//!< Number of containers around
+		static	udword			mUsedRam;			//!< Amount of bytes used by containers in the system
+#endif
+		private:
+		// Resizing
+				bool			Resize(udword needed=1);
+		// Data
+				udword			mMaxNbEntries;		//!< Maximum possible number of entries
+				udword			mCurNbEntries;		//!< Current number of entries
+				udword*			mEntries;			//!< List of entries
+				float			mGrowthFactor;		//!< Resize: new number of entries = old number * mGrowthFactor
+	};
+
+#endif // __ICECONTAINER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceFPU.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceFPU.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceFPU.h	(revision 216)
@@ -0,0 +1,337 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains FPU related code.
+ *	\file		IceFPU.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEFPU_H__
+#define __ICEFPU_H__
+
+	#define	SIGN_BITMASK			0x80000000
+
+	//! Integer representation of a floating-point value.
+	#define IR(x)					((udword&)(x))
+
+	//! Signed integer representation of a floating-point value.
+	#define SIR(x)					((sdword&)(x))
+
+	//! Absolute integer representation of a floating-point value
+	#define AIR(x)					(IR(x)&0x7fffffff)
+
+	//! Floating-point representation of an integer value.
+	#define FR(x)					((float&)(x))
+
+	//! Integer-based comparison of a floating point value.
+	//! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context.
+	#define IS_NEGATIVE_FLOAT(x)	(IR(x)&0x80000000)
+
+	//! Fast fabs for floating-point values. It just clears the sign bit.
+	//! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context.
+	inline_ float FastFabs(float x)
+	{
+		udword FloatBits = IR(x)&0x7fffffff;
+		return FR(FloatBits);
+	}
+
+	//! Fast square root for floating-point values.
+	inline_ float FastSqrt(float square)
+	{
+#ifdef _MSC_VER
+			float retval;
+
+			__asm {
+					mov             eax, square
+					sub             eax, 0x3F800000
+					sar             eax, 1
+					add             eax, 0x3F800000
+					mov             [retval], eax
+			}
+			return retval;
+#else
+			return sqrt(square);
+#endif
+	}
+
+	//! Saturates positive to zero.
+	inline_ float fsat(float f)
+	{
+		udword y = (udword&)f & ~((sdword&)f >>31);
+		return (float&)y;
+	}
+
+	//! Computes 1.0f / sqrtf(x).
+	inline_ float frsqrt(float f)
+	{
+		float x = f * 0.5f;
+		udword y = 0x5f3759df - ((udword&)f >> 1);
+		// Iteration...
+		(float&)y  = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) );
+		// Result
+		return (float&)y;
+	}
+
+	//! Computes 1.0f / sqrtf(x). Comes from NVIDIA.
+	inline_ float InvSqrt(const float& x)
+	{
+		udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1;   
+		float y = *(float*)&tmp;                                             
+		return y * (1.47f - 0.47f * x * y * y);
+	}
+
+	//! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above.
+	//! See http://www.magic-software.com/3DGEDInvSqrt.html
+	inline_ float RSqrt(float number)
+	{
+		long i;
+		float x2, y;
+		const float threehalfs = 1.5f;
+
+		x2 = number * 0.5f;
+		y  = number;
+		i  = * (long *) &y;
+		i  = 0x5f3759df - (i >> 1);
+		y  = * (float *) &i;
+		y  = y * (threehalfs - (x2 * y * y));
+
+		return y;
+	}
+
+	//! TO BE DOCUMENTED
+	inline_ float fsqrt(float f)
+	{
+		udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000;
+		// Iteration...?
+		// (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f;
+		// Result
+		return (float&)y;
+	}
+
+	//! Returns the float ranged espilon value.
+	inline_ float fepsilon(float f)
+	{
+		udword b = (udword&)f & 0xff800000;
+		udword a = b | 0x00000001;
+		(float&)a -= (float&)b;
+		// Result
+		return (float&)a;
+	}
+
+	//! Is the float valid ?
+	inline_ bool IsNAN(float value)				{ return (IR(value)&0x7f800000) == 0x7f800000;	}
+	inline_ bool IsIndeterminate(float value)	{ return IR(value) == 0xffc00000;				}
+	inline_ bool IsPlusInf(float value)			{ return IR(value) == 0x7f800000;				}
+	inline_ bool IsMinusInf(float value)		{ return IR(value) == 0xff800000;				}
+
+	inline_	bool IsValidFloat(float value)
+	{
+		if(IsNAN(value))			return false;
+		if(IsIndeterminate(value))	return false;
+		if(IsPlusInf(value))		return false;
+		if(IsMinusInf(value))		return false;
+		return true;
+	}
+
+	#define CHECK_VALID_FLOAT(x)	ASSERT(IsValidFloat(x));
+
+/*
+	//! FPU precision setting function.
+	inline_ void SetFPU()
+	{
+		// This function evaluates whether the floating-point
+		// control word is set to single precision/round to nearest/
+		// exceptions disabled. If these conditions don't hold, the
+		// function changes the control word to set them and returns
+		// TRUE, putting the old control word value in the passback
+		// location pointed to by pwOldCW.
+		{
+			uword wTemp, wSave;
+ 
+			__asm fstcw wSave
+			if (wSave & 0x300 ||            // Not single mode
+				0x3f != (wSave & 0x3f) ||   // Exceptions enabled
+				wSave & 0xC00)              // Not round to nearest mode
+			{
+				__asm
+				{
+					mov ax, wSave
+					and ax, not 300h    ;; single mode
+					or  ax, 3fh         ;; disable all exceptions
+					and ax, not 0xC00   ;; round to nearest mode
+					mov wTemp, ax
+					fldcw   wTemp
+				}
+			}
+		}
+	}
+*/
+	//! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON)
+	inline_ float ComputeFloatEpsilon()
+	{
+		float f = 1.0f;
+		((udword&)f)^=1;
+		return f - 1.0f;	// You can check it's the same as FLT_EPSILON
+	}
+
+	inline_ bool IsFloatZero(float x, float epsilon=1e-6f)
+	{
+		return x*x < epsilon;
+	}
+
+	#define FCOMI_ST0	_asm	_emit	0xdb	_asm	_emit	0xf0
+	#define FCOMIP_ST0	_asm	_emit	0xdf	_asm	_emit	0xf0
+	#define FCMOVB_ST0	_asm	_emit	0xda	_asm	_emit	0xc0
+	#define FCMOVNB_ST0	_asm	_emit	0xdb	_asm	_emit	0xc0
+
+	#define FCOMI_ST1	_asm	_emit	0xdb	_asm	_emit	0xf1
+	#define FCOMIP_ST1	_asm	_emit	0xdf	_asm	_emit	0xf1
+	#define FCMOVB_ST1	_asm	_emit	0xda	_asm	_emit	0xc1
+	#define FCMOVNB_ST1	_asm	_emit	0xdb	_asm	_emit	0xc1
+
+	#define FCOMI_ST2	_asm	_emit	0xdb	_asm	_emit	0xf2
+	#define FCOMIP_ST2	_asm	_emit	0xdf	_asm	_emit	0xf2
+	#define FCMOVB_ST2	_asm	_emit	0xda	_asm	_emit	0xc2
+	#define FCMOVNB_ST2	_asm	_emit	0xdb	_asm	_emit	0xc2
+
+	#define FCOMI_ST3	_asm	_emit	0xdb	_asm	_emit	0xf3
+	#define FCOMIP_ST3	_asm	_emit	0xdf	_asm	_emit	0xf3
+	#define FCMOVB_ST3	_asm	_emit	0xda	_asm	_emit	0xc3
+	#define FCMOVNB_ST3	_asm	_emit	0xdb	_asm	_emit	0xc3
+
+	#define FCOMI_ST4	_asm	_emit	0xdb	_asm	_emit	0xf4
+	#define FCOMIP_ST4	_asm	_emit	0xdf	_asm	_emit	0xf4
+	#define FCMOVB_ST4	_asm	_emit	0xda	_asm	_emit	0xc4
+	#define FCMOVNB_ST4	_asm	_emit	0xdb	_asm	_emit	0xc4
+
+	#define FCOMI_ST5	_asm	_emit	0xdb	_asm	_emit	0xf5
+	#define FCOMIP_ST5	_asm	_emit	0xdf	_asm	_emit	0xf5
+	#define FCMOVB_ST5	_asm	_emit	0xda	_asm	_emit	0xc5
+	#define FCMOVNB_ST5	_asm	_emit	0xdb	_asm	_emit	0xc5
+
+	#define FCOMI_ST6	_asm	_emit	0xdb	_asm	_emit	0xf6
+	#define FCOMIP_ST6	_asm	_emit	0xdf	_asm	_emit	0xf6
+	#define FCMOVB_ST6	_asm	_emit	0xda	_asm	_emit	0xc6
+	#define FCMOVNB_ST6	_asm	_emit	0xdb	_asm	_emit	0xc6
+
+	#define FCOMI_ST7	_asm	_emit	0xdb	_asm	_emit	0xf7
+	#define FCOMIP_ST7	_asm	_emit	0xdf	_asm	_emit	0xf7
+	#define FCMOVB_ST7	_asm	_emit	0xda	_asm	_emit	0xc7
+	#define FCMOVNB_ST7	_asm	_emit	0xdb	_asm	_emit	0xc7
+
+	//! A global function to find MAX(a,b) using FCOMI/FCMOV
+	inline_ float FCMax2(float a, float b)
+	{
+#ifdef _MSC_VER
+		float Res;
+		_asm	fld		[a]
+		_asm	fld		[b]
+		FCOMI_ST1
+		FCMOVB_ST1
+		_asm	fstp	[Res]
+		_asm	fcomp
+		return Res;
+#else
+		return (a > b) ? a : b;
+#endif
+	}
+
+	//! A global function to find MIN(a,b) using FCOMI/FCMOV
+	inline_ float FCMin2(float a, float b)
+	{
+#ifdef _MSC_VER
+		float Res;
+		_asm	fld		[a]
+		_asm	fld		[b]
+		FCOMI_ST1
+		FCMOVNB_ST1
+		_asm	fstp	[Res]
+		_asm	fcomp
+		return Res;
+#else
+		return (a < b) ? a : b;
+#endif
+	}
+
+	//! A global function to find MAX(a,b,c) using FCOMI/FCMOV
+	inline_ float FCMax3(float a, float b, float c)
+	{
+#ifdef _MSC_VER
+		float Res;
+		_asm	fld		[a]
+		_asm	fld		[b]
+		_asm	fld		[c]
+		FCOMI_ST1
+		FCMOVB_ST1
+		FCOMI_ST2
+		FCMOVB_ST2
+		_asm	fstp	[Res]
+		_asm	fcompp
+		return Res;
+#else
+		return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
+#endif
+	}
+
+	//! A global function to find MIN(a,b,c) using FCOMI/FCMOV
+	inline_ float FCMin3(float a, float b, float c)
+	{
+#ifdef _MSC_VER
+		float Res;
+		_asm	fld		[a]
+		_asm	fld		[b]
+		_asm	fld		[c]
+		FCOMI_ST1
+		FCMOVNB_ST1
+		FCOMI_ST2
+		FCMOVNB_ST2
+		_asm	fstp	[Res]
+		_asm	fcompp
+		return Res;
+#else
+		return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
+#endif
+	}
+
+	inline_ int ConvertToSortable(float f)
+	{
+		int& Fi = (int&)f;
+		int Fmask = (Fi>>31);
+		Fi ^= Fmask;
+		Fmask &= ~(1<<31);
+		Fi -= Fmask;
+		return Fi;
+	}
+
+	enum FPUMode
+	{
+		FPU_FLOOR		= 0,
+		FPU_CEIL		= 1,
+		FPU_BEST		= 2,
+
+		FPU_FORCE_DWORD	= 0x7fffffff
+	};
+
+	FUNCTION ICECORE_API FPUMode	GetFPUMode();
+	FUNCTION ICECORE_API void		SaveFPU();
+	FUNCTION ICECORE_API void		RestoreFPU();
+	FUNCTION ICECORE_API void		SetFPUFloorMode();
+	FUNCTION ICECORE_API void		SetFPUCeilMode();
+	FUNCTION ICECORE_API void		SetFPUBestMode();
+
+	FUNCTION ICECORE_API void		SetFPUPrecision24();
+	FUNCTION ICECORE_API void		SetFPUPrecision53();
+	FUNCTION ICECORE_API void		SetFPUPrecision64();
+	FUNCTION ICECORE_API void		SetFPURoundingChop();
+	FUNCTION ICECORE_API void		SetFPURoundingUp();
+	FUNCTION ICECORE_API void		SetFPURoundingDown();
+	FUNCTION ICECORE_API void		SetFPURoundingNear();
+
+	FUNCTION ICECORE_API int		intChop(const float& f);
+	FUNCTION ICECORE_API int		intFloor(const float& f);
+	FUNCTION ICECORE_API int		intCeil(const float& f);
+
+#endif // __ICEFPU_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceHPoint.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceHPoint.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceHPoint.cpp	(revision 216)
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for homogeneous points.
+ *	\file		IceHPoint.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Homogeneous point.
+ *
+ *	Use it:
+ *	- for clipping in homogeneous space (standard way)
+ *	- to differentiate between points (w=1) and vectors (w=0).
+ *	- in some cases you can also use it instead of Point for padding reasons.
+ *
+ *	\class		HPoint
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ *	\warning	No cross-product in 4D.
+ *	\warning	HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Point Mul = HPoint * Matrix3x3;
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Point HPoint::operator*(const Matrix3x3& mat) const
+{
+	return Point(
+	x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0],
+	x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1],
+	x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] );
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// HPoint Mul = HPoint * Matrix4x4;
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HPoint HPoint::operator*(const Matrix4x4& mat) const
+{
+	return HPoint(
+	x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0],
+	x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1],
+	x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2],
+	x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// HPoint *= Matrix4x4
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HPoint& HPoint::operator*=(const Matrix4x4& mat)
+{
+	float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0];
+	float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1];
+	float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2];
+	float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3];
+
+	x = xp; y = yp; z = zp; w = wp;
+
+	return	*this;
+}
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceHPoint.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceHPoint.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceHPoint.h	(revision 216)
@@ -0,0 +1,160 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for homogeneous points.
+ *	\file		IceHPoint.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEHPOINT_H__
+#define __ICEHPOINT_H__
+
+	class ICEMATHS_API HPoint : public Point
+	{
+		public:
+
+		//! Empty constructor
+		inline_				HPoint()																		{}
+		//! Constructor from floats
+		inline_				HPoint(float xx, float yy, float zz, float ww=0.0f) : Point(xx, yy, zz), w(ww)	{}
+		//! Constructor from array
+		inline_				HPoint(const float f[4]) : Point(f), w(f[3])									{}
+		//! Constructor from a Point
+		inline_				HPoint(const Point& p, float ww=0.0f) : Point(p), w(ww)							{}
+		//! Destructor
+		inline_				~HPoint()																		{}
+
+		//! Clear the point
+		inline_	HPoint&		Zero()											{ x =			y =			z =			w = 0.0f;		return *this;	}
+
+		//! Assignment from values
+		inline_	HPoint&		Set(float xx, float yy, float zz, float ww )	{ x  = xx;		y  = yy;	z  = zz;	w  = ww;		return *this;	}
+		//! Assignment from array
+		inline_	HPoint&		Set(const float f[4])							{ x  = f[X];	y  = f[Y];	z  = f[Z];	w  = f[W];		return *this;	}
+		//! Assignment from another h-point
+		inline_	HPoint&		Set(const HPoint& src)							{ x  = src.x;	y  = src.y;	z  = src.z;	w = src.w;		return *this;	}
+
+		//! Add a vector
+		inline_	HPoint&		Add(float xx, float yy, float zz, float ww )	{ x += xx;		y += yy;	z += zz;	w += ww;		return *this;	}
+		//! Add a vector
+		inline_	HPoint&		Add(const float f[4])							{ x += f[X];	y += f[Y];	z += f[Z];	w += f[W];		return *this;	}
+
+		//! Subtract a vector
+		inline_	HPoint&		Sub(float xx, float yy, float zz, float ww )	{ x -= xx;		y -= yy;	z -= zz;	w -= ww;		return *this;	}
+		//! Subtract a vector
+		inline_	HPoint&		Sub(const float f[4])							{ x -= f[X];	y -= f[Y];	z -= f[Z];	w -= f[W];		return *this;	}
+		
+		//! Multiplies by a scalar
+		inline_	HPoint&		Mul(float s)									{ x *= s;		y *= s;		z *= s;		w *= s;			return *this;	}
+
+		//! Returns MIN(x, y, z, w);
+				float		Min()								const		{ return MIN(x, MIN(y, MIN(z, w)));										}
+		//! Returns MAX(x, y, z, w);
+				float		Max()								const		{ return MAX(x, MAX(y, MAX(z, w)));										}
+		//! Sets each element to be componentwise minimum
+				HPoint&		Min(const HPoint& p)							{ x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w);	return *this;	}
+		//! Sets each element to be componentwise maximum
+				HPoint&		Max(const HPoint& p)							{ x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w);	return *this;	}
+
+		//! Computes square magnitude
+		inline_	float		SquareMagnitude()					const		{ return x*x + y*y + z*z + w*w;											}
+		//! Computes magnitude
+		inline_	float		Magnitude()							const		{ return sqrtf(x*x + y*y + z*z + w*w);									}
+
+		//! Normalize the vector
+		inline_	HPoint&		Normalize()
+							{
+								float M = Magnitude();
+								if(M)
+								{
+									M = 1.0f / M;
+									x *= M;
+									y *= M;
+									z *= M;
+									w *= M;
+								}
+								return *this;
+							}
+
+		// Arithmetic operators
+		//! Operator for HPoint Negate = - HPoint;
+		inline_	HPoint		operator-()							const		{ return HPoint(-x, -y, -z, -w);							}
+
+		//! Operator for HPoint Plus  = HPoint + HPoint;
+		inline_	HPoint		operator+(const HPoint& p)			const		{ return HPoint(x + p.x, y + p.y, z + p.z, w + p.w);		}
+		//! Operator for HPoint Minus = HPoint - HPoint;
+		inline_	HPoint		operator-(const HPoint& p)			const		{ return HPoint(x - p.x, y - p.y, z - p.z, w - p.w);		}
+
+		//! Operator for HPoint Mul   = HPoint * HPoint;
+		inline_	HPoint		operator*(const HPoint& p)			const		{ return HPoint(x * p.x, y * p.y, z * p.z, w * p.w);		}
+		//! Operator for HPoint Scale = HPoint * float;
+		inline_	HPoint		operator*(float s)					const		{ return HPoint(x * s, y * s, z * s, w * s);				}
+		//! Operator for HPoint Scale = float * HPoint;
+		inline_	friend	HPoint	operator*(float s, const HPoint& p)			{ return HPoint(s * p.x, s * p.y, s * p.z, s * p.w);		}
+
+		//! Operator for HPoint Div   = HPoint / HPoint;
+		inline_	HPoint		operator/(const HPoint& p)			const		{ return HPoint(x / p.x, y / p.y, z / p.z, w / p.w);		}
+		//! Operator for HPoint Scale = HPoint / float;
+		inline_	HPoint		operator/(float s)					const		{ s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s);	}
+		//! Operator for HPoint Scale = float / HPoint;
+		inline_	friend	HPoint	operator/(float s, const HPoint& p)			{ return HPoint(s / p.x, s / p.y, s / p.z, s / p.w);		}
+
+		//! Operator for float DotProd = HPoint | HPoint;
+		inline_	float		operator|(const HPoint& p)			const		{ return x*p.x + y*p.y + z*p.z + w*p.w;						}
+		// No cross-product in 4D
+
+		//! Operator for HPoint += HPoint;
+		inline_	HPoint&		operator+=(const HPoint& p)						{ x += p.x; y += p.y; z += p.z; w += p.w;	return *this;	}
+		//! Operator for HPoint += float;
+		inline_	HPoint&		operator+=(float s)								{ x += s;   y += s;   z += s;   w += s;		return *this;	}
+
+		//! Operator for HPoint -= HPoint;
+		inline_	HPoint&		operator-=(const HPoint& p)						{ x -= p.x; y -= p.y; z -= p.z; w -= p.w;	return *this;	}
+		//! Operator for HPoint -= float;
+		inline_	HPoint&		operator-=(float s)								{ x -= s;   y -= s;   z -= s;   w -= s;		return *this;	}
+
+		//! Operator for HPoint *= HPoint;
+		inline_	HPoint&		operator*=(const HPoint& p)						{ x *= p.x; y *= p.y; z *= p.z; w *= p.w;	return *this;	}
+		//! Operator for HPoint *= float;
+		inline_	HPoint&		operator*=(float s)								{ x*=s; y*=s; z*=s; w*=s;					return *this;	}
+
+		//! Operator for HPoint /= HPoint;
+		inline_	HPoint&		operator/=(const HPoint& p)						{ x /= p.x; y /= p.y; z /= p.z; w /= p.w;	return *this;	}
+		//! Operator for HPoint /= float;
+		inline_	HPoint&		operator/=(float s)								{ s = 1.0f / s; x*=s; y*=s; z*=s; w*=s;		return *this;	}
+
+		// Arithmetic operators
+
+		//! Operator for Point Mul = HPoint * Matrix3x3;
+				Point		operator*(const Matrix3x3& mat)		const;
+		//! Operator for HPoint Mul = HPoint * Matrix4x4;
+				HPoint		operator*(const Matrix4x4& mat)		const;
+
+		// HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4
+		//! Operator for HPoint *= Matrix4x4
+				HPoint&		operator*=(const Matrix4x4& mat);
+
+		// Logical operators
+
+		//! Operator for "if(HPoint==HPoint)"
+		inline_	bool		operator==(const HPoint& p)			const		{ return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w));			}
+		//! Operator for "if(HPoint!=HPoint)"
+		inline_	bool		operator!=(const HPoint& p)			const		{ return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w));			}
+
+		// Cast operators
+
+		//! Cast a HPoint to a Point. w is discarded.
+#ifdef _MSC_VER
+		inline_				operator	Point()					const		{ return Point(x, y, z);									}
+		// gcc complains that conversion to a base class will never use a type conversion operator
+#endif
+
+		public:
+				float		w;
+	};
+
+#endif // __ICEHPOINT_H__
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceIndexedTriangle.cpp	(revision 216)
@@ -0,0 +1,548 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a handy indexed triangle class.
+ *	\file		IceIndexedTriangle.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 17, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains an indexed triangle class.
+ *
+ *	\class		Triangle
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ *	\date		08.15.98
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Flips the winding order.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::Flip()
+{
+	Swap(mVRef[1], mVRef[2]);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle area.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\return		the area
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::Area(const Point* verts)	const
+{
+	if(!verts)	return 0.0f;
+	const Point& p0 = verts[0];
+	const Point& p1 = verts[1];
+	const Point& p2 = verts[2];
+	return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle perimeter.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\return		the perimeter
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::Perimeter(const Point* verts)	const
+{
+	if(!verts)	return 0.0f;
+	const Point& p0 = verts[0];
+	const Point& p1 = verts[1];
+	const Point& p2 = verts[2];
+	return		p0.Distance(p1)
+			+	p0.Distance(p2)
+			+	p1.Distance(p2);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle compacity.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\return		the compacity
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::Compacity(const Point* verts) const
+{
+	if(!verts)	return 0.0f;
+	float P = Perimeter(verts);
+	if(P==0.0f)	return 0.0f;
+	return (4.0f*PI*Area(verts)/(P*P));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle normal.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		normal	[out] the computed normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::Normal(const Point* verts, Point& normal)	const
+{
+	if(!verts)	return;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+	normal = ((p2-p1)^(p0-p1)).Normalize();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle denormalized normal.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		normal	[out] the computed normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal)	const
+{
+	if(!verts)	return;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+	normal = ((p2-p1)^(p0-p1));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle center.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		center	[out] the computed center
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::Center(const Point* verts, Point& center)	const
+{
+	if(!verts)	return;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+	center = (p0+p1+p2)*INV3;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the centered normal
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		normal	[out] the computed centered normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal)	const
+{
+	if(!verts)	return;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+	Point Center = (p0+p1+p2)*INV3;
+	normal = Center + ((p2-p1)^(p0-p1)).Normalize();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes a random point within the triangle.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		normal	[out] the computed centered normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::RandomPoint(const Point* verts, Point& random)	const
+{
+	if(!verts)	return;
+
+	// Random barycentric coords
+	float Alpha	= UnitRandomFloat();
+	float Beta	= UnitRandomFloat();
+	float Gamma	= UnitRandomFloat();
+	float OneOverTotal = 1.0f / (Alpha + Beta + Gamma);
+	Alpha	*= OneOverTotal;
+	Beta	*= OneOverTotal;
+	Gamma	*= OneOverTotal;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+	random = Alpha*p0 + Beta*p1 + Gamma*p2;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes backface culling.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		source	[in] source point (in local space) from which culling must be computed
+ *	\return		true if the triangle is visible from the source point
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::IsVisible(const Point* verts, const Point& source)	const
+{
+	// Checkings
+	if(!verts)	return false;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+
+	// Compute denormalized normal
+	Point Normal = (p2 - p1)^(p0 - p1);
+
+	// Backface culling
+	return (Normal | source) >= 0.0f;
+
+// Same as:
+//	Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
+//	return PL.Distance(source) > PL.d;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes backface culling.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		source	[in] source point (in local space) from which culling must be computed
+ *	\return		true if the triangle is visible from the source point
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source)	const
+{
+	// Checkings
+	if(!verts)	return false;
+
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+
+	// Compute base
+//	Point Base = (p0 + p1 + p2)*INV3;
+
+	// Compute denormalized normal
+	Point Normal = (p2 - p1)^(p0 - p1);
+
+	// Backface culling
+//	return (Normal | (source - Base)) >= 0.0f;
+	return (Normal | (source - p0)) >= 0.0f;
+
+// Same as: (but a bit faster)
+//	Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
+//	return PL.Distance(source)>0.0f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the occlusion potential of the triangle.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\param		source	[in] source point (in local space) from which occlusion potential must be computed
+ *	\return		the occlusion potential
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view)	const
+{
+	if(!verts)	return 0.0f;
+	// Occlusion potential: -(A * (N|V) / d^2)
+	// A = polygon area
+	// N = polygon normal
+	// V = view vector
+	// d = distance viewpoint-center of polygon
+
+	float A = Area(verts);
+	Point N;	Normal(verts, N);
+	Point C;	Center(verts, C);
+	float d = view.Distance(C);
+	return -(A*(N|view))/(d*d);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Replaces a vertex reference with another one.
+ *	\param		oldref	[in] the vertex reference to replace
+ *	\param		newref	[in] the new vertex reference
+ *	\return		true if success, else false if the input vertex reference doesn't belong to the triangle
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref)
+{
+			if(mVRef[0]==oldref)	{ mVRef[0] = newref; return true; }
+	else	if(mVRef[1]==oldref)	{ mVRef[1] = newref; return true; }
+	else	if(mVRef[2]==oldref)	{ mVRef[2] = newref; return true; }
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle.
+ *	\return		true if the triangle is degenerate
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::IsDegenerate()	const
+{
+	if(mVRef[0]==mVRef[1])	return true;
+	if(mVRef[1]==mVRef[2])	return true;
+	if(mVRef[2]==mVRef[0])	return true;
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks whether the input vertex reference belongs to the triangle or not.
+ *	\param		ref		[in] the vertex reference to look for
+ *	\return		true if the triangle contains the vertex reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::HasVertex(udword ref)	const
+{
+	if(mVRef[0]==ref)	return true;
+	if(mVRef[1]==ref)	return true;
+	if(mVRef[2]==ref)	return true;
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks whether the input vertex reference belongs to the triangle or not.
+ *	\param		ref		[in] the vertex reference to look for
+ *	\param		index	[out] the corresponding index in the triangle
+ *	\return		true if the triangle contains the vertex reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::HasVertex(udword ref, udword* index)	const
+{
+	if(mVRef[0]==ref)	{ *index = 0;	return true; }
+	if(mVRef[1]==ref)	{ *index = 1;	return true; }
+	if(mVRef[2]==ref)	{ *index = 2;	return true; }
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Finds an edge in a tri, given two vertex references.
+ *	\param		vref0	[in] the edge's first vertex reference
+ *	\param		vref1	[in] the edge's second vertex reference
+ *	\return		the edge number between 0 and 2, or 0xff if input refs are wrong.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1)	const
+{
+			if(mVRef[0]==vref0 && mVRef[1]==vref1)	return 0;
+	else	if(mVRef[0]==vref1 && mVRef[1]==vref0)	return 0;
+	else	if(mVRef[0]==vref0 && mVRef[2]==vref1)	return 1;
+	else	if(mVRef[0]==vref1 && mVRef[2]==vref0)	return 1;
+	else	if(mVRef[1]==vref0 && mVRef[2]==vref1)	return 2;
+	else	if(mVRef[1]==vref1 && mVRef[2]==vref0)	return 2;
+	return 0xff;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the last reference given the first two.
+ *	\param		vref0	[in] the first vertex reference
+ *	\param		vref1	[in] the second vertex reference
+ *	\return		the last reference, or INVALID_ID if input refs are wrong.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1)	const
+{
+			if(mVRef[0]==vref0 && mVRef[1]==vref1)	return mVRef[2];
+	else	if(mVRef[0]==vref1 && mVRef[1]==vref0)	return mVRef[2];
+	else	if(mVRef[0]==vref0 && mVRef[2]==vref1)	return mVRef[1];
+	else	if(mVRef[0]==vref1 && mVRef[2]==vref0)	return mVRef[1];
+	else	if(mVRef[1]==vref0 && mVRef[2]==vref1)	return mVRef[0];
+	else	if(mVRef[1]==vref1 && mVRef[2]==vref0)	return mVRef[0];
+	return INVALID_ID;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the three sorted vertex references according to an edge number.
+ *	edgenb = 0	=> edge 0-1, returns references 0, 1, 2
+ *	edgenb = 1	=> edge 0-2, returns references 0, 2, 1
+ *	edgenb = 2	=> edge 1-2, returns references 1, 2, 0
+ *
+ *	\param		edgenb	[in] the edge number, 0, 1 or 2
+ *	\param		vref0	[out] the returned first vertex reference
+ *	\param		vref1	[out] the returned second vertex reference
+ *	\param		vref2	[out] the returned third vertex reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const
+{
+	if(edgenb==0)
+	{
+		vref0 = mVRef[0];
+		vref1 = mVRef[1];
+		vref2 = mVRef[2];
+	}
+	else if(edgenb==1)
+	{
+		vref0 = mVRef[0];
+		vref1 = mVRef[2];
+		vref2 = mVRef[1];
+	}
+	else if(edgenb==2)
+	{
+		vref0 = mVRef[1];
+		vref1 = mVRef[2];
+		vref2 = mVRef[0];
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle's smallest edge length.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\return		the smallest edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::MinEdgeLength(const Point* verts)	const
+{
+	if(!verts)	return 0.0f;
+
+	float Min = MAX_FLOAT;
+	float Length01 = verts[0].Distance(verts[1]);
+	float Length02 = verts[0].Distance(verts[2]);
+	float Length12 = verts[1].Distance(verts[2]);
+	if(Length01 < Min)	Min = Length01;
+	if(Length02 < Min)	Min = Length02;
+	if(Length12 < Min)	Min = Length12;
+	return Min;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle's largest edge length.
+ *	\param		verts	[in] the list of indexed vertices
+ *	\return		the largest edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::MaxEdgeLength(const Point* verts)	const
+{
+	if(!verts)	return 0.0f;
+
+	float Max = MIN_FLOAT;
+	float Length01 = verts[0].Distance(verts[1]);
+	float Length02 = verts[0].Distance(verts[2]);
+	float Length12 = verts[1].Distance(verts[2]);
+	if(Length01 > Max)	Max = Length01;
+	if(Length02 > Max)	Max = Length02;
+	if(Length12 > Max)	Max = Length12;
+	return Max;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes a point on the triangle according to the stabbing information.
+ *	\param		verts		[in] the list of indexed vertices
+ *	\param		u,v			[in] point's barycentric coordinates
+ *	\param		pt			[out] point on triangle
+ *	\param		nearvtx		[out] index of nearest vertex
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx)	const
+{
+	// Checkings
+	if(!verts)	return;
+
+	// Get face in local or global space
+	const Point& p0 = verts[mVRef[0]];
+	const Point& p1 = verts[mVRef[1]];
+	const Point& p2 = verts[mVRef[2]];
+
+	// Compute point coordinates
+	pt = (1.0f - u - v)*p0 + u*p1 + v*p2;
+
+	// Compute nearest vertex if needed
+	if(nearvtx)
+	{
+		// Compute distance vector
+		Point d(p0.SquareDistance(pt),	// Distance^2 from vertex 0 to point on the face
+				p1.SquareDistance(pt),	// Distance^2 from vertex 1 to point on the face
+				p2.SquareDistance(pt));	// Distance^2 from vertex 2 to point on the face
+
+		// Get smallest distance
+		*nearvtx = mVRef[d.SmallestAxis()];
+	}
+}
+
+	//**************************************
+	// Angle between two vectors (in radians)
+	// we use this formula
+	// uv = |u||v| cos(u,v)
+	// u  ^ v  = w
+	// |w| = |u||v| |sin(u,v)|
+	//**************************************
+	float Angle(const Point& u, const Point& v)
+	{
+		float NormU = u.Magnitude();	// |u|
+		float NormV = v.Magnitude();	// |v|
+		float Product = NormU*NormV;	// |u||v|
+		if(Product==0.0f)	return 0.0f;
+		float OneOverProduct = 1.0f / Product;
+
+		// Cosinus
+		float Cosinus = (u|v) * OneOverProduct;
+
+		// Sinus
+		Point w = u^v;
+		float NormW = w.Magnitude();
+
+		float AbsSinus = NormW * OneOverProduct;
+
+		// Remove degeneracy
+		if(AbsSinus > 1.0f) AbsSinus = 1.0f;
+		if(AbsSinus < -1.0f) AbsSinus = -1.0f;
+
+		if(Cosinus>=0.0f)	return asinf(AbsSinus);
+		else				return (PI-asinf(AbsSinus));
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the angle between two triangles.
+ *	\param		tri		[in] the other triangle
+ *	\param		verts	[in] the list of indexed vertices
+ *	\return		the angle in radians
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts)	const
+{
+	// Checkings
+	if(!verts)	return 0.0f;
+
+	// Compute face normals
+	Point n0, n1;
+	Normal(verts, n0);
+	tri.Normal(verts, n1);
+
+	// Compute angle
+	float dp = n0|n1;
+	if(dp>1.0f)		return 0.0f;
+	if(dp<-1.0f)	return PI;
+	return acosf(dp);
+
+//	return ::Angle(n0,n1);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks a triangle is the same as another one.
+ *	\param		tri		[in] the other triangle
+ *	\return		true if same triangle
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool IndexedTriangle::Equal(const IndexedTriangle& tri) const
+{
+	// Test all vertex references
+	return (HasVertex(tri.mVRef[0]) && 
+			HasVertex(tri.mVRef[1]) &&
+			HasVertex(tri.mVRef[2]));
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceIndexedTriangle.h	(revision 216)
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a handy indexed triangle class.
+ *	\file		IceIndexedTriangle.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 17, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEINDEXEDTRIANGLE_H__
+#define __ICEINDEXEDTRIANGLE_H__
+
+	// Forward declarations
+#ifdef _MSC_VER
+	enum CubeIndex;
+#else
+	typedef int CubeIndex;
+#endif
+
+	// An indexed triangle class.
+	class ICEMATHS_API IndexedTriangle
+	{
+		public:
+		//! Constructor
+		inline_					IndexedTriangle()									{}
+		//! Constructor
+		inline_					IndexedTriangle(udword r0, udword r1, udword r2)	{ mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; }
+		//! Copy constructor
+		inline_					IndexedTriangle(const IndexedTriangle& triangle)
+								{
+									mVRef[0] = triangle.mVRef[0];
+									mVRef[1] = triangle.mVRef[1];
+									mVRef[2] = triangle.mVRef[2];
+								}
+		//! Destructor
+		inline_					~IndexedTriangle()									{}
+		//! Vertex-references
+				udword			mVRef[3];
+
+		// Methods
+				void			Flip();
+				float			Area(const Point* verts)											const;
+				float			Perimeter(const Point* verts)										const;
+				float			Compacity(const Point* verts)										const;
+				void			Normal(const Point* verts, Point& normal)							const;
+				void			DenormalizedNormal(const Point* verts, Point& normal)				const;
+				void			Center(const Point* verts, Point& center)							const;
+				void			CenteredNormal(const Point* verts, Point& normal)					const;
+				void			RandomPoint(const Point* verts, Point& random)						const;
+				bool			IsVisible(const Point* verts, const Point& source)					const;
+				bool			BackfaceCulling(const Point* verts, const Point& source)			const;
+				float			ComputeOcclusionPotential(const Point* verts, const Point& view)	const;
+				bool			ReplaceVertex(udword oldref, udword newref);
+				bool			IsDegenerate()														const;
+				bool			HasVertex(udword ref)												const;
+				bool			HasVertex(udword ref, udword* index)								const;
+				ubyte			FindEdge(udword vref0, udword vref1)								const;
+				udword			OppositeVertex(udword vref0, udword vref1)							const;
+		inline_	udword			OppositeVertex(ubyte edgenb)										const	{ return mVRef[2-edgenb];	}
+				void			GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2)	const;
+				float			MinEdgeLength(const Point* verts)									const;
+				float			MaxEdgeLength(const Point* verts)									const;
+				void			ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx=null)	const;
+				float			Angle(const IndexedTriangle& tri, const Point* verts)				const;
+		inline_	Plane			PlaneEquation(const Point* verts)									const	{ return Plane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);	}
+				bool			Equal(const IndexedTriangle& tri)									const;
+				CubeIndex		ComputeCubeIndex(const Point* verts)								const;
+	};
+
+#endif // __ICEINDEXEDTRIANGLE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceLSS.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceLSS.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceLSS.h	(revision 216)
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for line-swept spheres.
+ *	\file		IceLSS.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICELSS_H__
+#define __ICELSS_H__
+
+	class ICEMATHS_API LSS : public Segment
+	{
+		public:
+		//! Constructor
+		inline_			LSS()																	{}
+		//! Constructor
+		inline_			LSS(const Segment& seg, float radius) : Segment(seg), mRadius(radius)	{}
+		//! Destructor
+		inline_			~LSS()																	{}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes an OBB surrounding the LSS.
+		 *	\param		box		[out] the OBB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				void	ComputeOBB(OBB& box);
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a point is contained within the LSS.
+		 *	\param		pt	[in] the point to test
+		 *	\return		true if inside the LSS
+		 *	\warning	point and LSS must be in same space
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool	Contains(const Point& pt)	const	{ return SquareDistance(pt) <= mRadius*mRadius;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a sphere is contained within the LSS.
+		 *	\param		sphere	[in] the sphere to test
+		 *	\return		true if inside the LSS
+		 *	\warning	sphere and LSS must be in same space
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool	Contains(const Sphere& sphere)
+						{
+							float d = mRadius - sphere.mRadius;
+							if(d>=0.0f)	return SquareDistance(sphere.mCenter) <= d*d;
+							else		return false;
+						}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if an LSS is contained within the LSS.
+		 *	\param		lss		[in] the LSS to test
+		 *	\return		true if inside the LSS
+		 *	\warning	both LSS must be in same space
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	bool	Contains(const LSS& lss)
+						{
+							// We check the LSS contains the two spheres at the start and end of the sweep
+							return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius));
+						}
+
+				float	mRadius;	//!< Sphere radius
+	};
+
+#endif // __ICELSS_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix3x3.cpp	(revision 216)
@@ -0,0 +1,48 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for 3x3 matrices.
+ *	\file		IceMatrix3x3.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	3x3 matrix.
+ *	DirectX-compliant, ie row-column order, ie m[Row][Col].
+ *	Same as:
+ *	m11  m12  m13  first row.
+ *	m21  m22  m23  second row.
+ *	m31  m32  m33  third row.
+ *	Stored in memory as m11 m12 m13 m21...
+ *
+ *	Multiplication rules:
+ *
+ *	[x'y'z'] = [xyz][M]
+ *
+ *	x' = x*m11 + y*m21 + z*m31
+ *	y' = x*m12 + y*m22 + z*m32
+ *	z' = x*m13 + y*m23 + z*m33
+ *
+ *	\class		Matrix3x3
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+// Cast operator
+Matrix3x3::operator Matrix4x4() const
+{
+	return Matrix4x4(
+	m[0][0],	m[0][1],	m[0][2],	0.0f,
+	m[1][0],	m[1][1],	m[1][2],	0.0f,
+	m[2][0],	m[2][1],	m[2][2],	0.0f,
+	0.0f,		0.0f,		0.0f,		1.0f);
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix3x3.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix3x3.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix3x3.h	(revision 216)
@@ -0,0 +1,496 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for 3x3 matrices.
+ *	\file		IceMatrix3x3.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEMATRIX3X3_H__
+#define __ICEMATRIX3X3_H__
+
+	// Forward declarations
+	class Quat;
+
+	#define	MATRIX3X3_EPSILON		(1.0e-7f)
+
+	class ICEMATHS_API Matrix3x3
+	{
+		public:
+		//! Empty constructor
+		inline_					Matrix3x3()									{}
+		//! Constructor from 9 values
+		inline_					Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
+								{
+									m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;
+									m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;
+									m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;
+								}
+		//! Copy constructor
+		inline_					Matrix3x3(const Matrix3x3& mat)				{ CopyMemory(m, &mat.m, 9*sizeof(float));	}
+		//! Destructor
+		inline_					~Matrix3x3()								{}
+
+		//! Assign values
+		inline_	void			Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
+								{
+									m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;
+									m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;
+									m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;
+								}
+
+		//! Sets the scale from a Point. The point is put on the diagonal.
+		inline_	void			SetScale(const Point& p)					{ m[0][0] = p.x;	m[1][1] = p.y;	m[2][2] = p.z;	}
+
+		//! Sets the scale from floats. Values are put on the diagonal.
+		inline_	void			SetScale(float sx, float sy, float sz)		{ m[0][0] = sx;		m[1][1] = sy;	m[2][2] = sz;	}
+
+		//! Scales from a Point. Each row is multiplied by a component.
+		inline_	void			Scale(const Point& p)
+								{
+									m[0][0] *= p.x;	m[0][1] *= p.x;	m[0][2] *= p.x;
+									m[1][0] *= p.y;	m[1][1] *= p.y;	m[1][2] *= p.y;
+									m[2][0] *= p.z;	m[2][1] *= p.z;	m[2][2] *= p.z;
+								}
+
+		//! Scales from floats. Each row is multiplied by a value.
+		inline_	void			Scale(float sx, float sy, float sz)
+								{
+									m[0][0] *= sx;	m[0][1] *= sx;	m[0][2] *= sx;
+									m[1][0] *= sy;	m[1][1] *= sy;	m[1][2] *= sy;
+									m[2][0] *= sz;	m[2][1] *= sz;	m[2][2] *= sz;
+								}
+
+		//! Copy from a Matrix3x3
+		inline_	void			Copy(const Matrix3x3& source)				{ CopyMemory(m, source.m, 9*sizeof(float));			}
+
+		// Row-column access
+		//! Returns a row.
+		inline_	void			GetRow(const udword r, Point& p)	const	{ p.x = m[r][0];	p.y = m[r][1];	p.z = m[r][2];	}
+		//! Returns a row.
+		inline_	const Point&	GetRow(const udword r)				const	{ return *(const Point*)&m[r][0];	}
+		//! Returns a row.
+		inline_	Point&			GetRow(const udword r)						{ return *(Point*)&m[r][0];			}
+		//! Sets a row.
+		inline_	void			SetRow(const udword r, const Point& p)		{ m[r][0] = p.x;	m[r][1] = p.y;	m[r][2] = p.z;	}
+		//! Returns a column.
+		inline_	void			GetCol(const udword c, Point& p)	const	{ p.x = m[0][c];	p.y = m[1][c];	p.z = m[2][c];	}
+		//! Sets a column.
+		inline_	void			SetCol(const udword c, const Point& p)		{ m[0][c] = p.x;	m[1][c] = p.y;	m[2][c] = p.z;	}
+
+		//! Computes the trace. The trace is the sum of the 3 diagonal components.
+		inline_	float			Trace()					const				{ return m[0][0] + m[1][1] + m[2][2];				}
+		//! Clears the matrix.
+		inline_	void			Zero()										{ ZeroMemory(&m, sizeof(m));						}
+		//! Sets the identity matrix.
+		inline_	void			Identity()									{ Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; 		}
+		//! Checks for identity
+		inline_	bool			IsIdentity()			const
+								{
+									if(IR(m[0][0])!=IEEE_1_0)	return false;
+									if(IR(m[0][1])!=0)			return false;
+									if(IR(m[0][2])!=0)			return false;
+
+									if(IR(m[1][0])!=0)			return false;
+									if(IR(m[1][1])!=IEEE_1_0)	return false;
+									if(IR(m[1][2])!=0)			return false;
+
+									if(IR(m[2][0])!=0)			return false;
+									if(IR(m[2][1])!=0)			return false;
+									if(IR(m[2][2])!=IEEE_1_0)	return false;
+
+									return true;
+								}
+
+		//! Checks matrix validity
+		inline_	BOOL			IsValid()				const
+								{
+									for(udword j=0;j<3;j++)
+									{
+										for(udword i=0;i<3;i++)
+										{
+											if(!IsValidFloat(m[j][i]))	return FALSE;
+										}
+									}
+									return TRUE;
+								}
+
+		//! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix)
+		//!	[  0.0  -a.z   a.y ]
+		//!	[  a.z   0.0  -a.x ]
+		//!	[ -a.y   a.x   0.0 ]
+		//! This is also called a "cross matrix" since for any vectors A and B,
+		//! A^B = Skew(A) * B = - B * Skew(A);
+		inline_	void			SkewSymmetric(const Point& a)
+								{
+									m[0][0] = 0.0f;
+									m[0][1] = -a.z;
+									m[0][2] = a.y;
+
+									m[1][0] = a.z;
+									m[1][1] = 0.0f;
+									m[1][2] = -a.x;
+
+									m[2][0] = -a.y;
+									m[2][1] = a.x;
+									m[2][2] = 0.0f;
+								}
+
+		//! Negates the matrix
+		inline_	void			Neg()
+								{
+									m[0][0] = -m[0][0];	m[0][1] = -m[0][1];	m[0][2] = -m[0][2];
+									m[1][0] = -m[1][0];	m[1][1] = -m[1][1];	m[1][2] = -m[1][2];
+									m[2][0] = -m[2][0];	m[2][1] = -m[2][1];	m[2][2] = -m[2][2];
+								}
+
+		//! Neg from another matrix
+		inline_	void			Neg(const Matrix3x3& mat)
+								{
+									m[0][0] = -mat.m[0][0];	m[0][1] = -mat.m[0][1];	m[0][2] = -mat.m[0][2];
+									m[1][0] = -mat.m[1][0];	m[1][1] = -mat.m[1][1];	m[1][2] = -mat.m[1][2];
+									m[2][0] = -mat.m[2][0];	m[2][1] = -mat.m[2][1];	m[2][2] = -mat.m[2][2];
+								}
+
+		//! Add another matrix
+		inline_	void			Add(const Matrix3x3& mat)
+								{
+									m[0][0] += mat.m[0][0];	m[0][1] += mat.m[0][1];	m[0][2] += mat.m[0][2];
+									m[1][0] += mat.m[1][0];	m[1][1] += mat.m[1][1];	m[1][2] += mat.m[1][2];
+									m[2][0] += mat.m[2][0];	m[2][1] += mat.m[2][1];	m[2][2] += mat.m[2][2];
+								}
+
+		//! Sub another matrix
+		inline_	void			Sub(const Matrix3x3& mat)
+								{
+									m[0][0] -= mat.m[0][0];	m[0][1]	-= mat.m[0][1];	m[0][2] -= mat.m[0][2];
+									m[1][0] -= mat.m[1][0];	m[1][1] -= mat.m[1][1];	m[1][2] -= mat.m[1][2];
+									m[2][0] -= mat.m[2][0];	m[2][1] -= mat.m[2][1];	m[2][2] -= mat.m[2][2];
+								}
+		//! Mac
+		inline_	void			Mac(const Matrix3x3& a, const Matrix3x3& b, float s)
+								{
+									m[0][0] = a.m[0][0] + b.m[0][0] * s;
+									m[0][1] = a.m[0][1] + b.m[0][1] * s;
+									m[0][2] = a.m[0][2] + b.m[0][2] * s;
+
+									m[1][0] = a.m[1][0] + b.m[1][0] * s;
+									m[1][1] = a.m[1][1] + b.m[1][1] * s;
+									m[1][2] = a.m[1][2] + b.m[1][2] * s;
+
+									m[2][0] = a.m[2][0] + b.m[2][0] * s;
+									m[2][1] = a.m[2][1] + b.m[2][1] * s;
+									m[2][2] = a.m[2][2] + b.m[2][2] * s;
+								}
+		//! Mac
+		inline_	void			Mac(const Matrix3x3& a, float s)
+								{
+									m[0][0] += a.m[0][0] * s;	m[0][1] += a.m[0][1] * s;	m[0][2] += a.m[0][2] * s;
+									m[1][0] += a.m[1][0] * s;	m[1][1] += a.m[1][1] * s;	m[1][2] += a.m[1][2] * s;
+									m[2][0] += a.m[2][0] * s;	m[2][1] += a.m[2][1] * s;	m[2][2] += a.m[2][2] * s;
+								}
+
+		//! this = A * s
+		inline_	void			Mult(const Matrix3x3& a, float s)
+								{
+									m[0][0] = a.m[0][0] * s;	m[0][1] = a.m[0][1] * s;	m[0][2] = a.m[0][2] * s;
+									m[1][0] = a.m[1][0] * s;	m[1][1] = a.m[1][1] * s;	m[1][2] = a.m[1][2] * s;
+									m[2][0] = a.m[2][0] * s;	m[2][1] = a.m[2][1] * s;	m[2][2] = a.m[2][2] * s;
+								}
+
+		inline_	void			Add(const Matrix3x3& a, const Matrix3x3& b)
+								{
+									m[0][0] = a.m[0][0] + b.m[0][0];	m[0][1] = a.m[0][1] + b.m[0][1];	m[0][2] = a.m[0][2] + b.m[0][2];
+									m[1][0] = a.m[1][0] + b.m[1][0];	m[1][1] = a.m[1][1] + b.m[1][1];	m[1][2] = a.m[1][2] + b.m[1][2];
+									m[2][0] = a.m[2][0] + b.m[2][0];	m[2][1] = a.m[2][1] + b.m[2][1];	m[2][2] = a.m[2][2] + b.m[2][2];
+								}
+
+		inline_	void			Sub(const Matrix3x3& a, const Matrix3x3& b)
+								{
+									m[0][0] = a.m[0][0] - b.m[0][0];	m[0][1] = a.m[0][1] - b.m[0][1];	m[0][2] = a.m[0][2] - b.m[0][2];
+									m[1][0] = a.m[1][0] - b.m[1][0];	m[1][1] = a.m[1][1] - b.m[1][1];	m[1][2] = a.m[1][2] - b.m[1][2];
+									m[2][0] = a.m[2][0] - b.m[2][0];	m[2][1] = a.m[2][1] - b.m[2][1];	m[2][2] = a.m[2][2] - b.m[2][2];
+								}
+
+		//! this = a * b
+		inline_	void			Mult(const Matrix3x3& a, const Matrix3x3& b)
+								{
+									m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0];
+									m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1];
+									m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2];
+									m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0];
+									m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1];
+									m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2];
+									m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0];
+									m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1];
+									m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2];
+								}
+
+		//! this = transpose(a) * b
+		inline_	void			MultAtB(const Matrix3x3& a, const Matrix3x3& b)
+								{
+									m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0];
+									m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1];
+									m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2];
+									m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0];
+									m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1];
+									m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2];
+									m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0];
+									m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1];
+									m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2];
+								}
+
+		//! this = a * transpose(b)
+		inline_	void			MultABt(const Matrix3x3& a, const Matrix3x3& b)
+								{
+									m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2];
+									m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2];
+									m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2];
+									m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2];
+									m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2];
+									m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2];
+									m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2];
+									m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2];
+									m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2];
+								}
+
+		//! Makes a rotation matrix mapping vector "from" to vector "to".
+				Matrix3x3&		FromTo(const Point& from, const Point& to);
+
+		//! Set a rotation matrix around the X axis.
+		//!		 1		0		0
+		//!	RX = 0		cx		sx
+		//!		 0		-sx		cx
+				void			RotX(float angle);
+		//! Set a rotation matrix around the Y axis.
+		//!		 cy		0		-sy
+		//!	RY = 0		1		0
+		//!		 sy		0		cy
+				void			RotY(float angle);
+		//! Set a rotation matrix around the Z axis.
+		//!		 cz		sz		0
+		//!	RZ = -sz	cz		0
+		//!		 0		0		1
+				void			RotZ(float angle);
+		//!			cy		sx.sy		-sy.cx
+		//!	RY.RX	0		cx			sx
+		//!			sy		-sx.cy		cx.cy
+				void			RotYX(float y, float x);
+
+		//! Make a rotation matrix about an arbitrary axis
+				Matrix3x3&		Rot(float angle, const Point& axis);
+
+		//! Transpose the matrix.
+				void			Transpose()
+								{
+									IR(m[1][0]) ^= IR(m[0][1]);	IR(m[0][1]) ^= IR(m[1][0]);	IR(m[1][0]) ^= IR(m[0][1]);
+									IR(m[2][0]) ^= IR(m[0][2]);	IR(m[0][2]) ^= IR(m[2][0]);	IR(m[2][0]) ^= IR(m[0][2]);
+									IR(m[2][1]) ^= IR(m[1][2]);	IR(m[1][2]) ^= IR(m[2][1]);	IR(m[2][1]) ^= IR(m[1][2]);
+								}
+
+		//! this = Transpose(a)
+				void			Transpose(const Matrix3x3& a)
+								{
+									m[0][0] = a.m[0][0];	m[0][1] = a.m[1][0];	m[0][2] = a.m[2][0];
+									m[1][0] = a.m[0][1];	m[1][1] = a.m[1][1];	m[1][2] = a.m[2][1];
+									m[2][0] = a.m[0][2];	m[2][1] = a.m[1][2];	m[2][2] = a.m[2][2];
+								}
+
+		//! Compute the determinant of the matrix. We use the rule of Sarrus.
+				float			Determinant()					const
+								{
+									return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1])
+										-  (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]);
+								}
+/*
+		//! Compute a cofactor. Used for matrix inversion.
+				float			CoFactor(ubyte row, ubyte column)	const
+				{
+					static sdword gIndex[3+2] = { 0, 1, 2, 0, 1 };
+					return	(m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]);
+				}
+*/
+		//! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted.
+				Matrix3x3&		Invert()
+								{
+									float Det = Determinant();	// Must be !=0
+									float OneOverDet = 1.0f / Det;
+
+									Matrix3x3 Temp;
+									Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet;
+									Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet;
+									Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet;
+									Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet;
+									Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet;
+									Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet;
+									Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet;
+									Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet;
+									Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet;
+
+									*this = Temp;
+
+									return	*this;
+								}
+
+				Matrix3x3&		Normalize();
+
+		//! this = exp(a)
+				Matrix3x3&		Exp(const Matrix3x3& a);
+
+void FromQuat(const Quat &q);
+void FromQuatL2(const Quat &q, float l2);
+
+		// Arithmetic operators
+		//! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3;
+		inline_	Matrix3x3		operator+(const Matrix3x3& mat)	const
+								{
+									return Matrix3x3(
+									m[0][0] + mat.m[0][0],	m[0][1] + mat.m[0][1],	m[0][2] + mat.m[0][2],
+									m[1][0] + mat.m[1][0],	m[1][1] + mat.m[1][1],	m[1][2] + mat.m[1][2],
+									m[2][0] + mat.m[2][0],	m[2][1] + mat.m[2][1],	m[2][2] + mat.m[2][2]);
+								}
+
+		//! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3;
+		inline_	Matrix3x3		operator-(const Matrix3x3& mat)	const
+								{
+									return Matrix3x3(
+									m[0][0] - mat.m[0][0],	m[0][1] - mat.m[0][1],	m[0][2] - mat.m[0][2],
+									m[1][0] - mat.m[1][0],	m[1][1] - mat.m[1][1],	m[1][2] - mat.m[1][2],
+									m[2][0] - mat.m[2][0],	m[2][1] - mat.m[2][1],	m[2][2] - mat.m[2][2]);
+								}
+
+		//! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3;
+		inline_	Matrix3x3		operator*(const Matrix3x3& mat)	const
+								{
+									return Matrix3x3(
+									m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0],
+									m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1],
+									m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2],
+
+									m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0],
+									m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1],
+									m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2],
+
+									m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0],
+									m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1],
+									m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]);
+								}
+
+		//! Operator for Point Mul = Matrix3x3 * Point;
+		inline_	Point			operator*(const Point& v)		const		{ return Point(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); }
+
+		//! Operator for Matrix3x3 Mul = Matrix3x3 * float;
+		inline_	Matrix3x3		operator*(float s)				const
+								{
+									return Matrix3x3(
+									m[0][0]*s,	m[0][1]*s,	m[0][2]*s,
+									m[1][0]*s,	m[1][1]*s,	m[1][2]*s,
+									m[2][0]*s,	m[2][1]*s,	m[2][2]*s);
+								}
+
+		//! Operator for Matrix3x3 Mul = float * Matrix3x3;
+		inline_	friend Matrix3x3 operator*(float s, const Matrix3x3& mat)
+								{
+									return Matrix3x3(
+									s*mat.m[0][0],	s*mat.m[0][1],	s*mat.m[0][2],
+									s*mat.m[1][0],	s*mat.m[1][1],	s*mat.m[1][2],
+									s*mat.m[2][0],	s*mat.m[2][1],	s*mat.m[2][2]);
+								}
+
+		//! Operator for Matrix3x3 Div = Matrix3x3 / float;
+		inline_	Matrix3x3		operator/(float s)				const
+								{
+									if (s)	s = 1.0f / s;
+									return Matrix3x3(
+									m[0][0]*s,	m[0][1]*s,	m[0][2]*s,
+									m[1][0]*s,	m[1][1]*s,	m[1][2]*s,
+									m[2][0]*s,	m[2][1]*s,	m[2][2]*s);
+								}
+
+		//! Operator for Matrix3x3 Div = float / Matrix3x3;
+		inline_	friend Matrix3x3 operator/(float s, const Matrix3x3& mat)
+								{
+									return Matrix3x3(
+									s/mat.m[0][0],	s/mat.m[0][1],	s/mat.m[0][2],
+									s/mat.m[1][0],	s/mat.m[1][1],	s/mat.m[1][2],
+									s/mat.m[2][0],	s/mat.m[2][1],	s/mat.m[2][2]);
+								}
+
+		//! Operator for Matrix3x3 += Matrix3x3
+		inline_	Matrix3x3&		operator+=(const Matrix3x3& mat)
+								{
+									m[0][0] += mat.m[0][0];		m[0][1] += mat.m[0][1];		m[0][2] += mat.m[0][2];
+									m[1][0] += mat.m[1][0];		m[1][1] += mat.m[1][1];		m[1][2] += mat.m[1][2];
+									m[2][0] += mat.m[2][0];		m[2][1] += mat.m[2][1];		m[2][2] += mat.m[2][2];
+									return	*this;
+								}
+
+		//! Operator for Matrix3x3 -= Matrix3x3
+		inline_	Matrix3x3&		operator-=(const Matrix3x3& mat)
+								{
+									m[0][0] -= mat.m[0][0];		m[0][1] -= mat.m[0][1];		m[0][2] -= mat.m[0][2];
+									m[1][0] -= mat.m[1][0];		m[1][1] -= mat.m[1][1];		m[1][2] -= mat.m[1][2];
+									m[2][0] -= mat.m[2][0];		m[2][1] -= mat.m[2][1];		m[2][2] -= mat.m[2][2];
+									return	*this;
+								}
+
+		//! Operator for Matrix3x3 *= Matrix3x3
+		inline_	Matrix3x3&		operator*=(const Matrix3x3& mat)
+								{
+									Point TempRow;
+
+									GetRow(0, TempRow);
+									m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0];
+									m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1];
+									m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2];
+
+									GetRow(1, TempRow);
+									m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0];
+									m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1];
+									m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2];
+
+									GetRow(2, TempRow);
+									m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0];
+									m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1];
+									m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2];
+									return	*this;
+								}
+
+		//! Operator for Matrix3x3 *= float
+		inline_	Matrix3x3&		operator*=(float s)
+								{
+									m[0][0] *= s;	m[0][1] *= s;	m[0][2] *= s;
+									m[1][0] *= s;	m[1][1] *= s;	m[1][2] *= s;
+									m[2][0] *= s;	m[2][1] *= s;	m[2][2] *= s;
+									return	*this;
+								}
+
+		//! Operator for Matrix3x3 /= float
+		inline_	Matrix3x3&		operator/=(float s)
+								{
+									if (s)	s = 1.0f / s;
+									m[0][0] *= s;	m[0][1] *= s;	m[0][2] *= s;
+									m[1][0] *= s;	m[1][1] *= s;	m[1][2] *= s;
+									m[2][0] *= s;	m[2][1] *= s;	m[2][2] *= s;
+									return	*this;
+								}
+
+		// Cast operators
+		//! Cast a Matrix3x3 to a Matrix4x4.
+								operator Matrix4x4()	const;
+		//! Cast a Matrix3x3 to a Quat.
+								operator Quat()			const;
+
+		inline_	const Point&	operator[](int row)		const	{ return *(const Point*)&m[row][0];	}
+		inline_	Point&			operator[](int row)				{ return *(Point*)&m[row][0];		}
+
+		public:
+
+				float			m[3][3];
+	};
+
+#endif // __ICEMATRIX3X3_H__
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix4x4.cpp	(revision 216)
@@ -0,0 +1,135 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for 4x4 matrices.
+ *	\file		IceMatrix4x4.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	4x4 matrix.
+ *	DirectX-compliant, ie row-column order, ie m[Row][Col].
+ *	Same as:
+ *	m11  m12  m13  m14	first row.
+ *	m21  m22  m23  m24	second row.
+ *	m31  m32  m33  m34	third row.
+ *	m41  m42  m43  m44	fourth row.
+ *	Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1).
+ *	Stored in memory as m11 m12 m13 m14 m21...
+ *
+ *	Multiplication rules:
+ *
+ *	[x'y'z'1] = [xyz1][M]
+ *
+ *	x' = x*m11 + y*m21 + z*m31 + m41
+ *	y' = x*m12 + y*m22 + z*m32 + m42
+ *	z' = x*m13 + y*m23 + z*m33 + m43
+ *	1' =     0 +     0 +     0 + m44
+ *
+ *	\class		Matrix4x4
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Inverts a PR matrix. (which only contains a rotation and a translation)
+ *	This is faster and less subject to FPU errors than the generic inversion code.
+ *
+ *	\relates	Matrix4x4
+ *	\fn			InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
+ *	\param		dest	[out] destination matrix
+ *	\param		src		[in] source matrix
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src)
+{
+	dest.m[0][0] = src.m[0][0];
+	dest.m[1][0] = src.m[0][1];
+	dest.m[2][0] = src.m[0][2];
+	dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]);
+
+	dest.m[0][1] = src.m[1][0];
+	dest.m[1][1] = src.m[1][1];
+	dest.m[2][1] = src.m[1][2];
+	dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]);
+
+	dest.m[0][2] = src.m[2][0];
+	dest.m[1][2] = src.m[2][1];
+	dest.m[2][2] = src.m[2][2];
+	dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]);
+
+	dest.m[0][3] = 0.0f;
+	dest.m[1][3] = 0.0f;
+	dest.m[2][3] = 0.0f;
+	dest.m[3][3] = 1.0f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Compute the cofactor of the Matrix at a specified location
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Matrix4x4::CoFactor(udword row, udword col) const
+{
+	return	 (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] +
+				m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] +
+				m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3])
+			-  (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] +
+				m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] +
+				m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Compute the determinant of the Matrix
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Matrix4x4::Determinant() const
+{
+	return	m[0][0] * CoFactor(0, 0) +
+			m[0][1] * CoFactor(0, 1) +
+			m[0][2] * CoFactor(0, 2) +
+			m[0][3] * CoFactor(0, 3);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Compute the inverse of the matrix
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Matrix4x4& Matrix4x4::Invert()
+{
+	float Det = Determinant();
+	Matrix4x4 Temp;
+
+	if(fabsf(Det) < MATRIX4X4_EPSILON)
+		return	*this;		// The matrix is not invertible! Singular case!
+
+	float IDet = 1.0f / Det;
+
+	Temp.m[0][0] = CoFactor(0,0) * IDet;
+	Temp.m[1][0] = CoFactor(0,1) * IDet;
+	Temp.m[2][0] = CoFactor(0,2) * IDet;
+	Temp.m[3][0] = CoFactor(0,3) * IDet;
+	Temp.m[0][1] = CoFactor(1,0) * IDet;
+	Temp.m[1][1] = CoFactor(1,1) * IDet;
+	Temp.m[2][1] = CoFactor(1,2) * IDet;
+	Temp.m[3][1] = CoFactor(1,3) * IDet;
+	Temp.m[0][2] = CoFactor(2,0) * IDet;
+	Temp.m[1][2] = CoFactor(2,1) * IDet;
+	Temp.m[2][2] = CoFactor(2,2) * IDet;
+	Temp.m[3][2] = CoFactor(2,3) * IDet;
+	Temp.m[0][3] = CoFactor(3,0) * IDet;
+	Temp.m[1][3] = CoFactor(3,1) * IDet;
+	Temp.m[2][3] = CoFactor(3,2) * IDet;
+	Temp.m[3][3] = CoFactor(3,3) * IDet;
+
+	*this = Temp;
+
+	return	*this;
+}
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix4x4.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix4x4.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceMatrix4x4.h	(revision 216)
@@ -0,0 +1,455 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for 4x4 matrices.
+ *	\file		IceMatrix4x4.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEMATRIX4X4_H__
+#define __ICEMATRIX4X4_H__
+
+	// Forward declarations
+	class PRS;
+	class PR;
+
+	#define	MATRIX4X4_EPSILON		(1.0e-7f)
+
+	class ICEMATHS_API Matrix4x4
+	{
+//				void	LUBackwardSubstitution( sdword *indx, float* b );
+//				void	LUDecomposition( sdword* indx, float* d );
+
+		public:
+		//! Empty constructor.
+		inline_						Matrix4x4()									{}
+		//! Constructor from 16 values
+		inline_						Matrix4x4(	float m00, float m01, float m02, float m03,
+												float m10, float m11, float m12, float m13,
+												float m20, float m21, float m22, float m23,
+												float m30, float m31, float m32, float m33)
+									{
+										m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;	m[0][3] = m03;
+										m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;	m[1][3] = m13;
+										m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;	m[2][3] = m23;
+										m[3][0] = m30;	m[3][1] = m31;	m[3][2] = m32;	m[3][3] = m33;
+									}
+		//! Copy constructor
+		inline_						Matrix4x4(const Matrix4x4& mat)				{ CopyMemory(m, &mat.m, 16*sizeof(float));	}
+		//! Destructor.
+		inline_						~Matrix4x4()								{}
+
+		//! Assign values (rotation only)
+		inline_	Matrix4x4&			Set(	float m00, float m01, float m02,
+											float m10, float m11, float m12,
+											float m20, float m21, float m22)
+									{
+										m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;
+										m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;
+										m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;
+										return *this;
+									}
+		//! Assign values
+		inline_	Matrix4x4&			Set(	float m00, float m01, float m02, float m03,
+											float m10, float m11, float m12, float m13,
+											float m20, float m21, float m22, float m23,
+											float m30, float m31, float m32, float m33)
+									{
+										m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;	m[0][3] = m03;
+										m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;	m[1][3] = m13;
+										m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;	m[2][3] = m23;
+										m[3][0] = m30;	m[3][1] = m31;	m[3][2] = m32;	m[3][3] = m33;
+										return *this;
+									}
+
+		//! Copy from a Matrix4x4
+		inline_	void				Copy(const Matrix4x4& source)				{ CopyMemory(m, source.m, 16*sizeof(float));	}
+
+		// Row-column access
+		//! Returns a row.
+		inline_	void				GetRow(const udword r, HPoint& p)	const	{ p.x=m[r][0];	p.y=m[r][1];	p.z=m[r][2];	p.w=m[r][3];		}
+		//! Returns a row.
+		inline_	void				GetRow(const udword r, Point& p)	const	{ p.x=m[r][0];	p.y=m[r][1];	p.z=m[r][2];						}
+		//! Returns a row.
+		inline_	const HPoint&		GetRow(const udword r)				const	{ return *(const HPoint*)&m[r][0];									}
+		//! Returns a row.
+		inline_	HPoint&				GetRow(const udword r)						{ return *(HPoint*)&m[r][0];										}
+		//! Sets a row.
+		inline_	void				SetRow(const udword r, const HPoint& p)		{ m[r][0]=p.x;	m[r][1]=p.y;	m[r][2]=p.z;	m[r][3]=p.w;		}
+		//! Sets a row.
+		inline_	void				SetRow(const udword r, const Point& p)		{ m[r][0]=p.x;	m[r][1]=p.y;	m[r][2]=p.z;	m[r][3]= (r!=3) ? 0.0f : 1.0f;		}
+		//! Returns a column.
+		inline_	void				GetCol(const udword c, HPoint& p)	const	{ p.x=m[0][c];	p.y=m[1][c];	p.z=m[2][c];	p.w=m[3][c];		}
+		//! Returns a column.
+		inline_	void				GetCol(const udword c, Point& p)	const	{ p.x=m[0][c];	p.y=m[1][c];	p.z=m[2][c];						}
+		//! Sets a column.
+		inline_	void				SetCol(const udword c, const HPoint& p)		{ m[0][c]=p.x;	m[1][c]=p.y;	m[2][c]=p.z;	m[3][c]=p.w;		}
+		//! Sets a column.
+		inline_	void				SetCol(const udword c, const Point& p)		{ m[0][c]=p.x;	m[1][c]=p.y;	m[2][c]=p.z;	m[3][c]= (c!=3) ? 0.0f : 1.0f;	}
+
+		// Translation
+		//! Returns the translation part of the matrix.
+		inline_	const HPoint&		GetTrans()							const	{ return GetRow(3);								}
+		//! Gets the translation part of the matrix
+		inline_	void				GetTrans(Point& p)					const	{ p.x=m[3][0];	p.y=m[3][1];	p.z=m[3][2];	}
+		//! Sets the translation part of the matrix, from a Point.
+		inline_	void				SetTrans(const Point& p)					{ m[3][0]=p.x;	m[3][1]=p.y;	m[3][2]=p.z;	}
+		//! Sets the translation part of the matrix, from a HPoint.
+		inline_	void				SetTrans(const HPoint& p)					{ m[3][0]=p.x;	m[3][1]=p.y;	m[3][2]=p.z;	m[3][3]=p.w;	}
+		//! Sets the translation part of the matrix, from floats.
+		inline_	void				SetTrans(float tx, float ty, float tz)		{ m[3][0]=tx;	m[3][1]=ty;		m[3][2]=tz;		}
+
+		// Scale
+		//! Sets the scale from a Point. The point is put on the diagonal.
+		inline_	void				SetScale(const Point& p)					{ m[0][0]=p.x;	m[1][1]=p.y;	m[2][2]=p.z;	}
+		//! Sets the scale from floats. Values are put on the diagonal.
+		inline_	void				SetScale(float sx, float sy, float sz)		{ m[0][0]=sx;	m[1][1]=sy;		m[2][2]=sz;		}
+		//! Scales from a Point. Each row is multiplied by a component.
+				void				Scale(const Point& p)
+									{
+										m[0][0] *= p.x;	m[1][0] *= p.y;	m[2][0] *= p.z;
+										m[0][1] *= p.x;	m[1][1] *= p.y;	m[2][1] *= p.z;
+										m[0][2] *= p.x;	m[1][2] *= p.y;	m[2][2] *= p.z;
+									}
+		//! Scales from floats. Each row is multiplied by a value.
+				void				Scale(float sx, float sy, float sz)
+									{
+										m[0][0] *= sx;	m[1][0] *= sy;	m[2][0] *= sz;
+										m[0][1] *= sx;	m[1][1] *= sy;	m[2][1] *= sz;
+										m[0][2] *= sx;	m[1][2] *= sy;	m[2][2] *= sz;
+									}
+/*
+		//! Returns a row.
+		inline_	HPoint		GetRow(const udword row)	const			{ return mRow[row];														}
+		//! Sets a row.
+		inline_	Matrix4x4&	SetRow(const udword row, const HPoint& p)	{ mRow[row] = p;	return *this;										}
+		//! Sets a row.
+						Matrix4x4&	SetRow(const udword row, const Point& p)
+						{
+							m[row][0] = p.x;
+							m[row][1] = p.y;
+							m[row][2] = p.z;
+							m[row][3] = (row != 3) ? 0.0f : 1.0f;
+							return	*this;
+						}
+		//! Returns a column.
+						HPoint		GetCol(const udword col)		const
+						{
+							HPoint	Res;
+							Res.x = m[0][col];
+							Res.y = m[1][col];
+							Res.z = m[2][col];
+							Res.w = m[3][col];
+							return	Res;
+						}
+		//! Sets a column.
+						Matrix4x4&	SetCol(const udword col, const HPoint& p)
+						{
+							m[0][col] = p.x;
+							m[1][col] = p.y;
+							m[2][col] = p.z;
+							m[3][col] = p.w;
+							return	*this;
+						}
+		//! Sets a column.
+						Matrix4x4&	SetCol(const udword col, const Point& p)
+						{
+							m[0][col] = p.x;
+							m[1][col] = p.y;
+							m[2][col] = p.z;
+							m[3][col] = (col != 3) ? 0.0f : 1.0f;
+							return	*this;
+						}
+*/
+		//! Computes the trace. The trace is the sum of the 4 diagonal components.
+		inline_	float				Trace()			const			{ return m[0][0] + m[1][1] + m[2][2] + m[3][3];			}
+		//! Computes the trace of the upper 3x3 matrix.
+		inline_	float				Trace3x3()		const			{ return m[0][0] + m[1][1] + m[2][2];					}
+		//! Clears the matrix.
+		inline_	void				Zero()							{ ZeroMemory(&m,  sizeof(m));							}
+		//! Sets the identity matrix.
+		inline_	void				Identity()						{ Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;	}
+		//! Checks for identity
+		inline_	bool				IsIdentity()	const
+									{
+										if(IR(m[0][0])!=IEEE_1_0)	return false;
+										if(IR(m[0][1])!=0)			return false;
+										if(IR(m[0][2])!=0)			return false;
+										if(IR(m[0][3])!=0)			return false;
+
+										if(IR(m[1][0])!=0)			return false;
+										if(IR(m[1][1])!=IEEE_1_0)	return false;
+										if(IR(m[1][2])!=0)			return false;
+										if(IR(m[1][3])!=0)			return false;
+
+										if(IR(m[2][0])!=0)			return false;
+										if(IR(m[2][1])!=0)			return false;
+										if(IR(m[2][2])!=IEEE_1_0)	return false;
+										if(IR(m[2][3])!=0)			return false;
+
+										if(IR(m[3][0])!=0)			return false;
+										if(IR(m[3][1])!=0)			return false;
+										if(IR(m[3][2])!=0)			return false;
+										if(IR(m[3][3])!=IEEE_1_0)	return false;
+										return true;
+									}
+
+		//! Checks matrix validity
+		inline_	BOOL				IsValid()		const
+									{
+										for(udword j=0;j<4;j++)
+										{
+											for(udword i=0;i<4;i++)
+											{
+												if(!IsValidFloat(m[j][i]))	return FALSE;
+											}
+										}
+										return TRUE;
+									}
+
+		//! Sets a rotation matrix around the X axis.
+				void				RotX(float angle)	{ float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin;	m[1][2] = Sin;	}
+		//! Sets a rotation matrix around the Y axis.
+				void				RotY(float angle)	{ float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin;	m[0][2] = -Sin;	}
+		//! Sets a rotation matrix around the Z axis.
+				void				RotZ(float angle)	{ float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin;	m[0][1] = Sin;	}
+
+		//! Makes a rotation matrix about an arbitrary axis
+				Matrix4x4&			Rot(float angle, Point& p1, Point& p2);
+
+		//! Transposes the matrix.
+				void				Transpose()
+									{
+										IR(m[1][0]) ^= IR(m[0][1]);		IR(m[0][1]) ^= IR(m[1][0]);		IR(m[1][0]) ^= IR(m[0][1]);
+										IR(m[2][0]) ^= IR(m[0][2]);		IR(m[0][2]) ^= IR(m[2][0]);		IR(m[2][0]) ^= IR(m[0][2]);
+										IR(m[3][0]) ^= IR(m[0][3]);		IR(m[0][3]) ^= IR(m[3][0]);		IR(m[3][0]) ^= IR(m[0][3]);
+										IR(m[1][2]) ^= IR(m[2][1]);		IR(m[2][1]) ^= IR(m[1][2]);		IR(m[1][2]) ^= IR(m[2][1]);
+										IR(m[1][3]) ^= IR(m[3][1]);		IR(m[3][1]) ^= IR(m[1][3]);		IR(m[1][3]) ^= IR(m[3][1]);
+										IR(m[2][3]) ^= IR(m[3][2]);		IR(m[3][2]) ^= IR(m[2][3]);		IR(m[2][3]) ^= IR(m[3][2]);
+									}
+
+		//! Computes a cofactor. Used for matrix inversion.
+				float				CoFactor(udword row, udword col)	const;
+		//! Computes the determinant of the matrix.
+				float				Determinant()	const;
+		//! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted.
+				Matrix4x4&			Invert();
+//				Matrix&	ComputeAxisMatrix(Point& axis, float angle);
+
+		// Cast operators
+		//! Casts a Matrix4x4 to a Matrix3x3.
+		inline_	operator			Matrix3x3()	const
+									{
+										return Matrix3x3(
+										m[0][0],	m[0][1],	m[0][2],
+										m[1][0],	m[1][1],	m[1][2],
+										m[2][0],	m[2][1],	m[2][2]);
+									}
+		//! Casts a Matrix4x4 to a Quat.
+				operator			Quat()	const;
+		//! Casts a Matrix4x4 to a PR.
+				operator			PR()	const;
+
+		// Arithmetic operators
+		//! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4;
+		inline_	Matrix4x4			operator+(const Matrix4x4& mat)	const
+									{
+										return Matrix4x4(
+										m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3], 
+										m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3], 
+										m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3], 
+										m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]);
+									}
+
+		//! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4;
+		inline_	Matrix4x4			operator-(const Matrix4x4& mat)	const
+									{
+										return Matrix4x4(
+										m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3], 
+										m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3], 
+										m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3], 
+										m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]);
+									}
+
+		//! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4;
+		inline_	Matrix4x4			operator*(const Matrix4x4& mat)	const
+									{
+										return Matrix4x4(
+										m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0],
+										m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1],
+										m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2],
+										m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3],
+
+										m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0],
+										m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1],
+										m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2],
+										m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3],
+
+										m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0],
+										m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1],
+										m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2],
+										m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3],
+
+										m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0],
+										m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1],
+										m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2],
+										m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]);
+									}
+
+		//! Operator for HPoint Mul = Matrix4x4 * HPoint;
+		inline_	HPoint				operator*(const HPoint& v)		const	{ return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); }
+
+		//! Operator for Point Mul = Matrix4x4 * Point;
+		inline_	Point				operator*(const Point& v)		const
+									{
+										return Point(	m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3],
+														m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3],
+														m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3]	);
+									}
+
+		//! Operator for Matrix4x4 Scale = Matrix4x4 * float;
+		inline_	Matrix4x4			operator*(float s)				const
+									{
+										return Matrix4x4(
+										m[0][0]*s,	m[0][1]*s,	m[0][2]*s,	m[0][3]*s,
+										m[1][0]*s,	m[1][1]*s,	m[1][2]*s,	m[1][3]*s,
+										m[2][0]*s,	m[2][1]*s,	m[2][2]*s,	m[2][3]*s,
+										m[3][0]*s,	m[3][1]*s,	m[3][2]*s,	m[3][3]*s);
+									}
+
+		//! Operator for Matrix4x4 Scale = float * Matrix4x4;
+		inline_	friend Matrix4x4	operator*(float s, const Matrix4x4& mat)
+									{
+										return Matrix4x4(
+										s*mat.m[0][0],	s*mat.m[0][1],	s*mat.m[0][2],	s*mat.m[0][3],
+										s*mat.m[1][0],	s*mat.m[1][1],	s*mat.m[1][2],	s*mat.m[1][3],
+										s*mat.m[2][0],	s*mat.m[2][1],	s*mat.m[2][2],	s*mat.m[2][3],
+										s*mat.m[3][0],	s*mat.m[3][1],	s*mat.m[3][2],	s*mat.m[3][3]);
+									}
+
+		//! Operator for Matrix4x4 Div = Matrix4x4 / float;
+		inline_	Matrix4x4			operator/(float s)				const
+									{
+										if(s) s = 1.0f / s;
+
+										return Matrix4x4(
+										m[0][0]*s,	m[0][1]*s,	m[0][2]*s,	m[0][3]*s,
+										m[1][0]*s,	m[1][1]*s,	m[1][2]*s,	m[1][3]*s,
+										m[2][0]*s,	m[2][1]*s,	m[2][2]*s,	m[2][3]*s,
+										m[3][0]*s,	m[3][1]*s,	m[3][2]*s,	m[3][3]*s);
+									}
+
+		//! Operator for Matrix4x4 Div = float / Matrix4x4;
+		inline_	friend Matrix4x4	operator/(float s, const Matrix4x4& mat)
+									{
+										return Matrix4x4(
+										s/mat.m[0][0],	s/mat.m[0][1],	s/mat.m[0][2],	s/mat.m[0][3],
+										s/mat.m[1][0],	s/mat.m[1][1],	s/mat.m[1][2],	s/mat.m[1][3],
+										s/mat.m[2][0],	s/mat.m[2][1],	s/mat.m[2][2],	s/mat.m[2][3],
+										s/mat.m[3][0],	s/mat.m[3][1],	s/mat.m[3][2],	s/mat.m[3][3]);
+									}
+
+		//! Operator for Matrix4x4 += Matrix4x4;
+		inline_	Matrix4x4&			operator+=(const Matrix4x4& mat)
+									{
+										m[0][0]+=mat.m[0][0];	m[0][1]+=mat.m[0][1];	m[0][2]+=mat.m[0][2];	m[0][3]+=mat.m[0][3];
+										m[1][0]+=mat.m[1][0];	m[1][1]+=mat.m[1][1];	m[1][2]+=mat.m[1][2];	m[1][3]+=mat.m[1][3];
+										m[2][0]+=mat.m[2][0];	m[2][1]+=mat.m[2][1];	m[2][2]+=mat.m[2][2];	m[2][3]+=mat.m[2][3];
+										m[3][0]+=mat.m[3][0];	m[3][1]+=mat.m[3][1];	m[3][2]+=mat.m[3][2];	m[3][3]+=mat.m[3][3];
+										return	*this;
+									}
+
+		//! Operator for Matrix4x4 -= Matrix4x4;
+		inline_	Matrix4x4&			operator-=(const Matrix4x4& mat)
+									{
+										m[0][0]-=mat.m[0][0];	m[0][1]-=mat.m[0][1];	m[0][2]-=mat.m[0][2];	m[0][3]-=mat.m[0][3];
+										m[1][0]-=mat.m[1][0];	m[1][1]-=mat.m[1][1];	m[1][2]-=mat.m[1][2];	m[1][3]-=mat.m[1][3];
+										m[2][0]-=mat.m[2][0];	m[2][1]-=mat.m[2][1];	m[2][2]-=mat.m[2][2];	m[2][3]-=mat.m[2][3];
+										m[3][0]-=mat.m[3][0];	m[3][1]-=mat.m[3][1];	m[3][2]-=mat.m[3][2];	m[3][3]-=mat.m[3][3];
+										return	*this;
+									}
+
+		//! Operator for Matrix4x4 *= Matrix4x4;
+				Matrix4x4&			operator*=(const Matrix4x4& mat)
+									{
+										HPoint TempRow;
+
+										GetRow(0, TempRow);
+										m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
+										m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
+										m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
+										m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
+
+										GetRow(1, TempRow);
+										m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
+										m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
+										m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
+										m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
+
+										GetRow(2, TempRow);
+										m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
+										m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
+										m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
+										m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
+
+										GetRow(3, TempRow);
+										m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
+										m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
+										m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
+										m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
+
+										return	*this;
+									}
+
+		//! Operator for Matrix4x4 *= float;
+		inline_	Matrix4x4&		operator*=(float s)
+								{
+									m[0][0]*=s;	m[0][1]*=s;	m[0][2]*=s;	m[0][3]*=s;
+									m[1][0]*=s;	m[1][1]*=s;	m[1][2]*=s;	m[1][3]*=s;
+									m[2][0]*=s;	m[2][1]*=s;	m[2][2]*=s;	m[2][3]*=s;
+									m[3][0]*=s;	m[3][1]*=s;	m[3][2]*=s;	m[3][3]*=s;
+									return	*this;
+								}
+
+		//! Operator for Matrix4x4 /= float;
+		inline_	Matrix4x4&		operator/=(float s)
+								{
+									if(s)  s = 1.0f / s;
+									m[0][0]*=s;	m[0][1]*=s;	m[0][2]*=s;	m[0][3]*=s;
+									m[1][0]*=s;	m[1][1]*=s;	m[1][2]*=s;	m[1][3]*=s;
+									m[2][0]*=s;	m[2][1]*=s;	m[2][2]*=s;	m[2][3]*=s;
+									m[3][0]*=s;	m[3][1]*=s;	m[3][2]*=s;	m[3][3]*=s;
+									return	*this;
+								}
+
+		inline_	const HPoint&	operator[](int row)		const	{ return *(const HPoint*)&m[row][0];	}
+		inline_	HPoint&			operator[](int row)				{ return *(HPoint*)&m[row][0];			}
+
+		public:
+
+				float			m[4][4];
+	};
+
+	//! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix
+	inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot)
+	{
+		dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
+		dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
+		dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
+	}
+
+	//! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix
+	inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot)
+	{
+		dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
+		dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
+		dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
+	}
+
+	ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src);
+
+#endif // __ICEMATRIX4X4_H__
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceMemoryMacros.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceMemoryMacros.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceMemoryMacros.h	(revision 216)
@@ -0,0 +1,109 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains all memory macros.
+ *	\file		IceMemoryMacros.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEMEMORYMACROS_H__
+#define __ICEMEMORYMACROS_H__
+
+#undef ZeroMemory
+#undef CopyMemory
+#undef MoveMemory
+#undef FillMemory
+
+	//!	Clears a buffer.
+	//!	\param		addr	[in] buffer address
+	//!	\param		size	[in] buffer length
+	//!	\see		FillMemory
+	//!	\see		StoreDwords
+	//!	\see		CopyMemory
+	//!	\see		MoveMemory
+	inline_ void ZeroMemory(void* addr, udword size)					{ memset(addr, 0, size);		}
+
+	//!	Fills a buffer with a given byte.
+	//!	\param		addr	[in] buffer address
+	//!	\param		size	[in] buffer length
+	//!	\param		val		[in] the byte value
+	//!	\see		StoreDwords
+	//!	\see		ZeroMemory
+	//!	\see		CopyMemory
+	//!	\see		MoveMemory
+	inline_ void FillMemory(void* dest, udword size, ubyte val)			{ memset(dest, val, size);		}
+
+	//!	Fills a buffer with a given dword.
+	//!	\param		addr	[in] buffer address
+	//!	\param		nb		[in] number of dwords to write
+	//!	\param		value	[in] the dword value
+	//!	\see		FillMemory
+	//!	\see		ZeroMemory
+	//!	\see		CopyMemory
+	//!	\see		MoveMemory
+	//!	\warning	writes nb*4 bytes !
+	inline_ void StoreDwords(udword* dest, udword nb, udword value)
+	{
+		// The asm code below **SHOULD** be equivalent to one of those C versions
+		// or the other if your compiled is good: (checked on VC++ 6.0)
+		//
+		//	1) while(nb--)	*dest++ = value;
+		//
+		//	2) for(udword i=0;i<nb;i++)	dest[i] = value;
+		//
+#ifdef _MSC_VER
+		_asm push eax
+		_asm push ecx
+		_asm push edi
+		_asm mov edi, dest
+		_asm mov ecx, nb
+		_asm mov eax, value
+		_asm rep stosd
+		_asm pop edi
+		_asm pop ecx
+		_asm pop eax
+#else
+		while(nb--) *dest++ = value;
+#endif
+	}
+
+	//!	Copies a buffer.
+	//!	\param		addr	[in] destination buffer address
+	//!	\param		addr	[in] source buffer address
+	//!	\param		size	[in] buffer length
+	//!	\see		ZeroMemory
+	//!	\see		FillMemory
+	//!	\see		StoreDwords
+	//!	\see		MoveMemory
+	inline_ void CopyMemory(void* dest, const void* src, udword size)	{ memcpy(dest, src, size);		}
+
+	//!	Moves a buffer.
+	//!	\param		addr	[in] destination buffer address
+	//!	\param		addr	[in] source buffer address
+	//!	\param		size	[in] buffer length
+	//!	\see		ZeroMemory
+	//!	\see		FillMemory
+	//!	\see		StoreDwords
+	//!	\see		CopyMemory
+	inline_ void MoveMemory(void* dest, const void* src, udword size)	{ memmove(dest, src, size);		}
+
+	#define SIZEOFOBJECT		sizeof(*this)									//!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)").
+	//#define CLEAROBJECT		{ memset(this, 0, SIZEOFOBJECT);	}			//!< Clears current object. Laziness is my business. HANDLE WITH CARE.
+	#define DELETESINGLE(x)		if (x) { delete x;				x = null; }		//!< Deletes an instance of a class.
+	#define DELETEARRAY(x)		if (x) { delete []x;			x = null; }		//!< Deletes an array.
+	#define SAFE_RELEASE(x)		if (x) { (x)->Release();		(x) = null; }	//!< Safe D3D-style release
+	#define SAFE_DESTRUCT(x)	if (x) { (x)->SelfDestruct();	(x) = null; }	//!< Safe ICE-style release
+
+#ifdef __ICEERROR_H__
+	#define CHECKALLOC(x)		if(!x) return SetIceError("Out of memory.", EC_OUT_OF_MEMORY);	//!< Standard alloc checking. HANDLE WITH CARE.
+#else
+	#define CHECKALLOC(x)		if(!x) return false;
+#endif
+
+	//! Standard allocation cycle
+	#define SAFE_ALLOC(ptr, type, count)	DELETEARRAY(ptr);	ptr = new type[count];	CHECKALLOC(ptr);
+
+#endif // __ICEMEMORYMACROS_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceOBB.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceOBB.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceOBB.cpp	(revision 216)
@@ -0,0 +1,323 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains OBB-related code.
+ *	\file		IceOBB.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	An Oriented Bounding Box (OBB).
+ *	\class		OBB
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Tests if a point is contained within the OBB.
+ *	\param		p	[in] the world point to test
+ *	\return		true if inside the OBB
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool OBB::ContainsPoint(const Point& p) const
+{
+	// Point in OBB test using lazy evaluation and early exits
+
+	// Translate to box space
+	Point RelPoint = p - mCenter;
+
+	// Point * mRot maps from box space to world space
+	// mRot * Point maps from world space to box space (what we need here)
+
+	float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z;
+	if(f >= mExtents.x || f <= -mExtents.x) return false;
+
+	f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z;
+	if(f >= mExtents.y || f <= -mExtents.y) return false;
+
+	f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z;
+	if(f >= mExtents.z || f <= -mExtents.z) return false;
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds an OBB from an AABB and a world transform.
+ *	\param		aabb	[in] the aabb
+ *	\param		mat		[in] the world transform
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBB::Create(const AABB& aabb, const Matrix4x4& mat)
+{
+	// Note: must be coherent with Rotate()
+
+	aabb.GetCenter(mCenter);
+	aabb.GetExtents(mExtents);
+	// Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity).
+
+	// So following what's done in Rotate:
+	// - x-form the center
+	mCenter *= mat;
+	// - combine rotation with identity, i.e. just use given matrix
+	mRot = mat;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the obb planes.
+ *	\param		planes	[out] 6 box planes
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool OBB::ComputePlanes(Plane* planes)	const
+{
+	// Checkings
+	if(!planes)	return false;
+
+	Point Axis0 = mRot[0];
+	Point Axis1 = mRot[1];
+	Point Axis2 = mRot[2];
+
+	// Writes normals
+	planes[0].n = Axis0;
+	planes[1].n = -Axis0;
+	planes[2].n = Axis1;
+	planes[3].n = -Axis1;
+	planes[4].n = Axis2;
+	planes[5].n = -Axis2;
+
+	// Compute a point on each plane
+	Point p0 = mCenter + Axis0 * mExtents.x;
+	Point p1 = mCenter - Axis0 * mExtents.x;
+	Point p2 = mCenter + Axis1 * mExtents.y;
+	Point p3 = mCenter - Axis1 * mExtents.y;
+	Point p4 = mCenter + Axis2 * mExtents.z;
+	Point p5 = mCenter - Axis2 * mExtents.z;
+
+	// Compute d
+	planes[0].d = -(planes[0].n|p0);
+	planes[1].d = -(planes[1].n|p1);
+	planes[2].d = -(planes[2].n|p2);
+	planes[3].d = -(planes[3].n|p3);
+	planes[4].d = -(planes[4].n|p4);
+	planes[5].d = -(planes[5].n|p5);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the obb points.
+ *	\param		pts	[out] 8 box points
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool OBB::ComputePoints(Point* pts)	const
+{
+	// Checkings
+	if(!pts)	return false;
+
+	Point Axis0 = mRot[0];
+	Point Axis1 = mRot[1];
+	Point Axis2 = mRot[2];
+
+	Axis0 *= mExtents.x;
+	Axis1 *= mExtents.y;
+	Axis2 *= mExtents.z;
+
+	//     7+------+6			0 = ---
+	//     /|     /|			1 = +--
+	//    / |    / |			2 = ++-
+	//   / 4+---/--+5			3 = -+-
+	// 3+------+2 /    y   z	4 = --+
+	//  | /    | /     |  /		5 = +-+
+	//  |/     |/      |/		6 = +++
+	// 0+------+1      *---x	7 = -++
+
+	pts[0] = mCenter - Axis0 - Axis1 - Axis2;
+	pts[1] = mCenter + Axis0 - Axis1 - Axis2;
+	pts[2] = mCenter + Axis0 + Axis1 - Axis2;
+	pts[3] = mCenter - Axis0 + Axis1 - Axis2;
+	pts[4] = mCenter - Axis0 - Axis1 + Axis2;
+	pts[5] = mCenter + Axis0 - Axis1 + Axis2;
+	pts[6] = mCenter + Axis0 + Axis1 + Axis2;
+	pts[7] = mCenter - Axis0 + Axis1 + Axis2;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes vertex normals.
+ *	\param		pts	[out] 8 box points
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool OBB::ComputeVertexNormals(Point* pts)	const
+{
+	static float VertexNormals[] = 
+	{
+		-INVSQRT3,	-INVSQRT3,	-INVSQRT3,
+		INVSQRT3,	-INVSQRT3,	-INVSQRT3,
+		INVSQRT3,	INVSQRT3,	-INVSQRT3,
+		-INVSQRT3,	INVSQRT3,	-INVSQRT3,
+		-INVSQRT3,	-INVSQRT3,	INVSQRT3,
+		INVSQRT3,	-INVSQRT3,	INVSQRT3,
+		INVSQRT3,	INVSQRT3,	INVSQRT3,
+		-INVSQRT3,	INVSQRT3,	INVSQRT3
+	};
+
+	if(!pts)	return false;
+
+	const Point* VN = (const Point*)VertexNormals;
+	for(udword i=0;i<8;i++)
+	{
+		pts[i] = VN[i] * mRot;
+	}
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns edges.
+ *	\return		24 indices (12 edges) indexing the list returned by ComputePoints()
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const udword* OBB::GetEdges() const
+{
+	static udword Indices[] = {
+	0, 1,	1, 2,	2, 3,	3, 0,
+	7, 6,	6, 5,	5, 4,	4, 7,
+	1, 5,	6, 2,
+	3, 7,	4, 0
+	};
+	return Indices;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns local edge normals.
+ *	\return		edge normals in local space
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const Point* OBB::GetLocalEdgeNormals() const
+{
+	static float EdgeNormals[] = 
+	{
+		0,			-INVSQRT2,	-INVSQRT2,	// 0-1
+		INVSQRT2,	0,			-INVSQRT2,	// 1-2
+		0,			INVSQRT2,	-INVSQRT2,	// 2-3
+		-INVSQRT2,	0,			-INVSQRT2,	// 3-0
+
+		0,			INVSQRT2,	INVSQRT2,	// 7-6
+		INVSQRT2,	0,			INVSQRT2,	// 6-5
+		0,			-INVSQRT2,	INVSQRT2,	// 5-4
+		-INVSQRT2,	0,			INVSQRT2,	// 4-7
+
+		INVSQRT2,	-INVSQRT2,	0,			// 1-5
+		INVSQRT2,	INVSQRT2,	0,			// 6-2
+		-INVSQRT2,	INVSQRT2,	0,			// 3-7
+		-INVSQRT2,	-INVSQRT2,	0			// 4-0
+	};
+	return (const Point*)EdgeNormals;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns world edge normal
+ *	\param		edge_index		[in] 0 <= edge index < 12
+ *	\param		world_normal	[out] edge normal in world space
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBB::ComputeWorldEdgeNormal(udword edge_index, Point& world_normal) const
+{
+	ASSERT(edge_index<12);
+	world_normal = GetLocalEdgeNormals()[edge_index] * mRot;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes an LSS surrounding the OBB.
+ *	\param		lss		[out] the LSS
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBB::ComputeLSS(LSS& lss) const
+{
+	Point Axis0 = mRot[0];
+	Point Axis1 = mRot[1];
+	Point Axis2 = mRot[2];
+
+	switch(mExtents.LargestAxis())
+	{
+		case 0:
+			lss.mRadius = (mExtents.y + mExtents.z)*0.5f;
+			lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius);
+			lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius);
+			break;
+		case 1:
+			lss.mRadius = (mExtents.x + mExtents.z)*0.5f;
+			lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius);
+			lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius);
+			break;
+		case 2:
+			lss.mRadius = (mExtents.x + mExtents.y)*0.5f;
+			lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius);
+			lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius);
+			break;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the OBB is inside another OBB.
+ *	\param		box		[in] the other OBB
+ *	\return		TRUE if we're inside the other box
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL OBB::IsInside(const OBB& box) const
+{
+	// Make a 4x4 from the box & inverse it
+	Matrix4x4 M0Inv;
+	{
+		Matrix4x4 M0 = box.mRot;
+		M0.SetTrans(box.mCenter);
+		InvertPRMatrix(M0Inv, M0);
+	}
+
+	// With our inversed 4x4, create box1 in space of box0
+	OBB _1in0;
+	Rotate(M0Inv, _1in0);
+
+	// This should cancel out box0's rotation, i.e. it's now an AABB.
+	// => Center(0,0,0), Rot(identity)
+
+	// The two boxes are in the same space so now we can compare them.
+
+	// Create the AABB of (box1 in space of box0)
+	const Matrix3x3& mtx = _1in0.mRot;
+
+	float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x;
+	if(f > _1in0.mCenter.x)		return FALSE;
+	if(-f < _1in0.mCenter.x)	return FALSE;
+
+	f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y;
+	if(f > _1in0.mCenter.y)		return FALSE;
+	if(-f < _1in0.mCenter.y)	return FALSE;
+
+	f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z;
+	if(f > _1in0.mCenter.z)		return FALSE;
+	if(-f < _1in0.mCenter.z)	return FALSE;
+
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceOBB.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceOBB.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceOBB.h	(revision 216)
@@ -0,0 +1,177 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains OBB-related code. (oriented bounding box)
+ *	\file		IceOBB.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 13, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEOBB_H__
+#define __ICEOBB_H__
+
+	// Forward declarations
+	class LSS;
+
+	class ICEMATHS_API OBB
+	{
+		public:
+		//! Constructor
+		inline_						OBB()		{}
+		//! Constructor
+		inline_						OBB(const Point& center, const Point& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot)	{}
+		//! Destructor
+		inline_						~OBB()		{}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an empty OBB.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				void				SetEmpty()
+									{
+										mCenter.Zero();
+										mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
+										mRot.Identity();
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Tests if a point is contained within the OBB.
+		 *	\param		p	[in] the world point to test
+		 *	\return		true if inside the OBB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool				ContainsPoint(const Point& p)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Builds an OBB from an AABB and a world transform.
+		 *	\param		aabb	[in] the aabb
+		 *	\param		mat		[in] the world transform
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				void				Create(const AABB& aabb, const Matrix4x4& mat);
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Recomputes the OBB after an arbitrary transform by a 4x4 matrix.
+		 *	\param		mtx		[in] the transform matrix
+		 *	\param		obb		[out] the transformed OBB
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	void				Rotate(const Matrix4x4& mtx, OBB& obb)	const
+									{
+										// The extents remain constant
+										obb.mExtents = mExtents;
+										// The center gets x-formed
+										obb.mCenter = mCenter * mtx;
+										// Combine rotations
+										obb.mRot = mRot * Matrix3x3(mtx);
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the OBB is valid.
+		 *	\return		true if the box is valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	BOOL				IsValid()	const
+									{
+										// Consistency condition for (Center, Extents) boxes: Extents >= 0.0f
+										if(mExtents.x < 0.0f)	return FALSE;
+										if(mExtents.y < 0.0f)	return FALSE;
+										if(mExtents.z < 0.0f)	return FALSE;
+										return TRUE;
+									}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the obb planes.
+		 *	\param		planes	[out] 6 box planes
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool				ComputePlanes(Plane* planes)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the obb points.
+		 *	\param		pts	[out] 8 box points
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool				ComputePoints(Point* pts)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes vertex normals.
+		 *	\param		pts	[out] 8 box points
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				bool				ComputeVertexNormals(Point* pts)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Returns edges.
+		 *	\return		24 indices (12 edges) indexing the list returned by ComputePoints()
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				const udword*		GetEdges()	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Returns local edge normals.
+		 *	\return		edge normals in local space
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				const Point*		GetLocalEdgeNormals()	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Returns world edge normal
+		 *	\param		edge_index		[in] 0 <= edge index < 12
+		 *	\param		world_normal	[out] edge normal in world space
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				void				ComputeWorldEdgeNormal(udword edge_index, Point& world_normal)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes an LSS surrounding the OBB.
+		 *	\param		lss		[out] the LSS
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				void				ComputeLSS(LSS& lss)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the OBB is inside another OBB.
+		 *	\param		box		[in] the other OBB
+		 *	\return		TRUE if we're inside the other box
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				BOOL				IsInside(const OBB& box)	const;
+
+		inline_	const Point&		GetCenter()		const	{ return mCenter;	}
+		inline_	const Point&		GetExtents()	const	{ return mExtents;	}
+		inline_	const Matrix3x3&	GetRot()		const	{ return mRot;		}
+
+		inline_	void				GetRotatedExtents(Matrix3x3& extents)	const
+									{
+										extents = mRot;
+										extents.Scale(mExtents);
+									}
+
+				Point				mCenter;		//!< B for Box
+				Point				mExtents;		//!< B for Bounding
+				Matrix3x3			mRot;			//!< O for Oriented
+
+				// Orientation is stored in row-major format,
+				// i.e. rows = eigen vectors of the covariance matrix
+	};
+
+#endif	// __ICEOBB_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IcePairs.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IcePairs.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IcePairs.h	(revision 216)
@@ -0,0 +1,45 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a simple pair class.
+ *	\file		IcePairs.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 13, 2003
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEPAIRS_H__
+#define __ICEPAIRS_H__
+
+	//! A generic couple structure
+	struct ICECORE_API Pair
+	{
+		inline_	Pair()	{}
+		inline_	Pair(udword i0, udword i1) : id0(i0), id1(i1)	{}
+
+		udword	id0;	//!< First index of the pair
+		udword	id1;	//!< Second index of the pair
+	};
+
+	class ICECORE_API Pairs : private Container
+	{
+		public:
+		// Constructor / Destructor
+								Pairs()							{}
+								~Pairs()						{}
+
+		inline_	udword			GetNbPairs()		const		{ return GetNbEntries()>>1;					}
+		inline_	const Pair*		GetPairs()			const		{ return (const Pair*)GetEntries();			}
+		inline_	const Pair*		GetPair(udword i)	const		{ return (const Pair*)&GetEntries()[i+i];	}
+
+		inline_	BOOL			HasPairs()			const		{ return IsNotEmpty();						}
+
+		inline_	void			ResetPairs()					{ Reset();									}
+		inline_	void			DeleteLastPair()				{ DeleteLastEntry();	DeleteLastEntry();	}
+
+		inline_	void			AddPair(const Pair& p)			{ Add(p.id0).Add(p.id1);					}
+		inline_	void			AddPair(udword id0, udword id1)	{ Add(id0).Add(id1);						}
+	};
+
+#endif // __ICEPAIRS_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IcePlane.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IcePlane.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IcePlane.cpp	(revision 216)
@@ -0,0 +1,45 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for planes.
+ *	\file		IcePlane.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Plane class.
+ *	\class		Plane
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the plane equation from 3 points.
+ *	\param		p0	[in] first point
+ *	\param		p1	[in] second point
+ *	\param		p2	[in] third point
+ *	\return		Self-reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Plane& Plane::Set(const Point& p0, const Point& p1, const Point& p2)
+{
+	Point Edge0 = p1 - p0;
+	Point Edge1 = p2 - p0;
+
+	n = Edge0 ^ Edge1;
+	n.Normalize();
+
+	d = -(p0 | n);
+
+	return	*this;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IcePlane.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IcePlane.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IcePlane.h	(revision 216)
@@ -0,0 +1,113 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for planes.
+ *	\file		IcePlane.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEPLANE_H__
+#define __ICEPLANE_H__
+
+	#define PLANE_EPSILON		(1.0e-7f)
+
+	class ICEMATHS_API Plane
+	{
+		public:
+		//! Constructor
+		inline_			Plane()															{												}
+		//! Constructor from a normal and a distance
+		inline_			Plane(float nx, float ny, float nz, float d)					{ Set(nx, ny, nz, d);							}
+		//! Constructor from a point on the plane and a normal
+		inline_			Plane(const Point& p, const Point& n)							{ Set(p, n);									}
+		//! Constructor from three points
+		inline_			Plane(const Point& p0, const Point& p1, const Point& p2)		{ Set(p0, p1, p2);								}
+		//! Constructor from a normal and a distance
+		inline_			Plane(const Point& _n, float _d)								{ n = _n; d = _d;								}
+		//! Copy constructor
+		inline_			Plane(const Plane& plane) : n(plane.n), d(plane.d)				{												}
+		//! Destructor
+		inline_			~Plane()														{												}
+
+		inline_	Plane&	Zero()															{ n.Zero(); d = 0.0f;			return *this;	}
+		inline_	Plane&	Set(float nx, float ny, float nz, float _d)						{ n.Set(nx, ny, nz); d = _d;	return *this;	}
+		inline_	Plane&	Set(const Point& p, const Point& _n)							{ n = _n; d = - p | _n;			return *this;	}
+				Plane&	Set(const Point& p0, const Point& p1, const Point& p2);
+
+		inline_	float	Distance(const Point& p)			const						{ return (p | n) + d;							}
+		inline_	bool	Belongs(const Point& p)				const						{ return fabsf(Distance(p)) < PLANE_EPSILON;	}
+
+		inline_	void	Normalize()
+						{
+							float Denom = 1.0f / n.Magnitude();
+							n.x	*= Denom;
+							n.y	*= Denom;
+							n.z	*= Denom;
+							d	*= Denom;
+						}
+		public:
+		// Members
+				Point	n;		//!< The normal to the plane
+				float	d;		//!< The distance from the origin
+
+		// Cast operators
+		inline_			operator Point()					const						{ return n;										}
+		inline_			operator HPoint()					const						{ return HPoint(n, d);							}
+
+		// Arithmetic operators
+		inline_	Plane	operator*(const Matrix4x4& m)		const
+						{
+							// Old code from Irion. Kept for reference.
+							Plane Ret(*this);
+							return Ret *= m;
+						}
+
+		inline_	Plane&	operator*=(const Matrix4x4& m)
+						{
+							// Old code from Irion. Kept for reference.
+							Point n2 = HPoint(n, 0.0f) * m;
+							d = -((Point) (HPoint( -d*n, 1.0f ) * m) | n2);
+							n = n2;
+							return *this;
+						}
+	};
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
+	 *	\param		transformed	[out] transformed plane
+	 *	\param		plane		[in] source plane
+	 *	\param		transform	[in] transform matrix
+	 *	\warning	the plane normal must be unit-length
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	inline_	void TransformPlane(Plane& transformed, const Plane& plane, const Matrix4x4& transform)
+	{
+		// Rotate the normal using the rotation part of the 4x4 matrix
+		transformed.n = plane.n * Matrix3x3(transform);
+
+		// Compute new d
+		transformed.d = plane.d - (Point(transform.GetTrans())|transformed.n);
+	}
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	Transforms a plane by a 4x4 matrix. Same as Plane * Matrix4x4 operator, but faster.
+	 *	\param		plane		[in/out] source plane (transformed on return)
+	 *	\param		transform	[in] transform matrix
+	 *	\warning	the plane normal must be unit-length
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	inline_	void TransformPlane(Plane& plane, const Matrix4x4& transform)
+	{
+		// Rotate the normal using the rotation part of the 4x4 matrix
+		plane.n *= Matrix3x3(transform);
+
+		// Compute new d
+		plane.d -= Point(transform.GetTrans())|plane.n;
+	}
+
+#endif // __ICEPLANE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IcePoint.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IcePoint.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IcePoint.cpp	(revision 216)
@@ -0,0 +1,193 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for 3D vectors.
+ *	\file		IcePoint.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	3D point.
+ *
+ *	The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3".
+ *	So the choice was between "Point" and "Vector3", the first one looked better (IMHO).
+ *
+ *	Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3;
+ *	This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out:
+ *
+ *	\code
+ *		Point P0,P1 = some 3D points;
+ *		Point Delta = P1 - P0;
+ *	\endcode
+ *
+ *	This compiles fine, although you should have written:
+ *
+ *	\code
+ *		Point P0,P1 = some 3D points;
+ *		Vector3 Delta = P1 - P0;
+ *	\endcode
+ *
+ *	Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake
+ *	from the author or something you don't get.
+ *
+ *	One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors.
+ *	But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work.
+ *
+ *	Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store
+ *	your model's vertices and in most cases, you really want to use Points to save ram.
+ *
+ *	\class		Point
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Creates a positive unit random vector.
+ *	\return		Self-reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Point& Point::PositiveUnitRandomVector()
+{
+	x = UnitRandomFloat();
+	y = UnitRandomFloat();
+	z = UnitRandomFloat();
+	Normalize();
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Creates a unit random vector.
+ *	\return		Self-reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Point& Point::UnitRandomVector()
+{
+	x = UnitRandomFloat() - 0.5f;
+	y = UnitRandomFloat() - 0.5f;
+	z = UnitRandomFloat() - 0.5f;
+	Normalize();
+	return *this;
+}
+
+// Cast operator
+// WARNING: not inlined
+Point::operator HPoint() const	{ return HPoint(x, y, z, 0.0f); }
+
+Point& Point::Refract(const Point& eye, const Point& n, float refractindex, Point& refracted)
+{
+	//	Point EyePt = eye position
+	//	Point p = current vertex
+	//	Point n = vertex normal
+	//	Point rv = refracted vector
+	//	Eye vector - doesn't need to be normalized
+	Point Env;
+	Env.x = eye.x - x;
+	Env.y = eye.y - y;
+	Env.z = eye.z - z;
+
+	float NDotE = n|Env;
+	float NDotN = n|n;
+	NDotE /= refractindex;
+
+	// Refracted vector
+	refracted = n*NDotE - Env*NDotN;
+
+	return *this;
+}
+
+Point& Point::ProjectToPlane(const Plane& p)
+{
+	*this-= (p.d + (*this|p.n))*p.n;
+	return *this;
+}
+
+void Point::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const
+{
+	projected = HPoint(x, y, z, 1.0f) * mat;
+	projected.w = 1.0f / projected.w;
+
+	projected.x*=projected.w;
+	projected.y*=projected.w;
+	projected.z*=projected.w;
+
+	projected.x *= halfrenderwidth;		projected.x += halfrenderwidth;
+	projected.y *= -halfrenderheight;	projected.y += halfrenderheight;
+}
+
+void Point::SetNotUsed()
+{
+	// We use a particular integer pattern : 0xffffffff everywhere. This is a NAN.
+	IR(x) = 0xffffffff;
+	IR(y) = 0xffffffff;
+	IR(z) = 0xffffffff;
+}
+
+BOOL Point::IsNotUsed()	const
+{
+	if(IR(x)!=0xffffffff)	return FALSE;
+	if(IR(y)!=0xffffffff)	return FALSE;
+	if(IR(z)!=0xffffffff)	return FALSE;
+	return TRUE;
+}
+
+Point& Point::Mult(const Matrix3x3& mat, const Point& a)
+{
+	x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
+	y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
+	z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
+	return *this;
+}
+
+Point& Point::Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2)
+{
+	x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2];
+	y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2];
+	z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2];
+	return *this;
+}
+
+Point& Point::Mac(const Matrix3x3& mat, const Point& a)
+{
+	x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2];
+	y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2];
+	z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2];
+	return *this;
+}
+
+Point& Point::TransMult(const Matrix3x3& mat, const Point& a)
+{
+	x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0];
+	y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1];
+	z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2];
+	return *this;
+}
+
+Point& Point::Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
+{
+	x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x;
+	y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y;
+	z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z;
+	return *this;
+}
+
+Point& Point::InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos)
+{
+	float sx = r.x - linpos.x;
+	float sy = r.y - linpos.y;
+	float sz = r.z - linpos.z;
+	x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0];
+	y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1];
+	z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2];
+	return *this;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IcePoint.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IcePoint.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IcePoint.h	(revision 216)
@@ -0,0 +1,528 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for 3D vectors.
+ *	\file		IcePoint.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEPOINT_H__
+#define __ICEPOINT_H__
+
+	// Forward declarations
+	class HPoint;
+	class Plane;
+	class Matrix3x3;
+	class Matrix4x4;
+
+	#define CROSS2D(a, b)	(a.x*b.y - b.x*a.y)
+
+	const float EPSILON2 = 1.0e-20f;
+
+	class ICEMATHS_API Point
+	{
+		public:
+
+		//! Empty constructor
+		inline_					Point()														{}
+		//! Constructor from a single float
+//		inline_					Point(float val) : x(val), y(val), z(val)					{}
+// Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug.......
+		//! Constructor from floats
+		inline_					Point(float xx, float yy, float zz) : x(xx), y(yy), z(zz)	{}
+		//! Constructor from array
+		inline_					Point(const float f[3]) : x(f[X]), y(f[Y]), z(f[Z])		{}
+		//! Copy constructor
+		inline_					Point(const Point& p) : x(p.x), y(p.y), z(p.z)				{}
+		//! Destructor
+		inline_					~Point()													{}
+
+		//! Clears the vector
+		inline_	Point&			Zero()									{ x =			y =			z = 0.0f;			return *this;	}
+
+		//! + infinity
+		inline_	Point&			SetPlusInfinity()						{ x =			y =			z = MAX_FLOAT;		return *this;	}
+		//! - infinity
+		inline_	Point&			SetMinusInfinity()						{ x =			y =			z = MIN_FLOAT;		return *this;	}
+
+		//! Sets positive unit random vector
+				Point&			PositiveUnitRandomVector();
+		//! Sets unit random vector
+				Point&			UnitRandomVector();
+
+		//! Assignment from values
+		inline_	Point&			Set(float xx, float yy, float zz)		{ x  = xx;		y  = yy;	z  = zz;			return *this;	}
+		//! Assignment from array
+		inline_	Point&			Set(const float f[3])					{ x  = f[X];	y  = f[Y];	z  = f[Z];			return *this;	}
+		//! Assignment from another point
+		inline_	Point&			Set(const Point& src)					{ x  = src.x;	y  = src.y;	z  = src.z;			return *this;	}
+
+		//! Adds a vector
+		inline_	Point&			Add(const Point& p)						{ x += p.x;		y += p.y;	z += p.z;			return *this;	}
+		//! Adds a vector
+		inline_	Point&			Add(float xx, float yy, float zz)		{ x += xx;		y += yy;	z += zz;			return *this;	}
+		//! Adds a vector
+		inline_	Point&			Add(const float f[3])					{ x += f[X];	y += f[Y];	z += f[Z];			return *this;	}
+		//! Adds vectors
+		inline_	Point&			Add(const Point& p, const Point& q)		{ x = p.x+q.x;	y = p.y+q.y;	z = p.z+q.z;	return *this;	}
+
+		//! Subtracts a vector
+		inline_	Point&			Sub(const Point& p)						{ x -= p.x;		y -= p.y;	z -= p.z;			return *this;	}
+		//! Subtracts a vector
+		inline_	Point&			Sub(float xx, float yy, float zz)		{ x -= xx;		y -= yy;	z -= zz;			return *this;	}
+		//! Subtracts a vector
+		inline_	Point&			Sub(const float f[3])					{ x -= f[X];	y -= f[Y];	z -= f[Z];			return *this;	}
+		//! Subtracts vectors
+		inline_	Point&			Sub(const Point& p, const Point& q)		{ x = p.x-q.x;	y = p.y-q.y;	z = p.z-q.z;	return *this;	}
+
+		//! this = -this
+		inline_	Point&			Neg()									{ x = -x;		y = -y;			z = -z;			return *this;	}
+		//! this = -a
+		inline_	Point&			Neg(const Point& a)						{ x = -a.x;		y = -a.y;		z = -a.z;		return *this;	}
+
+		//! Multiplies by a scalar
+		inline_	Point&			Mult(float s)							{ x *= s;		y *= s;		z *= s;				return *this;	}
+
+		//! this = a * scalar
+		inline_	Point&			Mult(const Point& a, float scalar)
+								{
+									x = a.x * scalar;
+									y = a.y * scalar;
+									z = a.z * scalar;
+									return *this;
+								}
+
+		//! this = a + b * scalar
+		inline_	Point&			Mac(const Point& a, const Point& b, float scalar)
+								{
+									x = a.x + b.x * scalar;
+									y = a.y + b.y * scalar;
+									z = a.z + b.z * scalar;
+									return *this;
+								}
+
+		//! this = this + a * scalar
+		inline_	Point&			Mac(const Point& a, float scalar)
+								{
+									x += a.x * scalar;
+									y += a.y * scalar;
+									z += a.z * scalar;
+									return *this;
+								}
+
+		//! this = a - b * scalar
+		inline_	Point&			Msc(const Point& a, const Point& b, float scalar)
+								{
+									x = a.x - b.x * scalar;
+									y = a.y - b.y * scalar;
+									z = a.z - b.z * scalar;
+									return *this;
+								}
+
+		//! this = this - a * scalar
+		inline_	Point&			Msc(const Point& a, float scalar)
+								{
+									x -= a.x * scalar;
+									y -= a.y * scalar;
+									z -= a.z * scalar;
+									return *this;
+								}
+
+		//! this = a + b * scalarb + c * scalarc
+		inline_	Point&			Mac2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc)
+								{
+									x = a.x + b.x * scalarb + c.x * scalarc;
+									y = a.y + b.y * scalarb + c.y * scalarc;
+									z = a.z + b.z * scalarb + c.z * scalarc;
+									return *this;
+								}
+
+		//! this = a - b * scalarb - c * scalarc
+		inline_	Point&			Msc2(const Point& a, const Point& b, float scalarb, const Point& c, float scalarc)
+								{
+									x = a.x - b.x * scalarb - c.x * scalarc;
+									y = a.y - b.y * scalarb - c.y * scalarc;
+									z = a.z - b.z * scalarb - c.z * scalarc;
+									return *this;
+								}
+
+		//! this = mat * a
+		inline_	Point&			Mult(const Matrix3x3& mat, const Point& a);
+
+		//! this = mat1 * a1 + mat2 * a2
+		inline_	Point&			Mult2(const Matrix3x3& mat1, const Point& a1, const Matrix3x3& mat2, const Point& a2);
+
+		//! this = this + mat * a
+		inline_	Point&			Mac(const Matrix3x3& mat, const Point& a);
+
+		//! this = transpose(mat) * a
+		inline_	Point&			TransMult(const Matrix3x3& mat, const Point& a);
+
+		//! Linear interpolate between two vectors: this = a + t * (b - a)
+		inline_	Point&			Lerp(const Point& a, const Point& b, float t)
+								{
+									x = a.x + t * (b.x - a.x);
+									y = a.y + t * (b.y - a.y);
+									z = a.z + t * (b.z - a.z);
+									return *this;
+								}
+
+		//! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2.
+		//! this =	p0 * (2t^2 - t^3 - t)/2
+		//!			+ p1 * (3t^3 - 5t^2 + 2)/2
+		//!			+ p2 * (4t^2 - 3t^3 + t)/2
+		//!			+ p3 * (t^3 - t^2)/2
+		inline_	Point&			Herp(const Point& p0, const Point& p1, const Point& p2, const Point& p3, float t)
+								{
+									float t2 = t * t;
+									float t3 = t2 * t;
+									float kp0 = (2.0f * t2 - t3 - t) * 0.5f;
+									float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f;
+									float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f;
+									float kp3 = (t3 - t2) * 0.5f;
+									x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3;
+									y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3;
+									z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3;
+									return *this;
+								}
+
+		//! this = rotpos * r + linpos
+		inline_	Point&			Transform(const Point& r, const Matrix3x3& rotpos, const Point& linpos);
+
+		//! this = trans(rotpos) * (r - linpos)
+		inline_	Point&			InvTransform(const Point& r, const Matrix3x3& rotpos, const Point& linpos);
+
+		//! Returns MIN(x, y, z);
+		inline_	float			Min()				const		{ return MIN(x, MIN(y, z));												}
+		//! Returns MAX(x, y, z);
+		inline_	float			Max()				const		{ return MAX(x, MAX(y, z));												}
+		//! Sets each element to be componentwise minimum
+		inline_	Point&			Min(const Point& p)				{ x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z);	return *this;	}
+		//! Sets each element to be componentwise maximum
+		inline_	Point&			Max(const Point& p)				{ x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z);	return *this;	}
+
+		//! Clamps each element
+		inline_	Point&			Clamp(float min, float max)
+								{
+									if(x<min)	x=min;	if(x>max)	x=max;
+									if(y<min)	y=min;	if(y>max)	y=max;
+									if(z<min)	z=min;	if(z>max)	z=max;
+									return *this;
+								}
+
+		//! Computes square magnitude
+		inline_	float			SquareMagnitude()	const		{ return x*x + y*y + z*z;												}
+		//! Computes magnitude
+		inline_	float			Magnitude()			const		{ return sqrtf(x*x + y*y + z*z);										}
+		//! Computes volume
+		inline_	float			Volume()			const		{ return x * y * z;														}
+
+		//! Checks the point is near zero
+		inline_	bool			ApproxZero()		const		{ return SquareMagnitude() < EPSILON2;									}
+
+		//! Tests for exact zero vector
+		inline_	BOOL			IsZero()			const
+								{
+									if(IR(x) || IR(y) || IR(z))	return FALSE;
+									return TRUE;
+								}
+
+		//! Checks point validity
+		inline_	BOOL			IsValid()			const
+								{
+									if(!IsValidFloat(x))	return FALSE;
+									if(!IsValidFloat(y))	return FALSE;
+									if(!IsValidFloat(z))	return FALSE;
+									return TRUE;
+								}
+
+		//! Slighty moves the point
+				void			Tweak(udword coord_mask, udword tweak_mask)
+								{
+									if(coord_mask&1)	{ udword Dummy = IR(x);	Dummy^=tweak_mask;	x = FR(Dummy); }
+									if(coord_mask&2)	{ udword Dummy = IR(y);	Dummy^=tweak_mask;	y = FR(Dummy); }
+									if(coord_mask&4)	{ udword Dummy = IR(z);	Dummy^=tweak_mask;	z = FR(Dummy); }
+								}
+
+		#define TWEAKMASK		0x3fffff
+		#define TWEAKNOTMASK	~TWEAKMASK
+		//! Slighty moves the point out
+		inline_	void			TweakBigger()
+								{
+									udword	Dummy = (IR(x)&TWEAKNOTMASK);	if(!IS_NEGATIVE_FLOAT(x))	Dummy+=TWEAKMASK+1;	x = FR(Dummy);
+											Dummy = (IR(y)&TWEAKNOTMASK);	if(!IS_NEGATIVE_FLOAT(y))	Dummy+=TWEAKMASK+1;	y = FR(Dummy);
+											Dummy = (IR(z)&TWEAKNOTMASK);	if(!IS_NEGATIVE_FLOAT(z))	Dummy+=TWEAKMASK+1;	z = FR(Dummy);
+								}
+
+		//! Slighty moves the point in
+		inline_	void			TweakSmaller()
+								{
+									udword	Dummy = (IR(x)&TWEAKNOTMASK);	if(IS_NEGATIVE_FLOAT(x))	Dummy+=TWEAKMASK+1;	x = FR(Dummy);
+											Dummy = (IR(y)&TWEAKNOTMASK);	if(IS_NEGATIVE_FLOAT(y))	Dummy+=TWEAKMASK+1;	y = FR(Dummy);
+											Dummy = (IR(z)&TWEAKNOTMASK);	if(IS_NEGATIVE_FLOAT(z))	Dummy+=TWEAKMASK+1;	z = FR(Dummy);
+								}
+
+		//! Normalizes the vector
+		inline_	Point&			Normalize()
+								{
+									float M = x*x + y*y + z*z;
+									if(M)
+									{
+										M = 1.0f / sqrtf(M);
+										x *= M;
+										y *= M;
+										z *= M;
+									}
+									return *this;
+								}
+
+		//! Sets vector length
+		inline_	Point&			SetLength(float length)
+								{
+									float NewLength = length / Magnitude();
+									x *= NewLength;
+									y *= NewLength;
+									z *= NewLength;
+									return *this;
+								}
+
+		//! Clamps vector length
+		inline_	Point&			ClampLength(float limit_length)
+								{
+									if(limit_length>=0.0f)	// Magnitude must be positive
+									{
+										float CurrentSquareLength = SquareMagnitude();
+
+										if(CurrentSquareLength > limit_length * limit_length)
+										{
+											float Coeff = limit_length / sqrtf(CurrentSquareLength);
+											x *= Coeff;
+											y *= Coeff;
+											z *= Coeff;
+										}
+									}
+									return *this;
+								}
+
+		//! Computes distance to another point
+		inline_	float			Distance(const Point& b)			const
+								{
+									return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z));
+								}
+
+		//! Computes square distance to another point
+		inline_	float			SquareDistance(const Point& b)		const
+								{
+									return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z));
+								}
+
+		//! Dot product dp = this|a
+		inline_	float			Dot(const Point& p)					const		{	return p.x * x + p.y * y + p.z * z;				}
+
+		//! Cross product this = a x b
+		inline_	Point&			Cross(const Point& a, const Point& b)
+								{
+									x = a.y * b.z - a.z * b.y;
+									y = a.z * b.x - a.x * b.z;
+									z = a.x * b.y - a.y * b.x;
+									return *this;
+								}
+
+		//! Vector code ( bitmask = sign(z) | sign(y) | sign(x) )
+		inline_	udword			VectorCode()						const
+								{
+									return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29);
+								}
+
+		//! Returns largest axis
+		inline_	PointComponent	LargestAxis()						const
+								{
+									const float* Vals = &x;
+									PointComponent m = X;
+									if(Vals[Y] > Vals[m]) m = Y;
+									if(Vals[Z] > Vals[m]) m = Z;
+									return m;
+								}
+
+		//! Returns closest axis
+		inline_	PointComponent	ClosestAxis()						const
+								{
+									const float* Vals = &x;
+									PointComponent m = X;
+									if(AIR(Vals[Y]) > AIR(Vals[m])) m = Y;
+									if(AIR(Vals[Z]) > AIR(Vals[m])) m = Z;
+									return m;
+								}
+
+		//! Returns smallest axis
+		inline_	PointComponent	SmallestAxis()						const
+								{
+									const float* Vals = &x;
+									PointComponent m = X;
+									if(Vals[Y] < Vals[m]) m = Y;
+									if(Vals[Z] < Vals[m]) m = Z;
+									return m;
+								}
+
+		//! Refracts the point
+				Point&			Refract(const Point& eye, const Point& n, float refractindex, Point& refracted);
+
+		//! Projects the point onto a plane
+				Point&			ProjectToPlane(const Plane& p);
+
+		//! Projects the point onto the screen
+				void			ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const;
+
+		//! Unfolds the point onto a plane according to edge(a,b)
+				Point&			Unfold(Plane& p, Point& a, Point& b);
+
+		//! Hash function from Ville Miettinen
+		inline_	udword			GetHashValue()						const
+								{
+									const udword* h = (const udword*)(this);
+									udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff;	// avoid problems with +-0
+									return (f>>22)^(f>>12)^(f);
+								}
+
+		//! Stuff magic values in the point, marking it as explicitely not used.
+				void			SetNotUsed();
+		//! Checks the point is marked as not used
+				BOOL			IsNotUsed()							const;
+
+		// Arithmetic operators
+
+		//! Unary operator for Point Negate = - Point
+		inline_	Point			operator-()							const		{ return Point(-x, -y, -z);							}
+
+		//! Operator for Point Plus = Point + Point.
+		inline_	Point			operator+(const Point& p)			const		{ return Point(x + p.x, y + p.y, z + p.z);			}
+		//! Operator for Point Minus = Point - Point.
+		inline_	Point			operator-(const Point& p)			const		{ return Point(x - p.x, y - p.y, z - p.z);			}
+
+		//! Operator for Point Mul   = Point * Point.
+		inline_	Point			operator*(const Point& p)			const		{ return Point(x * p.x, y * p.y, z * p.z);			}
+		//! Operator for Point Scale = Point * float.
+		inline_	Point			operator*(float s)					const		{ return Point(x * s,   y * s,   z * s );			}
+		//! Operator for Point Scale = float * Point.
+		inline_ friend	Point	operator*(float s, const Point& p)				{ return Point(s * p.x, s * p.y, s * p.z);			}
+
+		//! Operator for Point Div   = Point / Point.
+		inline_	Point			operator/(const Point& p)			const		{ return Point(x / p.x, y / p.y, z / p.z);			}
+		//! Operator for Point Scale = Point / float.
+		inline_	Point			operator/(float s)					const		{ s = 1.0f / s; return Point(x * s, y * s, z * s);	}
+		//! Operator for Point Scale = float / Point.
+		inline_	friend	Point	operator/(float s, const Point& p)				{ return Point(s / p.x, s / p.y, s / p.z);			}
+
+		//! Operator for float DotProd = Point | Point.
+		inline_	float			operator|(const Point& p)			const		{ return x*p.x + y*p.y + z*p.z;						}
+		//! Operator for Point VecProd = Point ^ Point.
+		inline_	Point			operator^(const Point& p)			const
+								{
+									return Point(
+									y * p.z - z * p.y,
+									z * p.x - x * p.z,
+									x * p.y - y * p.x );
+								}
+
+		//! Operator for Point += Point.
+		inline_	Point&			operator+=(const Point& p)						{ x += p.x; y += p.y; z += p.z;	return *this;		}
+		//! Operator for Point += float.
+		inline_	Point&			operator+=(float s)								{ x += s;   y += s;   z += s;	return *this;		}
+
+		//! Operator for Point -= Point.
+		inline_	Point&			operator-=(const Point& p)						{ x -= p.x; y -= p.y; z -= p.z;	return *this;		}
+		//! Operator for Point -= float.
+		inline_	Point&			operator-=(float s)								{ x -= s;   y -= s;   z -= s;	return *this;		}
+
+		//! Operator for Point *= Point.
+		inline_	Point&			operator*=(const Point& p)						{ x *= p.x; y *= p.y; z *= p.z;	return *this;		}
+		//! Operator for Point *= float.
+		inline_	Point&			operator*=(float s)								{ x *= s; y *= s; z *= s;		return *this;		}
+
+		//! Operator for Point /= Point.
+		inline_	Point&			operator/=(const Point& p)						{ x /= p.x; y /= p.y; z /= p.z;	return *this;		}
+		//! Operator for Point /= float.
+		inline_	Point&			operator/=(float s)								{ s = 1.0f/s; x *= s; y *= s; z *= s; return *this; }
+
+		// Logical operators
+
+		//! Operator for "if(Point==Point)"
+		inline_	bool			operator==(const Point& p)			const		{ return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z)));	}
+		//! Operator for "if(Point!=Point)"
+		inline_	bool			operator!=(const Point& p)			const		{ return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z)));	}
+
+		// Arithmetic operators
+
+		//! Operator for Point Mul = Point * Matrix3x3.
+		inline_	Point			operator*(const Matrix3x3& mat)		const
+								{
+									class ShadowMatrix3x3{ public: float m[3][3]; };	// To allow inlining
+									const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat;
+
+									return Point(
+									x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0],
+									x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1],
+									x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] );
+								}
+
+		//! Operator for Point Mul = Point * Matrix4x4.
+		inline_	Point			operator*(const Matrix4x4& mat)		const
+								{
+									class ShadowMatrix4x4{ public: float m[4][4]; };	// To allow inlining
+									const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat;
+
+									return Point(
+									x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0],
+									x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1],
+									x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]);
+								}
+
+		//! Operator for Point *= Matrix3x3.
+		inline_	Point&			operator*=(const Matrix3x3& mat)
+								{
+									class ShadowMatrix3x3{ public: float m[3][3]; };	// To allow inlining
+									const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat;
+
+									float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0];
+									float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1];
+									float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2];
+
+									x = xp;	y = yp;	z = zp;
+
+									return *this;
+								}
+
+		//! Operator for Point *= Matrix4x4.
+		inline_	Point&			operator*=(const Matrix4x4& mat)
+								{
+									class ShadowMatrix4x4{ public: float m[4][4]; };	// To allow inlining
+									const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat;
+
+									float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0];
+									float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1];
+									float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2];
+
+									x = xp;	y = yp;	z = zp;
+
+									return *this;
+								}
+
+		// Cast operators
+
+		//! Cast a Point to a HPoint. w is set to zero.
+								operator	HPoint()				const;
+
+		inline_					operator	const	float*() const	{ return &x; }
+		inline_					operator			float*()		{ return &x; }
+
+		public:
+				float			x, y, z;
+	};
+
+	FUNCTION ICEMATHS_API void Normalize1(Point& a);
+	FUNCTION ICEMATHS_API void Normalize2(Point& a);
+
+#endif //__ICEPOINT_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IcePreprocessor.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IcePreprocessor.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IcePreprocessor.h	(revision 216)
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains preprocessor stuff. This should be the first included header.
+ *	\file		IcePreprocessor.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEPREPROCESSOR_H__
+#define __ICEPREPROCESSOR_H__
+
+	// Check platform
+	#if defined( _WIN32 ) || defined( WIN32 )
+		// #pragma message("Compiling on Windows...")
+		#define PLATFORM_WINDOWS
+	#else
+		// don't issue pragmas on unknown platforms
+		// #pragma message("Compiling on unknown platform...")
+	#endif
+
+	// Check compiler
+	#if defined(_MSC_VER)
+		// #pragma message("Compiling with VC++...")
+		#define COMPILER_VISUAL_CPP
+	#else
+		// don't issue pragmas on unknown platforms
+		// #pragma message("Compiling with unknown compiler...")
+	#endif
+
+	// Check compiler options. If this file is included in user-apps, this
+	// shouldn't be needed, so that they can use what they like best.
+	#ifndef ICE_DONT_CHECK_COMPILER_OPTIONS
+		#ifdef COMPILER_VISUAL_CPP
+			#if defined(_CHAR_UNSIGNED)
+			#endif
+
+			#if defined(_CPPRTTI)
+				#error Please disable RTTI...
+			#endif
+
+			#if defined(_CPPUNWIND)
+				#error Please disable exceptions...
+			#endif
+
+			#if defined(_MT)
+				// Multithreading
+			#endif
+		#endif
+	#endif
+
+	// Check debug mode
+	#ifdef	DEBUG			// May be defined instead of _DEBUG. Let's fix it.
+		#ifndef	_DEBUG
+			#define _DEBUG
+		#endif
+	#endif
+
+	#ifdef  _DEBUG
+	// Here you may define items for debug builds
+	#endif
+
+	#ifndef THIS_FILE
+		#define THIS_FILE			__FILE__
+	#endif
+
+	#ifndef ICE_NO_DLL
+		#ifdef ICECORE_EXPORTS
+			#define ICECORE_API			__declspec(dllexport)
+		#else
+			#define ICECORE_API			__declspec(dllimport)
+		#endif
+	#else
+			#define ICECORE_API
+	#endif
+
+	// Don't override new/delete
+//	#define DEFAULT_NEWDELETE
+	#define DONT_TRACK_MEMORY_LEAKS
+
+	#define FUNCTION				extern "C"
+
+	// Cosmetic stuff [mainly useful with multiple inheritance]
+	#define	override(base_class)	virtual
+
+	// Our own inline keyword, so that:
+	// - we can switch to __forceinline to check it's really better or not
+	// - we can remove __forceinline if the compiler doesn't support it
+//	#define inline_				__forceinline
+//	#define inline_				inline
+
+	// Contributed by Bruce Mitchener
+		#if defined(COMPILER_VISUAL_CPP)
+			#define inline_			__forceinline
+//			#define inline_			inline
+		#elif defined(__GNUC__) && __GNUC__ < 3
+			#define inline_ inline
+		#elif defined(__GNUC__)
+			#define inline_ inline __attribute__ ((always_inline))
+		#else
+			#define inline_ inline
+		#endif
+
+	// Down the hatch
+#ifdef _MSC_VER
+	#pragma inline_depth( 255 )
+#endif
+
+	#ifdef COMPILER_VISUAL_CPP
+		#pragma intrinsic(memcmp)
+		#pragma intrinsic(memcpy)
+		#pragma intrinsic(memset)
+		#pragma intrinsic(strcat)
+		#pragma intrinsic(strcmp)
+		#pragma intrinsic(strcpy)
+		#pragma intrinsic(strlen)
+		#pragma intrinsic(abs)
+		#pragma intrinsic(labs)
+	#endif
+
+	// ANSI compliance
+	#ifdef  _DEBUG
+		// Remove painful warning in debug
+		inline_ bool __False__(){ return false; }
+		#define for if(__False__()){}	else for
+	#else
+		#define for if(0){}	else for
+	#endif
+
+#endif // __ICEPREPROCESSOR_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceRandom.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceRandom.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceRandom.cpp	(revision 216)
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for random generators.
+ *	\file		IceRandom.cpp
+ *	\author		Pierre Terdiman
+ *	\date		August, 9, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceCore;
+
+void IceCore::	SRand(udword seed)
+{
+	srand(seed);
+}
+
+udword IceCore::Rand()
+{
+	return rand();
+}
+
+
+static BasicRandom gRandomGenerator(42);
+
+udword IceCore::GetRandomIndex(udword max_index)
+{
+	// We don't use rand() since it's limited to RAND_MAX
+	udword Index = gRandomGenerator.Randomize();
+	return Index % max_index;
+}
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceRandom.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceRandom.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceRandom.h	(revision 216)
@@ -0,0 +1,42 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for random generators.
+ *	\file		IceRandom.h
+ *	\author		Pierre Terdiman
+ *	\date		August, 9, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICERANDOM_H__
+#define __ICERANDOM_H__
+
+	FUNCTION ICECORE_API	void	SRand(udword seed);
+	FUNCTION ICECORE_API	udword	Rand();
+
+	//! Returns a unit random floating-point value
+	inline_ float UnitRandomFloat()	{ return float(Rand()) * ONE_OVER_RAND_MAX;	}
+
+	//! Returns a random index so that 0<= index < max_index
+	ICECORE_API	udword GetRandomIndex(udword max_index);
+
+	class ICECORE_API BasicRandom
+	{
+		public:
+
+		//! Constructor
+		inline_				BasicRandom(udword seed=0)	: mRnd(seed)	{}
+		//! Destructor
+		inline_				~BasicRandom()								{}
+
+		inline_	void		SetSeed(udword seed)		{ mRnd = seed;											}
+		inline_	udword		GetCurrentValue()	const	{ return mRnd;											}
+		inline_	udword		Randomize()					{ mRnd = mRnd * 2147001325 + 715136305; return mRnd;	}
+
+		private:
+				udword		mRnd;
+	};
+
+#endif // __ICERANDOM_H__
+
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceRay.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceRay.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceRay.cpp	(revision 216)
@@ -0,0 +1,84 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for rays.
+ *	\file		IceRay.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Ray class.
+ *	A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity
+ *	\class		Ray
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+	O = Origin = impact point
+	i = normalized vector along the x axis
+	j = normalized vector along the y axis = actually the normal vector in O
+	D = Direction vector, norm |D| = 1
+	N = Projection of D on y axis, norm |N| = normal reaction
+	T = Projection of D on x axis, norm |T| = tangential reaction
+	R = Reflexion vector
+
+              ^y
+              |
+              |
+              |
+       _  _  _| _ _ _
+       *      *      *|
+        \     |     /
+         \    |N   /  |
+         R\   |   /D
+           \  |  /    |
+            \ | /
+    _________\|/______*_______>x
+               O    T
+
+	Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized.
+
+	j|D = |j|*|D|*cos(theta) => |N| = j|D
+
+	Then we simply have:
+
+	D = N + T
+
+	To compute tangential reaction :
+
+	T = D - N
+
+	To compute reflexion vector :
+
+	R = N - T = N - (D-N) = 2*N - D
+*/
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+float Ray::SquareDistance(const Point& point, float* t)	const
+{
+	Point Diff = point - mOrig;
+	float fT = Diff | mDir;
+
+	if(fT<=0.0f)
+	{
+		fT = 0.0f;
+	}
+	else
+	{
+		fT /= mDir.SquareMagnitude();
+		Diff -= fT*mDir;
+	}
+
+	if(t) *t = fT;
+
+	return Diff.SquareMagnitude();
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceRay.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceRay.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceRay.h	(revision 216)
@@ -0,0 +1,98 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for rays.
+ *	\file		IceRay.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICERAY_H__
+#define __ICERAY_H__
+
+	class ICEMATHS_API Ray
+	{
+		public:
+		//! Constructor
+		inline_					Ray()																{}
+		//! Constructor
+		inline_					Ray(const Point& orig, const Point& dir) : mOrig(orig), mDir(dir)	{}
+		//! Copy constructor
+		inline_					Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir)				{}
+		//! Destructor
+		inline_					~Ray()																{}
+
+						float	SquareDistance(const Point& point, float* t=null)	const;
+		inline_			float	Distance(const Point& point, float* t=null)			const			{ return sqrtf(SquareDistance(point, t));	}
+
+						Point	mOrig;		//!< Ray origin
+						Point	mDir;		//!< Normalized direction
+	};
+
+	inline_ void ComputeReflexionVector(Point& reflected, const Point& incoming_dir, const Point& outward_normal)
+	{
+		reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal);
+	}
+
+	inline_ void ComputeReflexionVector(Point& reflected, const Point& source, const Point& impact, const Point& normal)
+	{
+		Point V = impact - source;
+		reflected = V - normal * 2.0f * (V|normal);
+	}
+
+	inline_ void DecomposeVector(Point& normal_compo, Point& tangent_compo, const Point& outward_dir, const Point& outward_normal)
+	{
+		normal_compo = outward_normal * (outward_dir|outward_normal);
+		tangent_compo = outward_dir - normal_compo;
+	}
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	Transforms a direction vector from world space to local space
+	 *	\param		local_dir	[out] direction vector in local space
+	 *	\param		world_dir	[in] direction vector in world space
+	 *	\param		world		[in] world transform
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	inline_ void ComputeLocalDirection(Point& local_dir, const Point& world_dir, const Matrix4x4& world)
+	{
+		// Get world direction back in local space
+//		Matrix3x3 InvWorld = world;
+//		local_dir = InvWorld * world_dir;
+		local_dir = Matrix3x3(world) * world_dir;
+	}
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	Transforms a position vector from world space to local space
+	 *	\param		local_pt	[out] position vector in local space
+	 *	\param		world_pt	[in] position vector in world space
+	 *	\param		world		[in] world transform
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	inline_ void ComputeLocalPoint(Point& local_pt, const Point& world_pt, const Matrix4x4& world)
+	{
+		// Get world vertex back in local space
+		Matrix4x4 InvWorld = world;
+		InvWorld.Invert();
+		local_pt = world_pt * InvWorld;
+	}
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	Transforms a ray from world space to local space
+	 *	\param		local_ray	[out] ray in local space
+	 *	\param		world_ray	[in] ray in world space
+	 *	\param		world		[in] world transform
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world)
+	{
+		// Get world ray back in local space
+		ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world);
+		ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world);
+	}
+
+#endif // __ICERAY_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceRevisitedRadix.cpp	(revision 216)
@@ -0,0 +1,520 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains source code from the article "Radix Sort Revisited".
+ *	\file		IceRevisitedRadix.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Revisited Radix Sort.
+ *	This is my new radix routine:
+ *  - it uses indices and doesn't recopy the values anymore, hence wasting less ram
+ *  - it creates all the histograms in one run instead of four
+ *  - it sorts words faster than dwords and bytes faster than words
+ *  - it correctly sorts negative floating-point values by patching the offsets
+ *  - it automatically takes advantage of temporal coherence
+ *  - multiple keys support is a side effect of temporal coherence
+ *  - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway]
+ *
+ *	History:
+ *	- 08.15.98: very first version
+ *	- 04.04.00: recoded for the radix article
+ *	- 12.xx.00: code lifting
+ *	- 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here)
+ *	- 10.11.01: added local ram support
+ *	- 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting......
+ *	- 01.02.02:	- "mIndices" renamed => "mRanks". That's a rank sorter after all.
+ *				- ranks are not "reset" anymore, but implicit on first calls
+ *	- 07.05.02:	- offsets rewritten with one less indirection.
+ *	- 11.03.02:	- "bool" replaced with RadixHint enum
+ *
+ *	\class		RadixSort
+ *	\author		Pierre Terdiman
+ *	\version	1.4
+ *	\date		August, 15, 1998
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+To do:
+	- add an offset parameter between two input values (avoid some data recopy sometimes)
+	- unroll ? asm ?
+	- 11 bits trick & 3 passes as Michael did
+	- prefetch stuff the day I have a P3
+	- make a version with 16-bits indices ?
+*/
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceCore;
+
+#define INVALIDATE_RANKS	mCurrentSize|=0x80000000
+#define VALIDATE_RANKS		mCurrentSize&=0x7fffffff
+#define CURRENT_SIZE		(mCurrentSize&0x7fffffff)
+#define INVALID_RANKS		(mCurrentSize&0x80000000)
+
+#define CHECK_RESIZE(n)																		\
+	if(n!=mPreviousSize)																	\
+	{																						\
+				if(n>mCurrentSize)	Resize(n);												\
+		else						ResetRanks();											\
+		mPreviousSize = n;																	\
+	}
+
+#define CREATE_HISTOGRAMS(type, buffer)														\
+	/* Clear counters/histograms */															\
+	ZeroMemory(mHistogram, 256*4*sizeof(udword));											\
+																							\
+	/* Prepare to count */																	\
+	ubyte* p = (ubyte*)input;																\
+	ubyte* pe = &p[nb*4];																	\
+	udword* h0= &mHistogram[0];		/* Histogram for first pass (LSB)	*/					\
+	udword* h1= &mHistogram[256];	/* Histogram for second pass		*/					\
+	udword* h2= &mHistogram[512];	/* Histogram for third pass			*/					\
+	udword* h3= &mHistogram[768];	/* Histogram for last pass (MSB)	*/					\
+																							\
+	bool AlreadySorted = true;	/* Optimism... */											\
+																							\
+	if(INVALID_RANKS)																		\
+	{																						\
+		/* Prepare for temporal coherence */												\
+		type* Running = (type*)buffer;														\
+		type PrevVal = *Running;															\
+																							\
+		while(p!=pe)																		\
+		{																					\
+			/* Read input buffer in previous sorted order */								\
+			type Val = *Running++;															\
+			/* Check whether already sorted or not */										\
+			if(Val<PrevVal)	{ AlreadySorted = false; break; } /* Early out */				\
+			/* Update for next iteration */													\
+			PrevVal = Val;																	\
+																							\
+			/* Create histograms */															\
+			h0[*p++]++;	h1[*p++]++;	h2[*p++]++;	h3[*p++]++;									\
+		}																					\
+																							\
+		/* If all input values are already sorted, we just have to return and leave the */	\
+		/* previous list unchanged. That way the routine may take advantage of temporal */	\
+		/* coherence, for example when used to sort transparent faces.					*/	\
+		if(AlreadySorted)																	\
+		{																					\
+			mNbHits++;																		\
+			for(udword i=0;i<nb;i++)	mRanks[i] = i;										\
+			return *this;																	\
+		}																					\
+	}																						\
+	else																					\
+	{																						\
+		/* Prepare for temporal coherence */												\
+		udword* Indices = mRanks;															\
+		type PrevVal = (type)buffer[*Indices];												\
+																							\
+		while(p!=pe)																		\
+		{																					\
+			/* Read input buffer in previous sorted order */								\
+			type Val = (type)buffer[*Indices++];											\
+			/* Check whether already sorted or not */										\
+			if(Val<PrevVal)	{ AlreadySorted = false; break; } /* Early out */				\
+			/* Update for next iteration */													\
+			PrevVal = Val;																	\
+																							\
+			/* Create histograms */															\
+			h0[*p++]++;	h1[*p++]++;	h2[*p++]++;	h3[*p++]++;									\
+		}																					\
+																							\
+		/* If all input values are already sorted, we just have to return and leave the */	\
+		/* previous list unchanged. That way the routine may take advantage of temporal */	\
+		/* coherence, for example when used to sort transparent faces.					*/	\
+		if(AlreadySorted)	{ mNbHits++; return *this;	}									\
+	}																						\
+																							\
+	/* Else there has been an early out and we must finish computing the histograms */		\
+	while(p!=pe)																			\
+	{																						\
+		/* Create histograms without the previous overhead */								\
+		h0[*p++]++;	h1[*p++]++;	h2[*p++]++;	h3[*p++]++;										\
+	}
+
+#define CHECK_PASS_VALIDITY(pass)															\
+	/* Shortcut to current counters */														\
+	udword* CurCount = &mHistogram[pass<<8];												\
+																							\
+	/* Reset flag. The sorting pass is supposed to be performed. (default) */				\
+	bool PerformPass = true;																\
+																							\
+	/* Check pass validity */																\
+																							\
+	/* If all values have the same byte, sorting is useless. */								\
+	/* It may happen when sorting bytes or words instead of dwords. */						\
+	/* This routine actually sorts words faster than dwords, and bytes */					\
+	/* faster than words. Standard running time (O(4*n))is reduced to O(2*n) */				\
+	/* for words and O(n) for bytes. Running time for floats depends on actual values... */	\
+																							\
+	/* Get first byte */																	\
+	ubyte UniqueVal = *(((ubyte*)input)+pass);												\
+																							\
+	/* Check that byte's counter */															\
+	if(CurCount[UniqueVal]==nb)	PerformPass=false;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+RadixSort::RadixSort() : mRanks(null), mRanks2(null), mCurrentSize(0), mTotalCalls(0), mNbHits(0)
+{
+#ifndef RADIX_LOCAL_RAM
+	// Allocate input-independent ram
+	mHistogram	= new udword[256*4];
+	mOffset		= new udword[256];
+#endif
+	// Initialize indices
+	INVALIDATE_RANKS;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+RadixSort::~RadixSort()
+{
+	// Release everything
+#ifndef RADIX_LOCAL_RAM
+	DELETEARRAY(mOffset);
+	DELETEARRAY(mHistogram);
+#endif
+	DELETEARRAY(mRanks2);
+	DELETEARRAY(mRanks);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Resizes the inner lists.
+ *	\param		nb	[in] new size (number of dwords)
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool RadixSort::Resize(udword nb)
+{
+	// Free previously used ram
+	DELETEARRAY(mRanks2);
+	DELETEARRAY(mRanks);
+
+	// Get some fresh one
+	mRanks	= new udword[nb];	CHECKALLOC(mRanks);
+	mRanks2	= new udword[nb];	CHECKALLOC(mRanks2);
+
+	return true;
+}
+
+inline_ void RadixSort::CheckResize(udword nb)
+{
+	udword CurSize = CURRENT_SIZE;
+	if(nb!=CurSize)
+	{
+		if(nb>CurSize)	Resize(nb);
+		mCurrentSize = nb;
+		INVALIDATE_RANKS;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Main sort routine.
+ *	This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data.
+ *	\param		input	[in] a list of integer values to sort
+ *	\param		nb		[in] number of values to sort, must be < 2^31
+ *	\param		hint	[in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values
+ *	\return		Self-Reference
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint)
+{
+	// Checkings
+	if(!input || !nb || nb&0x80000000)	return *this;
+
+	// Stats
+	mTotalCalls++;
+
+	// Resize lists if needed
+	CheckResize(nb);
+
+#ifdef RADIX_LOCAL_RAM
+	// Allocate histograms & offsets on the stack
+	udword mHistogram[256*4];
+//	udword mOffset[256];
+	udword* mLink[256];
+#endif
+
+	// Create histograms (counters). Counters for all passes are created in one run.
+	// Pros:	read input buffer once instead of four times
+	// Cons:	mHistogram is 4Kb instead of 1Kb
+	// We must take care of signed/unsigned values for temporal coherence.... I just
+	// have 2 code paths even if just a single opcode changes. Self-modifying code, someone?
+	if(hint==RADIX_UNSIGNED)	{ CREATE_HISTOGRAMS(udword, input);	}
+	else						{ CREATE_HISTOGRAMS(sdword, input);	}
+
+	// Compute #negative values involved if needed
+	udword NbNegativeValues = 0;
+	if(hint==RADIX_SIGNED)
+	{
+		// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
+		// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
+		// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
+		udword* h3= &mHistogram[768];
+		for(udword i=128;i<256;i++)	NbNegativeValues += h3[i];	// 768 for last histogram, 128 for negative part
+	}
+
+	// Radix sort, j is the pass number (0=LSB, 3=MSB)
+	for(udword j=0;j<4;j++)
+	{
+		CHECK_PASS_VALIDITY(j);
+
+		// Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is
+		// not a problem, numbers are correctly sorted anyway.
+		if(PerformPass)
+		{
+			// Should we care about negative values?
+			if(j!=3 || hint==RADIX_UNSIGNED)
+			{
+				// Here we deal with positive values only
+
+				// Create offsets
+//				mOffset[0] = 0;
+//				for(udword i=1;i<256;i++)		mOffset[i] = mOffset[i-1] + CurCount[i-1];
+				mLink[0] = mRanks2;
+				for(udword i=1;i<256;i++)		mLink[i] = mLink[i-1] + CurCount[i-1];
+			}
+			else
+			{
+				// This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place.
+
+				// Create biased offsets, in order for negative numbers to be sorted as well
+//				mOffset[0] = NbNegativeValues;												// First positive number takes place after the negative ones
+				mLink[0] = &mRanks2[NbNegativeValues];										// First positive number takes place after the negative ones
+//				for(udword i=1;i<128;i++)		mOffset[i] = mOffset[i-1] + CurCount[i-1];	// 1 to 128 for positive numbers
+				for(udword i=1;i<128;i++)		mLink[i] = mLink[i-1] + CurCount[i-1];		// 1 to 128 for positive numbers
+
+				// Fixing the wrong place for negative values
+//				mOffset[128] = 0;
+				mLink[128] = mRanks2;
+//				for(i=129;i<256;i++)			mOffset[i] = mOffset[i-1] + CurCount[i-1];
+				for(udword i=129;i<256;i++)		mLink[i] = mLink[i-1] + CurCount[i-1];
+			}
+
+			// Perform Radix Sort
+			ubyte* InputBytes	= (ubyte*)input;
+			InputBytes += j;
+			if(INVALID_RANKS)
+			{
+//				for(udword i=0;i<nb;i++)	mRanks2[mOffset[InputBytes[i<<2]]++] = i;
+				for(udword i=0;i<nb;i++)	*mLink[InputBytes[i<<2]]++ = i;
+				VALIDATE_RANKS;
+			}
+			else
+			{
+				udword* Indices		= mRanks;
+				udword* IndicesEnd	= &mRanks[nb];
+				while(Indices!=IndicesEnd)
+				{
+					udword id = *Indices++;
+//					mRanks2[mOffset[InputBytes[id<<2]]++] = id;
+					*mLink[InputBytes[id<<2]]++ = id;
+				}
+			}
+
+			// Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
+			udword* Tmp	= mRanks;	mRanks = mRanks2; mRanks2 = Tmp;
+		}
+	}
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Main sort routine.
+ *	This one is for floating-point values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data.
+ *	\param		input			[in] a list of floating-point values to sort
+ *	\param		nb				[in] number of values to sort, must be < 2^31
+ *	\return		Self-Reference
+ *	\warning	only sorts IEEE floating-point values
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+RadixSort& RadixSort::Sort(const float* input2, udword nb)
+{
+	// Checkings
+	if(!input2 || !nb || nb&0x80000000)	return *this;
+
+	// Stats
+	mTotalCalls++;
+
+	udword* input = (udword*)input2;
+
+	// Resize lists if needed
+	CheckResize(nb);
+
+#ifdef RADIX_LOCAL_RAM
+	// Allocate histograms & offsets on the stack
+	udword mHistogram[256*4];
+//	udword mOffset[256];
+	udword* mLink[256];
+#endif
+
+	// Create histograms (counters). Counters for all passes are created in one run.
+	// Pros:	read input buffer once instead of four times
+	// Cons:	mHistogram is 4Kb instead of 1Kb
+	// Floating-point values are always supposed to be signed values, so there's only one code path there.
+	// Please note the floating point comparison needed for temporal coherence! Although the resulting asm code
+	// is dreadful, this is surprisingly not such a performance hit - well, I suppose that's a big one on first
+	// generation Pentiums....We can't make comparison on integer representations because, as Chris said, it just
+	// wouldn't work with mixed positive/negative values....
+	{ CREATE_HISTOGRAMS(float, input2); }
+
+	// Compute #negative values involved if needed
+	udword NbNegativeValues = 0;
+	// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
+	// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
+	// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
+	udword* h3= &mHistogram[768];
+	for(udword i=128;i<256;i++)	NbNegativeValues += h3[i];	// 768 for last histogram, 128 for negative part
+
+	// Radix sort, j is the pass number (0=LSB, 3=MSB)
+	for(udword j=0;j<4;j++)
+	{
+		// Should we care about negative values?
+		if(j!=3)
+		{
+			// Here we deal with positive values only
+			CHECK_PASS_VALIDITY(j);
+
+			if(PerformPass)
+			{
+				// Create offsets
+//				mOffset[0] = 0;
+				mLink[0] = mRanks2;
+//				for(udword i=1;i<256;i++)		mOffset[i] = mOffset[i-1] + CurCount[i-1];
+				for(udword i=1;i<256;i++)		mLink[i] = mLink[i-1] + CurCount[i-1];
+
+				// Perform Radix Sort
+				ubyte* InputBytes = (ubyte*)input;
+				InputBytes += j;
+				if(INVALID_RANKS)
+				{
+//					for(i=0;i<nb;i++)	mRanks2[mOffset[InputBytes[i<<2]]++] = i;
+					for(udword i=0;i<nb;i++)	*mLink[InputBytes[i<<2]]++ = i;
+					VALIDATE_RANKS;
+				}
+				else
+				{
+					udword* Indices		= mRanks;
+					udword* IndicesEnd	= &mRanks[nb];
+					while(Indices!=IndicesEnd)
+					{
+						udword id = *Indices++;
+//						mRanks2[mOffset[InputBytes[id<<2]]++] = id;
+						*mLink[InputBytes[id<<2]]++ = id;
+					}
+				}
+
+				// Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
+				udword* Tmp	= mRanks;	mRanks = mRanks2; mRanks2 = Tmp;
+			}
+		}
+		else
+		{
+			// This is a special case to correctly handle negative values
+			CHECK_PASS_VALIDITY(j);
+
+			if(PerformPass)
+			{
+				// Create biased offsets, in order for negative numbers to be sorted as well
+//				mOffset[0] = NbNegativeValues;												// First positive number takes place after the negative ones
+				mLink[0] = &mRanks2[NbNegativeValues];										// First positive number takes place after the negative ones
+//				for(udword i=1;i<128;i++)		mOffset[i] = mOffset[i-1] + CurCount[i-1];	// 1 to 128 for positive numbers
+				for(udword i=1;i<128;i++)		mLink[i] = mLink[i-1] + CurCount[i-1];		// 1 to 128 for positive numbers
+
+				// We must reverse the sorting order for negative numbers!
+//				mOffset[255] = 0;
+				mLink[255] = mRanks2;
+//				for(i=0;i<127;i++)		mOffset[254-i] = mOffset[255-i] + CurCount[255-i];	// Fixing the wrong order for negative values
+				for(udword i=0;i<127;i++)	mLink[254-i] = mLink[255-i] + CurCount[255-i];		// Fixing the wrong order for negative values
+//				for(i=128;i<256;i++)	mOffset[i] += CurCount[i];							// Fixing the wrong place for negative values
+				for(udword i=128;i<256;i++)	mLink[i] += CurCount[i];							// Fixing the wrong place for negative values
+
+				// Perform Radix Sort
+				if(INVALID_RANKS)
+				{
+					for(udword i=0;i<nb;i++)
+					{
+						udword Radix = input[i]>>24;							// Radix byte, same as above. AND is useless here (udword).
+						// ### cmp to be killed. Not good. Later.
+//						if(Radix<128)		mRanks2[mOffset[Radix]++] = i;		// Number is positive, same as above
+//						else				mRanks2[--mOffset[Radix]] = i;		// Number is negative, flip the sorting order
+						if(Radix<128)		*mLink[Radix]++ = i;		// Number is positive, same as above
+						else				*(--mLink[Radix]) = i;		// Number is negative, flip the sorting order
+					}
+					VALIDATE_RANKS;
+				}
+				else
+				{
+					for(udword i=0;i<nb;i++)
+					{
+						udword Radix = input[mRanks[i]]>>24;							// Radix byte, same as above. AND is useless here (udword).
+						// ### cmp to be killed. Not good. Later.
+//						if(Radix<128)		mRanks2[mOffset[Radix]++] = mRanks[i];		// Number is positive, same as above
+//						else				mRanks2[--mOffset[Radix]] = mRanks[i];		// Number is negative, flip the sorting order
+						if(Radix<128)		*mLink[Radix]++ = mRanks[i];		// Number is positive, same as above
+						else				*(--mLink[Radix]) = mRanks[i];		// Number is negative, flip the sorting order
+					}
+				}
+				// Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
+				udword* Tmp	= mRanks;	mRanks = mRanks2; mRanks2 = Tmp;
+			}
+			else
+			{
+				// The pass is useless, yet we still have to reverse the order of current list if all values are negative.
+				if(UniqueVal>=128)
+				{
+					if(INVALID_RANKS)
+					{
+						// ###Possible?
+						for(udword i=0;i<nb;i++)	mRanks2[i] = nb-i-1;
+						VALIDATE_RANKS;
+					}
+					else
+					{
+						for(udword i=0;i<nb;i++)	mRanks2[i] = mRanks[nb-i-1];
+					}
+
+					// Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap.
+					udword* Tmp	= mRanks;	mRanks = mRanks2; mRanks2 = Tmp;
+				}
+			}
+		}
+	}
+	return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the ram used.
+ *	\return		memory used in bytes
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword RadixSort::GetUsedRam() const
+{
+	udword UsedRam = sizeof(RadixSort);
+#ifndef RADIX_LOCAL_RAM
+	UsedRam += 256*4*sizeof(udword);			// Histograms
+	UsedRam += 256*sizeof(udword);				// Offsets
+#endif
+	UsedRam += 2*CURRENT_SIZE*sizeof(udword);	// 2 lists of indices
+	return UsedRam;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceRevisitedRadix.h	(revision 216)
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains source code from the article "Radix Sort Revisited".
+ *	\file		IceRevisitedRadix.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICERADIXSORT_H__
+#define __ICERADIXSORT_H__
+
+	//! Allocate histograms & offsets locally
+	#define RADIX_LOCAL_RAM
+
+	enum RadixHint
+	{
+		RADIX_SIGNED,		//!< Input values are signed
+		RADIX_UNSIGNED,		//!< Input values are unsigned
+
+		RADIX_FORCE_DWORD = 0x7fffffff
+	};
+
+	class ICECORE_API RadixSort
+	{
+		public:
+		// Constructor/Destructor
+								RadixSort();
+								~RadixSort();
+		// Sorting methods
+				RadixSort&		Sort(const udword* input, udword nb, RadixHint hint=RADIX_SIGNED);
+				RadixSort&		Sort(const float* input, udword nb);
+
+		//! Access to results. mRanks is a list of indices in sorted order, i.e. in the order you may further process your data
+		inline_	const udword*	GetRanks()			const	{ return mRanks;		}
+
+		//! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want.
+		inline_	udword*			GetRecyclable()		const	{ return mRanks2;		}
+
+		// Stats
+				udword			GetUsedRam()		const;
+		//! Returns the total number of calls to the radix sorter.
+		inline_	udword			GetNbTotalCalls()	const	{ return mTotalCalls;	}
+		//! Returns the number of eraly exits due to temporal coherence.
+		inline_	udword			GetNbHits()			const	{ return mNbHits;		}
+
+		private:
+#ifndef RADIX_LOCAL_RAM
+				udword*			mHistogram;			//!< Counters for each byte
+				udword*			mOffset;			//!< Offsets (nearly a cumulative distribution function)
+#endif
+				udword			mCurrentSize;		//!< Current size of the indices list
+				udword*			mRanks;				//!< Two lists, swapped each pass
+				udword*			mRanks2;
+		// Stats
+				udword			mTotalCalls;		//!< Total number of calls to the sort routine
+				udword			mNbHits;			//!< Number of early exits due to coherence
+		// Internal methods
+				void			CheckResize(udword nb);
+				bool			Resize(udword nb);
+	};
+
+#endif // __ICERADIXSORT_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceSegment.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceSegment.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceSegment.cpp	(revision 216)
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for segments.
+ *	\file		IceSegment.cpp
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Segment class.
+ *	A segment is defined by S(t) = mP0 * (1 - t) + mP1 * t, with 0 <= t <= 1
+ *	Alternatively, a segment is S(t) = Origin + t * Direction for 0 <= t <= 1.
+ *	Direction is not necessarily unit length. The end points are Origin = mP0 and Origin + Direction = mP1.
+ *
+ *	\class		Segment
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+float Segment::SquareDistance(const Point& point, float* t)	const
+{
+	Point Diff = point - mP0;
+	Point Dir = mP1 - mP0;
+	float fT = Diff | Dir;
+
+	if(fT<=0.0f)
+	{
+		fT = 0.0f;
+	}
+	else
+	{
+		float SqrLen= Dir.SquareMagnitude();
+		if(fT>=SqrLen)
+		{
+			fT = 1.0f;
+			Diff -= Dir;
+		}
+		else
+		{
+			fT /= SqrLen;
+			Diff -= fT*Dir;
+		}
+	}
+
+	if(t)	*t = fT;
+
+	return Diff.SquareMagnitude();
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceSegment.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceSegment.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceSegment.h	(revision 216)
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for segments.
+ *	\file		IceSegment.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICESEGMENT_H__
+#define __ICESEGMENT_H__
+
+	class ICEMATHS_API Segment
+	{
+		public:
+		//! Constructor
+		inline_					Segment()															{}
+		//! Constructor
+		inline_					Segment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1)		{}
+		//! Copy constructor
+		inline_					Segment(const Segment& seg) : mP0(seg.mP0), mP1(seg.mP1)			{}
+		//! Destructor
+		inline_					~Segment()															{}
+
+		inline_	const	Point&	GetOrigin()						const	{ return mP0;						}
+		inline_			Point	ComputeDirection()				const	{ return mP1 - mP0;					}
+		inline_			void	ComputeDirection(Point& dir)	const	{ dir = mP1 - mP0;					}
+		inline_			float	ComputeLength()					const	{ return mP1.Distance(mP0);			}
+		inline_			float	ComputeSquareLength()			const	{ return mP1.SquareDistance(mP0);	}
+
+		inline_			void	SetOriginDirection(const Point& origin, const Point& direction)
+								{
+									mP0 = mP1 = origin;
+									mP1 += direction;
+								}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes a point on the segment
+		 *	\param		pt	[out] point on segment
+		 *	\param		t	[in] point's parameter [t=0 => pt = mP0, t=1 => pt = mP1]
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void	ComputePoint(Point& pt, float t)	const	{	pt = mP0 + t * (mP1 - mP0);		}
+
+						float	SquareDistance(const Point& point, float* t=null)	const;
+		inline_			float	Distance(const Point& point, float* t=null)			const			{ return sqrtf(SquareDistance(point, t));	}
+
+						Point	mP0;		//!< Start of segment
+						Point	mP1;		//!< End of segment
+	};
+
+#endif // __ICESEGMENT_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriList.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriList.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriList.h	(revision 216)
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a triangle container.
+ *	\file		IceTrilist.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICETRILIST_H__
+#define __ICETRILIST_H__
+
+	class ICEMATHS_API TriList : public Container
+	{
+		public:
+		// Constructor / Destructor
+								TriList()					{}
+								~TriList()					{}
+
+		inline_	udword			GetNbTriangles()	const	{ return GetNbEntries()/9;			}
+		inline_	Triangle*		GetTriangles()		const	{ return (Triangle*)GetEntries();	}
+
+				void			AddTri(const Triangle& tri)
+								{
+									Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z);
+									Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z);
+									Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z);
+								}
+
+				void			AddTri(const Point& p0, const Point& p1, const Point& p2)
+								{
+									Add(p0.x).Add(p0.y).Add(p0.z);
+									Add(p1.x).Add(p1.y).Add(p1.z);
+									Add(p2.x).Add(p2.y).Add(p2.z);
+								}
+	};
+
+	class ICEMATHS_API TriangleList : public Container
+	{
+		public:
+		// Constructor / Destructor
+									TriangleList()				{}
+									~TriangleList()				{}
+
+		inline_	udword				GetNbTriangles()	const	{ return GetNbEntries()/3;				}
+		inline_	IndexedTriangle*	GetTriangles()		const	{ return (IndexedTriangle*)GetEntries();}
+
+				void				AddTriangle(const IndexedTriangle& tri)
+									{
+										Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]);
+									}
+
+				void				AddTriangle(udword vref0, udword vref1, udword vref2)
+									{
+										Add(vref0).Add(vref1).Add(vref2);
+									}
+	};
+
+#endif //__ICETRILIST_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriangle.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriangle.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriangle.cpp	(revision 216)
@@ -0,0 +1,286 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a handy triangle class.
+ *	\file		IceTriangle.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 17, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a triangle class.
+ *
+ *	\class		Tri
+ *	\author		Pierre Terdiman
+ *	\version	1.0
+ *	\date		08.15.98
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static sdword VPlaneSideEps(const Point& v, const Plane& plane, float epsilon)
+{
+	// Compute distance from current vertex to the plane
+	float Dist = plane.Distance(v);
+	// Compute side:
+	// 1	= the vertex is on the positive side of the plane
+	// -1	= the vertex is on the negative side of the plane
+	// 0	= the vertex is on the plane (within epsilon)
+	return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Flips the winding order.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::Flip()
+{
+	Point Tmp = mVerts[1];
+	mVerts[1] = mVerts[2];
+	mVerts[2] = Tmp;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle area.
+ *	\return		the area
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::Area() const
+{
+	const Point& p0 = mVerts[0];
+	const Point& p1 = mVerts[1];
+	const Point& p2 = mVerts[2];
+	return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle perimeter.
+ *	\return		the perimeter
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::Perimeter()	const
+{
+	const Point& p0 = mVerts[0];
+	const Point& p1 = mVerts[1];
+	const Point& p2 = mVerts[2];
+	return		p0.Distance(p1)
+			+	p0.Distance(p2)
+			+	p1.Distance(p2);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle compacity.
+ *	\return		the compacity
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::Compacity() const
+{
+	float P = Perimeter();
+	if(P==0.0f)	return 0.0f;
+	return (4.0f*PI*Area()/(P*P));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle normal.
+ *	\param		normal	[out] the computed normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::Normal(Point& normal) const
+{
+	const Point& p0 = mVerts[0];
+	const Point& p1 = mVerts[1];
+	const Point& p2 = mVerts[2];
+	normal = ((p0 - p1)^(p0 - p2)).Normalize();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle denormalized normal.
+ *	\param		normal	[out] the computed normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::DenormalizedNormal(Point& normal) const
+{
+	const Point& p0 = mVerts[0];
+	const Point& p1 = mVerts[1];
+	const Point& p2 = mVerts[2];
+	normal = ((p0 - p1)^(p0 - p2));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle center.
+ *	\param		center	[out] the computed center
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::Center(Point& center) const
+{
+	const Point& p0 = mVerts[0];
+	const Point& p1 = mVerts[1];
+	const Point& p2 = mVerts[2];
+	center = (p0 + p1 + p2)*INV3;
+}
+
+PartVal Triangle::TestAgainstPlane(const Plane& plane, float epsilon) const
+{
+	bool Pos = false, Neg = false;
+
+	// Loop through all vertices
+	for(udword i=0;i<3;i++)
+	{
+		// Compute side:
+		sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon);
+
+				if (Side < 0)	Neg = true;
+		else	if (Side > 0)	Pos = true;
+	}
+
+			if (!Pos && !Neg)	return TRI_ON_PLANE;
+	else	if (Pos && Neg)		return TRI_INTERSECT;
+	else	if (Pos && !Neg)	return TRI_PLUS_SPACE;
+	else	if (!Pos && Neg)	return TRI_MINUS_SPACE;
+
+	// What?!
+	return TRI_FORCEDWORD;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle moment.
+ *	\param		m	[out] the moment
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+void Triangle::ComputeMoment(Moment& m)
+{
+	// Compute the area of the triangle
+	m.mArea = Area();
+
+	// Compute the centroid
+	Center(m.mCentroid);
+
+	// Second-order components. Handle zero-area faces.
+	Point& p = mVerts[0];
+	Point& q = mVerts[1];
+	Point& r = mVerts[2];
+	if(m.mArea==0.0f)
+	{
+		// This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the 
+		// sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices.
+		m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x);
+		m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y);
+		m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z);
+		m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y);
+		m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z);
+		m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z);      
+		m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
+		m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
+		m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
+	}
+	else
+	{
+		const float OneOverTwelve = 1.0f / 12.0f;
+		m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve;
+		m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve;
+		m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve;
+		m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve;
+		m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve;
+		m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve;
+		m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
+		m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
+		m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
+	}
+}
+*/
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle's smallest edge length.
+ *	\return		the smallest edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::MinEdgeLength()	const
+{
+	float Min = MAX_FLOAT;
+	float Length01 = mVerts[0].Distance(mVerts[1]);
+	float Length02 = mVerts[0].Distance(mVerts[2]);
+	float Length12 = mVerts[1].Distance(mVerts[2]);
+	if(Length01 < Min)	Min = Length01;
+	if(Length02 < Min)	Min = Length02;
+	if(Length12 < Min)	Min = Length12;
+	return Min;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the triangle's largest edge length.
+ *	\return		the largest edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::MaxEdgeLength()	const
+{
+	float Max = MIN_FLOAT;
+	float Length01 = mVerts[0].Distance(mVerts[1]);
+	float Length02 = mVerts[0].Distance(mVerts[2]);
+	float Length12 = mVerts[1].Distance(mVerts[2]);
+	if(Length01 > Max)	Max = Length01;
+	if(Length02 > Max)	Max = Length02;
+	if(Length12 > Max)	Max = Length12;
+	return Max;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes a point on the triangle according to the stabbing information.
+ *	\param		u,v			[in] point's barycentric coordinates
+ *	\param		pt			[out] point on triangle
+ *	\param		nearvtx		[out] index of nearest vertex
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx)	const
+{
+	// Compute point coordinates
+	pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
+
+	// Compute nearest vertex if needed
+	if(nearvtx)
+	{
+		// Compute distance vector
+		Point d(mVerts[0].SquareDistance(pt),	// Distance^2 from vertex 0 to point on the face
+				mVerts[1].SquareDistance(pt),	// Distance^2 from vertex 1 to point on the face
+				mVerts[2].SquareDistance(pt));	// Distance^2 from vertex 2 to point on the face
+
+		// Get smallest distance
+		*nearvtx = d.SmallestAxis();
+	}
+}
+
+void Triangle::Inflate(float fat_coeff, bool constant_border)
+{
+	// Compute triangle center
+	Point TriangleCenter;
+	Center(TriangleCenter);
+
+	// Don't normalize?
+	// Normalize => add a constant border, regardless of triangle size
+	// Don't => add more to big triangles
+	for(udword i=0;i<3;i++)
+	{
+		Point v = mVerts[i] - TriangleCenter;
+
+		if(constant_border)	v.Normalize();
+
+		mVerts[i] += v * fat_coeff;
+	}
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriangle.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriangle.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceTriangle.h	(revision 216)
@@ -0,0 +1,68 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a handy triangle class.
+ *	\file		IceTriangle.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 17, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICETRIANGLE_H__
+#define __ICETRIANGLE_H__
+
+	// Forward declarations
+	class Moment;
+
+	// Partitioning values
+	enum PartVal
+	{
+		TRI_MINUS_SPACE		= 0,			//!< Triangle is in the negative space
+		TRI_PLUS_SPACE		= 1,			//!< Triangle is in the positive space
+		TRI_INTERSECT		= 2,			//!< Triangle intersects plane
+		TRI_ON_PLANE		= 3,			//!< Triangle and plane are coplanar
+
+		TRI_FORCEDWORD		= 0x7fffffff
+	};
+
+	// A triangle class.
+	class ICEMATHS_API Triangle
+	{
+		public:
+		//! Constructor
+		inline_					Triangle()													{}
+		//! Constructor
+		inline_					Triangle(const Point& p0, const Point& p1, const Point& p2)	{ mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; }
+		//! Copy constructor
+		inline_					Triangle(const Triangle& triangle)
+								{
+									mVerts[0] = triangle.mVerts[0];
+									mVerts[1] = triangle.mVerts[1];
+									mVerts[2] = triangle.mVerts[2];
+								}
+		//! Destructor
+		inline_					~Triangle()													{}
+		//! Vertices
+				Point			mVerts[3];
+
+		// Methods
+				void			Flip();
+				float			Area() const;
+				float			Perimeter()	const;
+				float			Compacity()	const;
+				void			Normal(Point& normal) const;
+				void			DenormalizedNormal(Point& normal) const;
+				void			Center(Point& center) const;
+		inline_	Plane			PlaneEquation() const	{ return Plane(mVerts[0], mVerts[1], mVerts[2]);	}
+
+				PartVal			TestAgainstPlane(const Plane& plane, float epsilon) const;
+//				float			Distance(Point& cp, Point& cq, Tri& tri);
+				void			ComputeMoment(Moment& m);
+				float			MinEdgeLength() const;
+				float			MaxEdgeLength() const;
+				void			ComputePoint(float u, float v, Point& pt, udword* nearvtx=null)	const;
+				void			Inflate(float fat_coeff, bool constant_border);
+	};
+
+#endif // __ICETRIANGLE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceTypes.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceTypes.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceTypes.h	(revision 216)
@@ -0,0 +1,171 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains custom types.
+ *	\file		IceTypes.h
+ *	\author		Pierre Terdiman
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICETYPES_H__
+#define __ICETYPES_H__
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Things to help us compile on non-windows platforms
+
+#if defined(__MACOSX__) || defined(__APPLE__)
+#undef bool
+#define bool char
+#undef true
+#define true ((bool)-1)
+#undef false
+#define false ((bool)0)
+#endif // mac stuff
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	#define USE_HANDLE_MANAGER
+
+	// Constants
+	#define	PI					3.1415926535897932384626433832795028841971693993751f	//!< PI
+	#define	HALFPI				1.57079632679489661923f									//!< 0.5 * PI
+	#define	TWOPI				6.28318530717958647692f									//!< 2.0 * PI
+	#define	INVPI				0.31830988618379067154f									//!< 1.0 / PI
+
+	#define	RADTODEG			57.2957795130823208768f									//!< 180.0 / PI, convert radians to degrees
+	#define	DEGTORAD			0.01745329251994329577f									//!< PI / 180.0, convert degrees to radians
+
+	#define	EXP					2.71828182845904523536f									//!< e
+	#define	INVLOG2				3.32192809488736234787f									//!< 1.0 / log10(2)
+	#define	LN2					0.693147180559945f										//!< ln(2)
+	#define	INVLN2				1.44269504089f											//!< 1.0f / ln(2)
+
+	#define	INV3				0.33333333333333333333f									//!< 1/3
+	#define	INV6				0.16666666666666666666f									//!< 1/6
+	#define	INV7				0.14285714285714285714f									//!< 1/7
+	#define	INV9				0.11111111111111111111f									//!< 1/9
+	#define	INV255				0.00392156862745098039f									//!< 1/255
+
+	#define	SQRT2				1.41421356237f											//!< sqrt(2)
+	#define	INVSQRT2			0.707106781188f											//!< 1 / sqrt(2)
+
+	#define	SQRT3				1.73205080757f											//!< sqrt(3)
+	#define	INVSQRT3			0.577350269189f											//!< 1 / sqrt(3)
+
+	#define null				0														//!< our own NULL pointer
+
+	// Custom types used in ICE
+	typedef signed char			sbyte;		//!< sizeof(sbyte)	must be 1
+	typedef unsigned char		ubyte;		//!< sizeof(ubyte)	must be 1
+	typedef signed short		sword;		//!< sizeof(sword)	must be 2
+	typedef unsigned short		uword;		//!< sizeof(uword)	must be 2
+	typedef signed int			sdword;		//!< sizeof(sdword)	must be 4
+	typedef unsigned int		udword;		//!< sizeof(udword)	must be 4
+	typedef signed __int64		sqword;		//!< sizeof(sqword)	must be 8
+	typedef unsigned __int64	uqword;		//!< sizeof(uqword)	must be 8
+	typedef float				float32;	//!< sizeof(float32)	must be 4
+	typedef double				float64;	//!< sizeof(float64)	must be 4
+
+	ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1);	// ...otherwise things might fail with VC++ 4.2 !
+	ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1);
+	ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1);
+	ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2);
+	ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2);
+	ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4);
+	ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4);
+	ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8);
+	ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8);
+
+	//! TO BE DOCUMENTED
+	#define DECLARE_ICE_HANDLE(name)	struct name##__ { int unused; }; typedef struct name##__ *name
+
+	typedef udword				DynID;		//!< Dynamic identifier
+#ifdef USE_HANDLE_MANAGER
+	typedef udword				KID;		//!< Kernel ID
+//	DECLARE_ICE_HANDLE(KID);
+#else
+	typedef uword				KID;		//!< Kernel ID
+#endif
+	typedef udword				RTYPE;		//!< Relationship-type (!) between owners and references
+	#define	INVALID_ID			0xffffffff	//!< Invalid dword ID (counterpart of null pointers)
+#ifdef USE_HANDLE_MANAGER
+	#define	INVALID_KID			0xffffffff	//!< Invalid Kernel ID
+#else
+	#define	INVALID_KID			0xffff		//!< Invalid Kernel ID
+#endif
+	#define	INVALID_NUMBER		0xDEADBEEF	//!< Standard junk value
+
+	// Define BOOL if needed
+	#ifndef BOOL
+	typedef int	BOOL;						//!< Another boolean type.
+	#endif
+
+	//! Union of a float and a sdword
+	typedef union {
+		float	f;							//!< The float
+		sdword	d;							//!< The integer
+	}scell;
+
+	//! Union of a float and a udword
+	typedef union {
+		float	f;							//!< The float
+		udword	d;							//!< The integer
+	}ucell;
+
+	// Type ranges
+	#define	MAX_SBYTE				0x7f						//!< max possible sbyte value
+	#define	MIN_SBYTE				0x80						//!< min possible sbyte value
+	#define	MAX_UBYTE				0xff						//!< max possible ubyte value
+	#define	MIN_UBYTE				0x00						//!< min possible ubyte value
+	#define	MAX_SWORD				0x7fff						//!< max possible sword value
+	#define	MIN_SWORD				0x8000						//!< min possible sword value
+	#define	MAX_UWORD				0xffff						//!< max possible uword value
+	#define	MIN_UWORD				0x0000						//!< min possible uword value
+	#define	MAX_SDWORD				0x7fffffff					//!< max possible sdword value
+	#define	MIN_SDWORD				0x80000000					//!< min possible sdword value
+	#define	MAX_UDWORD				0xffffffff					//!< max possible udword value
+	#define	MIN_UDWORD				0x00000000					//!< min possible udword value
+	#define	MAX_FLOAT				FLT_MAX						//!< max possible float value
+	#define	MIN_FLOAT				(-FLT_MAX)					//!< min possible loat value
+	#define IEEE_1_0				0x3f800000					//!< integer representation of 1.0
+	#define IEEE_255_0				0x437f0000					//!< integer representation of 255.0
+	#define IEEE_MAX_FLOAT			0x7f7fffff					//!< integer representation of MAX_FLOAT
+	#define IEEE_MIN_FLOAT			0xff7fffff					//!< integer representation of MIN_FLOAT
+	#define IEEE_UNDERFLOW_LIMIT	0x1a000000
+
+	#define ONE_OVER_RAND_MAX		(1.0f / float(RAND_MAX))	//!< Inverse of the max possible value returned by rand()
+
+	typedef int					(__stdcall* PROC)();			//!< A standard procedure call.
+	typedef bool				(*ENUMERATION)(udword value, udword param, udword context);	//!< ICE standard enumeration call
+	typedef	void**				VTABLE;							//!< A V-Table.
+
+	#undef		MIN
+	#undef		MAX
+	#define		MIN(a, b)       ((a) < (b) ? (a) : (b))			//!< Returns the min value between a and b
+	#define		MAX(a, b)       ((a) > (b) ? (a) : (b))			//!< Returns the max value between a and b
+	#define		MAXMAX(a,b,c)   ((a) > (b) ? MAX (a,c) : MAX (b,c))	//!<	Returns the max value between a, b and c
+
+	template<class T>	inline_ const T&	TMin	(const T& a, const T& b)	{ return b < a ? b : a;	}
+	template<class T>	inline_ const T&	TMax	(const T& a, const T& b)	{ return a < b ? b : a;	}
+	template<class T>	inline_ void		TSetMin	(T& a, const T& b)			{ if(a>b)	a = b;		}
+	template<class T>	inline_ void		TSetMax	(T& a, const T& b)			{ if(a<b)	a = b;		}
+
+	#define		SQR(x)			((x)*(x))						//!< Returns x square
+	#define		CUBE(x)			((x)*(x)*(x))					//!< Returns x cube
+
+	#define		AND		&										//!< ...
+	#define		OR		|										//!< ...
+	#define		XOR		^										//!< ...
+
+	#define		QUADRAT(x)		((x)*(x))						//!< Returns x square
+
+#ifdef _WIN32
+#   define srand48(x) srand((unsigned int) (x))
+#	define srandom(x) srand((unsigned int) (x))
+#	define random()   ((double) rand())
+#   define drand48()  ((double) (((double) rand()) / ((double) RAND_MAX)))
+#endif
+
+#endif // __ICETYPES_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceUtils.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceUtils.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceUtils.cpp	(revision 216)
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains misc. useful macros & defines.
+ *	\file		IceUtils.cpp
+ *	\author		Pierre Terdiman (collected from various sources)
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace IceCore;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Returns the alignment of the input address.
+ *	\fn			Alignment()
+ *	\param		address	[in] address to check
+ *	\return		the best alignment (e.g. 1 for odd addresses, etc)
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword IceCore::Alignment(udword address)
+{
+	// Returns 0 for null addresses
+	if(!address) return 0;
+
+	// Test all bits
+	udword Align = 1;
+	for(udword i=1;i<32;i++)
+	{
+		// Returns as soon as the alignment is broken
+		if(address&Align)	return Align;
+		Align<<=1;
+	}
+	// Here all bits are null, except the highest one (else the address would be null)
+	return Align;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/Ice/IceUtils.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Ice/IceUtils.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Ice/IceUtils.h	(revision 216)
@@ -0,0 +1,256 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains misc. useful macros & defines.
+ *	\file		IceUtils.h
+ *	\author		Pierre Terdiman (collected from various sources)
+ *	\date		April, 4, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __ICEUTILS_H__
+#define __ICEUTILS_H__
+
+	#define START_RUNONCE	{ static bool __RunOnce__ = false;	if(!__RunOnce__){
+	#define END_RUNONCE		__RunOnce__ = true;}}
+
+	//! Reverse all the bits in a 32 bit word (from Steve Baker's Cute Code Collection)
+	//! (each line can be done in any order.
+	inline_ void	ReverseBits(udword& n)
+	{
+		n = ((n >>  1) & 0x55555555) | ((n <<  1) & 0xaaaaaaaa);
+		n = ((n >>  2) & 0x33333333) | ((n <<  2) & 0xcccccccc);
+		n = ((n >>  4) & 0x0f0f0f0f) | ((n <<  4) & 0xf0f0f0f0);
+		n = ((n >>  8) & 0x00ff00ff) | ((n <<  8) & 0xff00ff00);
+		n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
+		// Etc for larger intergers (64 bits in Java)
+		// NOTE: the >> operation must be unsigned! (>>> in java)
+	}
+
+	//! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection)
+	inline_ udword	CountBits(udword n)
+	{
+		// This relies of the fact that the count of n bits can NOT overflow 
+		// an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts
+		// 2 bit interger, 3 bit count requires only a 2 bit interger.
+		// So we add all bit pairs, then each nible, then each byte etc...
+		n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1);
+		n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2);
+		n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4);
+		n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8);
+		n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16);
+		// Etc for larger intergers (64 bits in Java)
+		// NOTE: the >> operation must be unsigned! (>>> in java)
+		return n;
+	}
+
+	//! Even faster?
+	inline_ udword	CountBits2(udword bits)
+	{
+		bits = bits - ((bits >> 1) & 0x55555555);
+		bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333);
+		bits = ((bits >> 4) + bits) & 0x0F0F0F0F;
+		return (bits * 0x01010101) >> 24;
+	}
+
+	//! Spread out bits.	EG	00001111  ->   0101010101
+	//! 						00001010  ->   0100010000
+	//! This is used to interleve to intergers to produce a `Morten Key'
+	//! used in Space Filling Curves (See DrDobbs Journal, July 1999)
+	//! Order is important.
+	inline_ void	SpreadBits(udword& n)
+	{
+		n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16);
+		n = ( n & 0x000000ff) | (( n & 0x0000ff00) <<  8);
+		n = ( n & 0x000f000f) | (( n & 0x00f000f0) <<  4);
+		n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) <<  2);
+		n = ( n & 0x11111111) | (( n & 0x22222222) <<  1);
+	}
+
+	// Next Largest Power of 2
+	// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
+	// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
+	// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
+	// largest power of 2. For a 32-bit value: 
+	inline_ udword	nlpo2(udword x)
+	{
+		x |= (x >> 1);
+		x |= (x >> 2);
+		x |= (x >> 4);
+		x |= (x >> 8);
+		x |= (x >> 16);
+		return x+1;
+	}
+
+	//! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection)
+	inline_ bool	IsPowerOfTwo(udword n)				{ return ((n&(n-1))==0);					}
+
+	//! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection)
+	inline_ void	ZeroLeastSetBit(udword& n)			{ n&=(n-1);									}
+
+	//! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection)
+	inline_ void	SetLeastNBits(udword& x, udword n)	{ x|=~(~0<<n);								}
+
+	//! Classic XOR swap (from Steve Baker's Cute Code Collection)
+	//! x ^= y;		/* x' = (x^y) */
+	//! y ^= x;		/* y' = (y^(x^y)) = x */
+	//! x ^= y;		/* x' = (x^y)^x = y */
+	inline_ void	Swap(udword& x, udword& y)			{ x ^= y; y ^= x; x ^= y;					}
+
+	//! Little/Big endian (from Steve Baker's Cute Code Collection)
+	//!
+	//! Extra comments by Kenny Hoff:
+	//! Determines the byte-ordering of the current machine (little or big endian)
+	//! by setting an integer value to 1 (so least significant bit is now 1); take
+	//! the address of the int and cast to a byte pointer (treat integer as an
+	//! array of four bytes); check the value of the first byte (must be 0 or 1).
+	//! If the value is 1, then the first byte least significant byte and this
+	//! implies LITTLE endian. If the value is 0, the first byte is the most
+	//! significant byte, BIG endian. Examples:
+	//!      integer 1 on BIG endian: 00000000 00000000 00000000 00000001
+	//!   integer 1 on LITTLE endian: 00000001 00000000 00000000 00000000
+	//!---------------------------------------------------------------------------
+	//! int IsLittleEndian()	{ int x=1;	return ( ((char*)(&x))[0] );	}
+	inline_ char	LittleEndian()						{ int i = 1; return *((char*)&i);			}
+
+	//!< Alternative abs function
+	inline_ udword	abs_(sdword x)					{ sdword y= x >> 31;	return (x^y)-y;		}
+
+	//!< Alternative min function
+	inline_ sdword	min_(sdword a, sdword b)			{ sdword delta = b-a;	return a + (delta&(delta>>31));	}
+
+	// Determine if one of the bytes in a 4 byte word is zero
+	inline_	BOOL	HasNullByte(udword x)			{ return ((x + 0xfefefeff) & (~x) & 0x80808080);		}
+
+	// To find the smallest 1 bit in a word  EG: ~~~~~~10---0    =>    0----010---0
+	inline_	udword	LowestOneBit(udword w)			{ return ((w) & (~(w)+1));					}
+//	inline_	udword	LowestOneBit_(udword w)			{ return ((w) & (-(w)));					}
+
+	// Most Significant 1 Bit
+	// Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set)
+	// can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits.
+	// This process yields a bit vector with the same most significant 1 as x, but all 1's below it.
+	 // Bitwise AND of the original value with the complement of the "folded" value shifted down by one
+	// yields the most significant bit. For a 32-bit value: 
+	inline_ udword	msb32(udword x)
+	{
+		x |= (x >> 1);
+		x |= (x >> 2);
+		x |= (x >> 4);
+		x |= (x >> 8);
+		x |= (x >> 16);
+		return (x & ~(x >> 1));
+	}
+
+	/*
+	"Just call it repeatedly with various input values and always with the same variable as "memory".
+	The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1
+	does no filtering at all.
+
+	I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed
+	to the more typical FIR (Finite Impulse Response).
+
+	Also, I'd say that you can make more intelligent and interesting filters than this, for example filters
+	that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter
+	to be applied before this one, of course."
+
+	(JCAB on Flipcode)
+	*/
+	inline_ float	FeedbackFilter(float val, float& memory, float sharpness)
+	{
+		ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter");
+				if(sharpness<0.0f)	sharpness = 0.0f;
+		else	if(sharpness>1.0f)	sharpness = 1.0f;
+		return memory = val * sharpness + memory * (1.0f - sharpness);
+	}
+
+	//! If you can guarantee that your input domain (i.e. value of x) is slightly
+	//! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the
+	//! following code to clamp the resulting value into [-32768,+32767] range:
+	inline_ int	ClampToInt16(int x)
+	{
+//		ASSERT(abs(x) < (int)((1<<31u)-32767));
+
+		int delta = 32767 - x;
+		x += (delta>>31) & delta;
+		delta = x + 32768;
+		x -= (delta>>31) & delta;
+		return x;
+	}
+
+	// Generic functions
+	template<class Type> inline_ void TSwap(Type& a, Type& b)								{ const Type c = a; a = b; b = c;			}
+	template<class Type> inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi)	{ return ((x<lo) ? lo : (x>hi) ? hi : x);	}
+
+	template<class Type> inline_ void TSort(Type& a, Type& b)
+	{
+		if(a>b)	TSwap(a, b);
+	}
+
+	template<class Type> inline_ void TSort(Type& a, Type& b, Type& c)
+	{
+		if(a>b)	TSwap(a, b);
+		if(b>c)	TSwap(b, c);
+		if(a>b)	TSwap(a, b);
+		if(b>c)	TSwap(b, c);
+	}
+
+	// Prevent nasty user-manipulations (strategy borrowed from Charles Bloom)
+//	#define PREVENT_COPY(curclass)	void operator = (const curclass& object)	{	ASSERT(!"Bad use of operator =");	}
+	// ... actually this is better !
+	#define PREVENT_COPY(cur_class)	private: cur_class(const cur_class& object);	cur_class& operator=(const cur_class& object);
+
+	//! TO BE DOCUMENTED
+	#define OFFSET_OF(Class, Member)	(size_t)&(((Class*)0)->Member)
+	//! TO BE DOCUMENTED
+	#define ARRAYSIZE(p)				(sizeof(p)/sizeof(p[0]))
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	Returns the alignment of the input address.
+	 *	\fn			Alignment()
+	 *	\param		address	[in] address to check
+	 *	\return		the best alignment (e.g. 1 for odd addresses, etc)
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	FUNCTION ICECORE_API udword Alignment(udword address);
+
+	#define IS_ALIGNED_2(x)		((x&1)==0)
+	#define IS_ALIGNED_4(x)		((x&3)==0)
+	#define IS_ALIGNED_8(x)		((x&7)==0)
+
+	inline_ void _prefetch(void const* ptr)		{ (void)*(char const volatile *)ptr;	}
+
+	// Compute implicit coords from an index:
+	// The idea is to get back 2D coords from a 1D index.
+	// For example:
+	//
+	// 0		1		2	...	nbu-1
+	// nbu		nbu+1	i	...
+	//
+	// We have i, we're looking for the equivalent (u=2, v=1) location.
+	//		i = u + v*nbu
+	// <=>	i/nbu = u/nbu + v
+	// Since 0 <= u < nbu, u/nbu = 0 (integer)
+	// Hence: v = i/nbu
+	// Then we simply put it back in the original equation to compute u = i - v*nbu
+	inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu)
+	{
+		v = i / nbu;
+		u = i - (v * nbu);
+	}
+
+	// In 3D:	i = u + v*nbu + w*nbu*nbv
+	// <=>		i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w
+	// u/(nbu*nbv) is null since u/nbu was null already.
+	// v/nbv is null as well for the same reason.
+	// Hence w = i/(nbu*nbv)
+	// Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu
+	inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv)
+	{
+		w = i / (nbu_nbv);
+		Compute2DCoords(u, v, i - (w * nbu_nbv), nbu);
+	}
+
+#endif // __ICEUTILS_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_AABBCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_AABBCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_AABBCollider.cpp	(revision 216)
@@ -0,0 +1,696 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for an AABB collider.
+ *	\file		OPC_AABBCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 1st, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains an AABB-vs-tree collider.
+ *
+ *	\class		AABBCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		January, 1st, 2002
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_BoxBoxOverlap.h"
+#include "OPC_TriBoxOverlap.h"
+
+#define SET_CONTACT(prim_index, flag)						\
+	/* Set contact status */								\
+	mFlags |= flag;											\
+	mTouchedPrimitives->Add(udword(prim_index));
+
+//! AABB-triangle test
+#define AABB_PRIM(prim_index, flag)							\
+	/* Request vertices from the app */						\
+	VertexPointers VP;	mIMesh->GetTriangle(VP, prim_index);\
+	mLeafVerts[0] = *VP.Vertex[0];							\
+	mLeafVerts[1] = *VP.Vertex[1];							\
+	mLeafVerts[2] = *VP.Vertex[2];							\
+	/* Perform triangle-box overlap test */					\
+	if(TriBoxOverlap())										\
+	{														\
+		SET_CONTACT(prim_index, flag)						\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBCollider::AABBCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBCollider::~AABBCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic collision query for generic OPCODE models. After the call, access the results:
+ *	- with GetContactStatus()
+ *	- with GetNbTouchedPrimitives()
+ *	- with GetTouchedPrimitives()
+ *
+ *	\param		cache		[in/out] a box cache
+ *	\param		box			[in] collision AABB in world space
+ *	\param		model		[in] Opcode model to collide with
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model)
+{
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, box))	return true;
+
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a collision query :
+ *	- reset stats & contact status
+ *	- check temporal coherence
+ *
+ *	\param		cache		[in/out] a box cache
+ *	\param		box			[in] AABB in world space
+ *	\return		TRUE if we can return immediately
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box)
+{
+	// 1) Call the base method
+	VolumeCollider::InitQuery();
+
+	// 2) Keep track of the query box
+	mBox = box;
+
+	// 3) Setup destination pointer
+	mTouchedPrimitives = &cache.TouchedPrimitives;
+
+	// 4) Special case: 1-triangle meshes [Opcode 1.3]
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		if(!SkipPrimitiveTests())
+		{
+			// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
+			mTouchedPrimitives->Reset();
+
+			// Perform overlap test between the unique triangle and the box (and set contact status if needed)
+			AABB_PRIM(udword(0), OPC_CONTACT)
+
+			// Return immediately regardless of status
+			return TRUE;
+		}
+	}
+
+	// 5) Check temporal coherence :
+	if(TemporalCoherenceEnabled())
+	{
+		// Here we use temporal coherence
+		// => check results from previous frame before performing the collision query
+		if(FirstContactEnabled())
+		{
+			// We're only interested in the first contact found => test the unique previously touched face
+			if(mTouchedPrimitives->GetNbEntries())
+			{
+				// Get index of previously touched face = the first entry in the array
+				udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
+
+				// Then reset the array:
+				// - if the overlap test below is successful, the index we'll get added back anyway
+				// - if it isn't, then the array should be reset anyway for the normal query
+				mTouchedPrimitives->Reset();
+
+				// Perform overlap test between the cached triangle and the box (and set contact status if needed)
+				AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
+
+				// Return immediately if possible
+				if(GetContactStatus())	return TRUE;
+			}
+			// else no face has been touched during previous query
+			// => we'll have to perform a normal query
+		}
+		else
+		{
+			// We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious):
+			if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox))
+			{
+				// - if N is included in P, return previous list
+				// => we simply leave the list (mTouchedFaces) unchanged
+
+				// Set contact status if needed
+				if(mTouchedPrimitives->GetNbEntries())	mFlags |= OPC_TEMPORAL_CONTACT;
+
+				// In any case we don't need to do a query
+				return TRUE;
+			}
+			else
+			{
+				// - else do the query using a fat N
+
+				// Reset cache since we'll about to perform a real query
+				mTouchedPrimitives->Reset();
+
+				// Make a fat box so that coherence will work for subsequent frames
+				mBox.mExtents *= cache.FatCoeff;
+
+				// Update cache with query data (signature for cached faces)
+				cache.FatBox = mBox;
+			}
+		}
+	}
+	else
+	{
+		// Here we don't use temporal coherence => do a normal query
+		mTouchedPrimitives->Reset();
+	}
+
+	// 5) Precompute min & max bounds if needed
+	mMin = box.mCenter - box.mExtents;
+	mMax = box.mCenter + box.mExtents;
+
+	return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for vanilla AABB trees.
+ *	\param		cache		[in/out] a box cache
+ *	\param		box			[in] collision AABB in world space
+ *	\param		tree		[in] AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree)
+{
+	// This is typically called for a scene tree, full of -AABBs-, not full of triangles.
+	// So we don't really have "primitives" to deal with. Hence it doesn't work with
+	// "FirstContact" + "TemporalCoherence".
+	ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
+
+	// Checkings
+	if(!tree)	return false;
+
+	// Init collision query
+	if(InitQuery(cache, box))	return true;
+
+	// Perform collision query
+	_Collide(tree);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the AABB completely contains the box. In which case we can end the query sooner.
+ *	\param		bc	[in] box center
+ *	\param		be	[in] box extents
+ *	\return		true if the AABB contains the whole box
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL AABBCollider::AABBContainsBox(const Point& bc, const Point& be)
+{
+	if(mMin.x > bc.x - be.x)	return FALSE;
+	if(mMin.y > bc.y - be.y)	return FALSE;
+	if(mMin.z > bc.z - be.z)	return FALSE;
+
+	if(mMax.x < bc.x + be.x)	return FALSE;
+	if(mMax.y < bc.y + be.y)	return FALSE;
+	if(mMax.z < bc.z + be.z)	return FALSE;
+
+	return TRUE;
+}
+
+#define TEST_BOX_IN_AABB(center, extents)	\
+	if(AABBContainsBox(center, extents))	\
+	{										\
+		/* Set contact status */			\
+		mFlags |= OPC_CONTACT;				\
+		_Dump(node);						\
+		return;								\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_Collide(const AABBCollisionNode* node)
+{
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		AABB_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
+{
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_Collide(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_AABB(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		AABB_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_AABB(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_Collide(const AABBNoLeafNode* node)
+{
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
+{
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_AABB(Center, Extents)
+
+	if(node->HasPosLeaf())	{ AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform AABB-AABB overlap test
+	if(!AABBAABBOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_AABB(Center, Extents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for vanilla AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBCollider::_Collide(const AABBTreeNode* node)
+{
+	// Perform AABB-AABB overlap test
+	Point Center, Extents;
+	node->GetAABB()->GetCenter(Center);
+	node->GetAABB()->GetExtents(Extents);
+	if(!AABBAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf() || AABBContainsBox(Center, Extents))
+	{
+		mFlags |= OPC_CONTACT;
+		mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
+	}
+	else
+	{
+		_Collide(node->GetPos());
+		_Collide(node->GetNeg());
+	}
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridAABBCollider::HybridAABBCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridAABBCollider::~HybridAABBCollider()
+{
+}
+
+bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model)
+{
+	// We don't want primitive tests here!
+	mFlags |= OPC_NO_PRIMITIVE_TESTS;
+
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, box))	return true;
+
+	// Special case for 1-leaf trees
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
+		udword Nb = mIMesh->GetNbTriangles();
+
+		// Loop through all triangles
+		for(udword i=0;i<Nb;i++)
+		{
+			AABB_PRIM(i, OPC_CONTACT)
+		}
+		return true;
+	}
+
+	// Override destination array since we're only going to get leaf boxes here
+	mTouchedBoxes.Reset();
+	mTouchedPrimitives = &mTouchedBoxes;
+
+	// Now, do the actual query against leaf boxes
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+
+	// We only have a list of boxes so far
+	if(GetContactStatus())
+	{
+		// Reset contact status, since it currently only reflects collisions with leaf boxes
+		Collider::InitQuery();
+
+		// Change dest container so that we can use built-in overlap tests and get collided primitives
+		cache.TouchedPrimitives.Reset();
+		mTouchedPrimitives = &cache.TouchedPrimitives;
+
+		// Read touched leaf boxes
+		udword Nb = mTouchedBoxes.GetNbEntries();
+		const udword* Touched = mTouchedBoxes.GetEntries();
+
+		const LeafTriangles* LT = model.GetLeafTriangles();
+		const udword* Indices = model.GetIndices();
+
+		// Loop through touched leaves
+		while(Nb--)
+		{
+			const LeafTriangles& CurrentLeaf = LT[*Touched++];
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = *T++;
+					AABB_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = BaseIndex++;
+					AABB_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+		}
+	}
+
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_AABBCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_AABBCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_AABBCollider.h	(revision 216)
@@ -0,0 +1,97 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for an AABB collider.
+ *	\file		OPC_AABBCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 1st, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_AABBCOLLIDER_H__
+#define __OPC_AABBCOLLIDER_H__
+
+	struct OPCODE_API AABBCache : VolumeCache
+	{
+						AABBCache() : FatCoeff(1.1f)
+						{
+							FatBox.mCenter.Zero();
+							FatBox.mExtents.Zero();
+						}
+
+		// Cached faces signature
+		CollisionAABB	FatBox;		//!< Box used when performing the query resulting in cached faces
+		// User settings
+		float			FatCoeff;	//!< mRadius2 multiplier used to create a fat sphere
+	};
+
+	class OPCODE_API AABBCollider : public VolumeCollider
+	{
+		public:
+		// Constructor / Destructor
+											AABBCollider();
+		virtual								~AABBCollider();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic collision query for generic OPCODE models. After the call, access the results:
+		 *	- with GetContactStatus()
+		 *	- with GetNbTouchedPrimitives()
+		 *	- with GetTouchedPrimitives()
+		 *
+		 *	\param		cache			[in/out] a box cache
+		 *	\param		box				[in] collision AABB in world space
+		 *	\param		model			[in] Opcode model to collide with
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(AABBCache& cache, const CollisionAABB& box, const Model& model);
+		//
+							bool			Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree);
+		protected:
+							CollisionAABB	mBox;			//!< Query box in (center, extents) form
+							Point			mMin;			//!< Query box min point
+							Point			mMax;			//!< Query box max point
+		// Leaf description
+							Point			mLeafVerts[3];	//!< Triangle vertices
+		// Internal methods
+							void			_Collide(const AABBCollisionNode* node);
+							void			_Collide(const AABBNoLeafNode* node);
+							void			_Collide(const AABBQuantizedNode* node);
+							void			_Collide(const AABBQuantizedNoLeafNode* node);
+							void			_Collide(const AABBTreeNode* node);
+							void			_CollideNoPrimitiveTest(const AABBCollisionNode* node);
+							void			_CollideNoPrimitiveTest(const AABBNoLeafNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
+			// Overlap tests
+		inline_				BOOL			AABBContainsBox(const Point& bc, const Point& be);
+		inline_				BOOL			AABBAABBOverlap(const Point& b, const Point& Pb);
+		inline_				BOOL			TriBoxOverlap();
+			// Init methods
+							BOOL			InitQuery(AABBCache& cache, const CollisionAABB& box);
+	};
+
+	class OPCODE_API HybridAABBCollider : public AABBCollider
+	{
+		public:
+		// Constructor / Destructor
+											HybridAABBCollider();
+		virtual								~HybridAABBCollider();
+
+							bool			Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model);
+		protected:
+							Container		mTouchedBoxes;
+	};
+
+#endif // __OPC_AABBCOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_AABBTree.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_AABBTree.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_AABBTree.cpp	(revision 216)
@@ -0,0 +1,573 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a versatile AABB tree.
+ *	\file		OPC_AABBTree.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a generic AABB tree node.
+ *
+ *	\class		AABBTreeNode
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a generic AABB tree.
+ *	This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to
+ *	user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive
+ *	is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the
+ *	resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree
+ *	can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way).
+ *
+ *	\class		AABBTree
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBTreeNode::AABBTreeNode() :
+	mPos			(null),
+#ifndef OPC_NO_NEG_VANILLA_TREE
+	mNeg			(null),
+#endif
+	mNbPrimitives	(0),
+	mNodePrimitives	(null)
+{
+#ifdef OPC_USE_TREE_COHERENCE
+	mBitmask = 0;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBTreeNode::~AABBTreeNode()
+{
+	// Opcode 1.3:
+	const AABBTreeNode* Pos = GetPos();
+	const AABBTreeNode* Neg = GetNeg();
+#ifndef OPC_NO_NEG_VANILLA_TREE
+	if(!(mPos&1))	DELETESINGLE(Pos);
+	if(!(mNeg&1))	DELETESINGLE(Neg);
+#else
+	if(!(mPos&1))	DELETEARRAY(Pos);
+#endif
+	mNodePrimitives	= null;	// This was just a shortcut to the global list => no release
+	mNbPrimitives	= 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Splits the node along a given axis.
+ *	The list of indices is reorganized according to the split values.
+ *	\param		axis		[in] splitting axis index
+ *	\param		builder		[in] the tree builder
+ *	\return		the number of primitives assigned to the first child
+ *	\warning	this method reorganizes the internal list of primitives
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder)
+{
+	// Get node split value
+	float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis);
+
+	udword NbPos = 0;
+	// Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1].
+	// Those indices map the global list in the tree builder.
+	for(udword i=0;i<mNbPrimitives;i++)
+	{
+		// Get index in global list
+		udword Index = mNodePrimitives[i];
+
+		// Test against the splitting value. The primitive value is tested against the enclosing-box center.
+		// [We only need an approximate partition of the enclosing box here.]
+		float PrimitiveValue = builder->GetSplittingValue(Index, axis);
+
+		// Reorganize the list of indices in this order: positive - negative.
+		if(PrimitiveValue > SplitValue)
+		{
+			// Swap entries
+			udword Tmp = mNodePrimitives[i];
+			mNodePrimitives[i] = mNodePrimitives[NbPos];
+			mNodePrimitives[NbPos] = Tmp;
+			// Count primitives assigned to positive space
+			NbPos++;
+		}
+	}
+	return NbPos;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Subdivides the node.
+ *	
+ *	          N
+ *	        /   \
+ *	      /       \
+ *	   N/2         N/2
+ *	  /   \       /   \
+ *	N/4   N/4   N/4   N/4
+ *	(etc)
+ *
+ *	A well-balanced tree should have a O(log n) depth.
+ *	A degenerate tree would have a O(n) depth.
+ *	Note a perfectly-balanced tree is not well-suited to collision detection anyway.
+ *
+ *	\param		builder		[in] the tree builder
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder)
+{
+	// Checkings
+	if(!builder)	return false;
+
+	// Stop subdividing if we reach a leaf node. This is always performed here,
+	// else we could end in trouble if user overrides this.
+	if(mNbPrimitives==1)	return true;
+
+	// Let the user validate the subdivision
+	if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV))	return true;
+
+	bool ValidSplit = true;	// Optimism...
+	udword NbPos;
+	if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS)
+	{
+		// Find the largest axis to split along
+		Point Extents;	mBV.GetExtents(Extents);	// Box extents
+		udword Axis	= Extents.LargestAxis();		// Index of largest axis
+
+		// Split along the axis
+		NbPos = Split(Axis, builder);
+
+		// Check split validity
+		if(!NbPos || NbPos==mNbPrimitives)	ValidSplit = false;
+	}
+	else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS)
+	{
+		// Compute the means
+		Point Means(0.0f, 0.0f, 0.0f);
+		for(udword i=0;i<mNbPrimitives;i++)
+		{
+			udword Index = mNodePrimitives[i];
+			Means.x+=builder->GetSplittingValue(Index, 0);
+			Means.y+=builder->GetSplittingValue(Index, 1);
+			Means.z+=builder->GetSplittingValue(Index, 2);
+		}
+		Means/=float(mNbPrimitives);
+
+		// Compute variances
+		Point Vars(0.0f, 0.0f, 0.0f);
+		for(udword i=0;i<mNbPrimitives;i++)
+		{
+			udword Index = mNodePrimitives[i];
+			float Cx = builder->GetSplittingValue(Index, 0);
+			float Cy = builder->GetSplittingValue(Index, 1);
+			float Cz = builder->GetSplittingValue(Index, 2);
+			Vars.x += (Cx - Means.x)*(Cx - Means.x);
+			Vars.y += (Cy - Means.y)*(Cy - Means.y);
+			Vars.z += (Cz - Means.z)*(Cz - Means.z);
+		}
+		Vars/=float(mNbPrimitives-1);
+
+		// Choose axis with greatest variance
+		udword Axis = Vars.LargestAxis();
+
+		// Split along the axis
+		NbPos = Split(Axis, builder);
+
+		// Check split validity
+		if(!NbPos || NbPos==mNbPrimitives)	ValidSplit = false;
+	}
+	else if(builder->mSettings.mRules & SPLIT_BALANCED)
+	{
+		// Test 3 axis, take the best
+		float Results[3];
+		NbPos = Split(0, builder);	Results[0] = float(NbPos)/float(mNbPrimitives);
+		NbPos = Split(1, builder);	Results[1] = float(NbPos)/float(mNbPrimitives);
+		NbPos = Split(2, builder);	Results[2] = float(NbPos)/float(mNbPrimitives);
+		Results[0]-=0.5f;	Results[0]*=Results[0];
+		Results[1]-=0.5f;	Results[1]*=Results[1];
+		Results[2]-=0.5f;	Results[2]*=Results[2];
+		udword Min=0;
+		if(Results[1]<Results[Min])	Min = 1;
+		if(Results[2]<Results[Min])	Min = 2;
+		
+		// Split along the axis
+		NbPos = Split(Min, builder);
+
+		// Check split validity
+		if(!NbPos || NbPos==mNbPrimitives)	ValidSplit = false;
+	}
+	else if(builder->mSettings.mRules & SPLIT_BEST_AXIS)
+	{
+		// Test largest, then middle, then smallest axis...
+
+		// Sort axis
+		Point Extents;	mBV.GetExtents(Extents);	// Box extents
+		udword SortedAxis[] = { 0, 1, 2 };
+		float* Keys = (float*)&Extents.x;
+		for(udword j=0;j<3;j++)
+		{
+			for(udword i=0;i<2;i++)
+			{
+				if(Keys[SortedAxis[i]]<Keys[SortedAxis[i+1]])
+				{
+					udword Tmp = SortedAxis[i];
+					SortedAxis[i] = SortedAxis[i+1];
+					SortedAxis[i+1] = Tmp;
+				}
+			}
+		}
+
+		// Find the largest axis to split along
+		udword CurAxis = 0;
+		ValidSplit = false;
+		while(!ValidSplit && CurAxis!=3)
+		{
+			NbPos = Split(SortedAxis[CurAxis], builder);
+			// Check the subdivision has been successful
+			if(!NbPos || NbPos==mNbPrimitives)	CurAxis++;
+			else								ValidSplit = true;
+		}
+	}
+	else if(builder->mSettings.mRules & SPLIT_FIFTY)
+	{
+		// Don't even bother splitting (mainly a performance test)
+		NbPos = mNbPrimitives>>1;
+	}
+	else return false;	// Unknown splitting rules
+
+	// Check the subdivision has been successful
+	if(!ValidSplit)
+	{
+		// Here, all boxes lie in the same sub-space. Two strategies:
+		// - if the tree *must* be complete, make an arbitrary 50-50 split
+		// - else stop subdividing
+//		if(builder->mSettings.mRules&SPLIT_COMPLETE)
+		if(builder->mSettings.mLimit==1)
+		{
+			builder->IncreaseNbInvalidSplits();
+			NbPos = mNbPrimitives>>1;
+		}
+		else return true;
+	}
+
+	// Now create children and assign their pointers.
+	if(builder->mNodeBase)
+	{
+		// We use a pre-allocated linear pool for complete trees [Opcode 1.3]
+		AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase;
+		udword Count = builder->GetCount() - 1;	// Count begins to 1...
+		// Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives
+		ASSERT(!(udword(&Pool[Count+0])&1));
+		ASSERT(!(udword(&Pool[Count+1])&1));
+		mPos = size_t(&Pool[Count+0])|1;
+#ifndef OPC_NO_NEG_VANILLA_TREE
+		mNeg = size_t(&Pool[Count+1])|1;
+#endif
+	}
+	else
+	{
+		// Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly
+#ifndef OPC_NO_NEG_VANILLA_TREE
+		mPos = (size_t)new AABBTreeNode;	CHECKALLOC(mPos);
+		mNeg = (size_t)new AABBTreeNode;	CHECKALLOC(mNeg);
+#else
+		AABBTreeNode* PosNeg = new AABBTreeNode[2];
+		CHECKALLOC(PosNeg);
+		mPos = (size_t)PosNeg;
+#endif
+	}
+
+	// Update stats
+	builder->IncreaseCount(2);
+
+	// Assign children
+	AABBTreeNode* Pos = (AABBTreeNode*)GetPos();
+	AABBTreeNode* Neg = (AABBTreeNode*)GetNeg();
+	Pos->mNodePrimitives	= &mNodePrimitives[0];
+	Pos->mNbPrimitives		= NbPos;
+	Neg->mNodePrimitives	= &mNodePrimitives[NbPos];
+	Neg->mNbPrimitives		= mNbPrimitives - NbPos;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive hierarchy building in a top-down fashion.
+ *	\param		builder		[in] the tree builder
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder)
+{
+	// 1) Compute the global box for current node. The box is stored in mBV.
+	builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV);
+
+	// 2) Subdivide current node
+	Subdivide(builder);
+
+	// 3) Recurse
+	AABBTreeNode* Pos = (AABBTreeNode*)GetPos();
+	AABBTreeNode* Neg = (AABBTreeNode*)GetNeg();
+	if(Pos)	Pos->_BuildHierarchy(builder);
+	if(Neg)	Neg->_BuildHierarchy(builder);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the tree (top-down).
+ *	\param		builder		[in] the tree builder
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeNode::_Refit(AABBTreeBuilder* builder)
+{
+	// 1) Recompute the new global box for current node
+	builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV);
+
+	// 2) Recurse
+	AABBTreeNode* Pos = (AABBTreeNode*)GetPos();
+	AABBTreeNode* Neg = (AABBTreeNode*)GetNeg();
+	if(Pos)	Pos->_Refit(builder);
+	if(Neg)	Neg->_Refit(builder);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBTree::AABBTree() : mIndices(null), mTotalNbNodes(0), mPool(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBTree::~AABBTree()
+{
+	Release();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Releases the tree.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTree::Release()
+{
+	DELETEARRAY(mPool);
+	DELETEARRAY(mIndices);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds a generic AABB tree from a tree builder.
+ *	\param		builder		[in] the tree builder
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTree::Build(AABBTreeBuilder* builder)
+{
+	// Checkings
+	if(!builder || !builder->mNbPrimitives)	return false;
+
+	// Release previous tree
+	Release();
+
+	// Init stats
+	builder->SetCount(1);
+	builder->SetNbInvalidSplits(0);
+
+	// Initialize indices. This list will be modified during build.
+	mIndices = new udword[builder->mNbPrimitives];
+	CHECKALLOC(mIndices);
+	// Identity permutation
+	for(udword i=0;i<builder->mNbPrimitives;i++)	mIndices[i] = i;
+
+	// Setup initial node. Here we have a complete permutation of the app's primitives.
+	mNodePrimitives	= mIndices;
+	mNbPrimitives	= builder->mNbPrimitives;
+
+	// Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3]
+//	if(builder->mRules&SPLIT_COMPLETE)
+	if(builder->mSettings.mLimit==1)
+	{
+		// Allocate a pool of nodes
+		mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1];
+
+		builder->mNodeBase = mPool;	// ### ugly !
+	}
+
+	// Build the hierarchy
+	_BuildHierarchy(builder);
+
+	// Get back total number of nodes
+	mTotalNbNodes	= builder->GetCount();
+
+	// For complete trees, check the correct number of nodes has been created [Opcode 1.3]
+	if(mPool)	ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the depth of the tree.
+ *	A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth.
+ *	\return		depth of the tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword AABBTree::ComputeDepth() const
+{
+	return Walk(null, null);	// Use the walking code without callback
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Walks the tree, calling the user back for each node.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword AABBTree::Walk(WalkingCallback callback, void* user_data) const
+{
+	// Call it without callback to compute max depth
+	udword MaxDepth = 0;
+	udword CurrentDepth = 0;
+
+	struct Local
+	{
+		static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data)
+		{
+			// Checkings
+			if(!current_node)	return;
+			// Entering a new node => increase depth
+			current_depth++;
+			// Keep track of max depth
+			if(current_depth>max_depth)	max_depth = current_depth;
+
+			// Callback
+			if(callback && !(callback)(current_node, current_depth, user_data))	return;
+
+			// Recurse
+			if(current_node->GetPos())	{ _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data);	current_depth--;	}
+			if(current_node->GetNeg())	{ _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data);	current_depth--;	}
+		}
+	};
+	Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data);
+	return MaxDepth;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the tree in a top-down way.
+ *	\param		builder		[in] the tree builder
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTree::Refit(AABBTreeBuilder* builder)
+{
+	if(!builder)	return false;
+	_Refit(builder);
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the tree in a bottom-up way.
+ *	\param		builder		[in] the tree builder
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTree::Refit2(AABBTreeBuilder* builder)
+{
+	// Checkings
+	if(!builder)	return false;
+
+	ASSERT(mPool);
+
+	// Bottom-up update
+	Point Min,Max;
+	Point Min_,Max_;
+	udword Index = mTotalNbNodes;
+	while(Index--)
+	{
+		AABBTreeNode& Current = mPool[Index];
+
+		if(Current.IsLeaf())
+		{
+			builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *(AABB*)Current.GetAABB());
+		}
+		else
+		{
+			Current.GetPos()->GetAABB()->GetMin(Min);
+			Current.GetPos()->GetAABB()->GetMax(Max);
+
+			Current.GetNeg()->GetAABB()->GetMin(Min_);
+			Current.GetNeg()->GetAABB()->GetMax(Max_);
+
+			Min.Min(Min_);
+			Max.Max(Max_);
+
+			((AABB*)Current.GetAABB())->SetMinMax(Min, Max);
+		}
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the number of bytes used by the tree.
+ *	\return		number of bytes used
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword AABBTree::GetUsedBytes() const
+{
+	udword TotalSize = mTotalNbNodes*GetNodeSize();
+	if(mIndices)	TotalSize+=mNbPrimitives*sizeof(udword);
+	return TotalSize;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the tree is a complete tree or not.
+ *	A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree.
+ *	\return		true for complete trees
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTree::IsComplete() const
+{
+	return (GetNbNodes()==GetNbPrimitives()*2-1);
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_AABBTree.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_AABBTree.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_AABBTree.h	(revision 216)
@@ -0,0 +1,137 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a versatile AABB tree.
+ *	\file		OPC_AABBTree.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_AABBTREE_H__
+#define __OPC_AABBTREE_H__
+
+#ifdef OPC_NO_NEG_VANILLA_TREE
+	//! TO BE DOCUMENTED
+	#define IMPLEMENT_TREE(base_class, volume)																			\
+		public:																											\
+		/* Constructor / Destructor */																					\
+									base_class();																		\
+									~base_class();																		\
+		/* Data access */																								\
+		inline_	const volume*		Get##volume()	const	{ return &mBV;							}					\
+		/* Clear the last bit */																						\
+		inline_	const base_class*	GetPos()		const	{ return (const base_class*)(mPos&~1);	}					\
+		inline_	const base_class*	GetNeg()		const	{ const base_class* P = GetPos(); return P ? P+1 : null;}	\
+																														\
+		/* We don't need to test both nodes since we can't have one without the other	*/								\
+		inline_	bool				IsLeaf()		const	{ return !GetPos();						}					\
+																														\
+		/* Stats */																										\
+		inline_	udword				GetNodeSize()	const	{ return SIZEOFOBJECT;					}					\
+		protected:																										\
+		/* Tree-independent data */																						\
+		/* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/				\
+		/* Whatever happens we need the two children and the enclosing volume.*/										\
+				volume				mBV;		/* Global bounding-volume enclosing all the node-related primitives */	\
+				size_t				mPos;		/* "Positive" & "Negative" children */
+#else
+	//! TO BE DOCUMENTED
+	#define IMPLEMENT_TREE(base_class, volume)																			\
+		public:																											\
+		/* Constructor / Destructor */																					\
+									base_class();																		\
+									~base_class();																		\
+		/* Data access */																								\
+		inline_	const volume*		Get##volume()	const	{ return &mBV;							}					\
+		/* Clear the last bit */																						\
+		inline_	const base_class*	GetPos()		const	{ return (const base_class*)(mPos&~1);	}					\
+		inline_	const base_class*	GetNeg()		const	{ return (const base_class*)(mNeg&~1);	}					\
+																														\
+/*		inline_	bool				IsLeaf()		const	{ return (!GetPos() && !GetNeg());	}	*/					\
+		/* We don't need to test both nodes since we can't have one without the other	*/								\
+		inline_	bool				IsLeaf()		const	{ return !GetPos();						}					\
+																														\
+		/* Stats */																										\
+		inline_	udword				GetNodeSize()	const	{ return SIZEOFOBJECT;					}					\
+		protected:																										\
+		/* Tree-independent data */																						\
+		/* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/				\
+		/* Whatever happens we need the two children and the enclosing volume.*/										\
+				volume				mBV;		/* Global bounding-volume enclosing all the node-related primitives */	\
+				size_t				mPos;		/* "Positive" child */													\
+				size_t				mNeg;		/* "Negative" child */
+#endif
+
+	typedef		void				(*CullingCallback)		(udword nb_primitives, udword* node_primitives, BOOL need_clipping, void* user_data);
+
+	class OPCODE_API AABBTreeNode
+	{
+									IMPLEMENT_TREE(AABBTreeNode, AABB)
+		public:
+		// Data access
+		inline_	const udword*		GetPrimitives()		const	{ return mNodePrimitives;	}
+		inline_	udword				GetNbPrimitives()	const	{ return mNbPrimitives;		}
+
+		protected:
+		// Tree-dependent data
+				udword*				mNodePrimitives;	//!< Node-related primitives (shortcut to a position in mIndices below)
+				udword				mNbPrimitives;		//!< Number of primitives for this node
+		// Internal methods
+				udword				Split(udword axis, AABBTreeBuilder* builder);
+				bool				Subdivide(AABBTreeBuilder* builder);
+				void				_BuildHierarchy(AABBTreeBuilder* builder);
+				void				_Refit(AABBTreeBuilder* builder);
+	};
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	User-callback, called for each node by the walking code.
+	 *	\param		current		[in] current node
+	 *	\param		depth		[in] current node's depth
+	 *	\param		user_data	[in] user-defined data
+	 *	\return		true to recurse through children, else false to bypass them
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	typedef		bool				(*WalkingCallback)	(const AABBTreeNode* current, udword depth, void* user_data);
+
+	class OPCODE_API AABBTree : public AABBTreeNode
+	{
+		public:
+		// Constructor / Destructor
+									AABBTree();
+									~AABBTree();
+		// Build
+				bool				Build(AABBTreeBuilder* builder);
+				void				Release();
+
+		// Data access
+		inline_	const udword*		GetIndices()		const	{ return mIndices;		}	//!< Catch the indices
+		inline_	udword				GetNbNodes()		const	{ return mTotalNbNodes;	}	//!< Catch the number of nodes
+
+		// Infos
+				bool				IsComplete()		const;
+		// Stats
+				udword				ComputeDepth()		const;
+				udword				GetUsedBytes()		const;
+				udword				Walk(WalkingCallback callback, void* user_data) const;
+
+				bool				Refit(AABBTreeBuilder* builder);
+				bool				Refit2(AABBTreeBuilder* builder);
+		private:
+				udword*				mIndices;			//!< Indices in the app list. Indices are reorganized during build (permutation).
+				AABBTreeNode*		mPool;				//!< Linear pool of nodes for complete trees. Null otherwise. [Opcode 1.3]
+		// Stats
+				udword				mTotalNbNodes;		//!< Number of nodes in the tree.
+	};
+
+#endif // __OPC_AABBTREE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_BaseModel.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_BaseModel.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_BaseModel.cpp	(revision 216)
@@ -0,0 +1,138 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains base model interface.
+ *	\file		OPC_BaseModel.cpp
+ *	\author		Pierre Terdiman
+ *	\date		May, 18, 2003
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	The base class for collision models.
+ *
+ *	\class		BaseModel
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		May, 18, 2003
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OPCODECREATE::OPCODECREATE()
+{
+	mIMesh				= null;
+	mSettings.mRules	= SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER;
+	mSettings.mLimit	= 1;	// Mandatory for complete trees
+	mNoLeaf				= true;
+	mQuantized			= true;
+#ifdef __MESHMERIZER_H__
+	mCollisionHull		= false;
+#endif // __MESHMERIZER_H__
+	mKeepOriginal		= false;
+	mCanRemap			= false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BaseModel::~BaseModel()
+{
+	ReleaseBase();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Releases everything.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void BaseModel::ReleaseBase()
+{
+	DELETESINGLE(mSource);
+	DELETESINGLE(mTree);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Creates an optimized tree according to user-settings, and setups mModelCode.
+ *	\param		no_leaf		[in] true for "no leaf" tree
+ *	\param		quantized	[in] true for quantized tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool BaseModel::CreateTree(bool no_leaf, bool quantized)
+{
+	DELETESINGLE(mTree);
+
+	// Setup model code
+	if(no_leaf)		mModelCode |= OPC_NO_LEAF;
+	else			mModelCode &= ~OPC_NO_LEAF;
+
+	if(quantized)	mModelCode |= OPC_QUANTIZED;
+	else			mModelCode &= ~OPC_QUANTIZED;
+
+	// Create the correct class
+	if(mModelCode & OPC_NO_LEAF)
+	{
+		if(mModelCode & OPC_QUANTIZED)	mTree = new AABBQuantizedNoLeafTree;
+		else							mTree = new AABBNoLeafTree;
+	}
+	else
+	{
+		if(mModelCode & OPC_QUANTIZED)	mTree = new AABBQuantizedTree;
+		else							mTree = new AABBCollisionTree;
+	}
+	CHECKALLOC(mTree);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the collision model. This can be used to handle dynamic meshes. Usage is:
+ *	1. modify your mesh vertices (keep the topology constant!)
+ *	2. refit the tree (call this method)
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool BaseModel::Refit()
+{
+	// Refit the optimized tree
+	return mTree->Refit(mIMesh);
+
+// Old code kept for reference : refit the source tree then rebuild !
+//	if(!mSource)	return false;
+//	// Ouch...
+//	mSource->Refit(&mTB);
+//	// Ouch...
+//	return mTree->Build(mSource);
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_BaseModel.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_BaseModel.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_BaseModel.h	(revision 216)
@@ -0,0 +1,175 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains base model interface.
+ *	\file		OPC_BaseModel.h
+ *	\author		Pierre Terdiman
+ *	\date		May, 18, 2003
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_BASEMODEL_H__
+#define __OPC_BASEMODEL_H__
+
+	//! Model creation structure
+	struct OPCODE_API OPCODECREATE
+	{
+		//! Constructor
+								OPCODECREATE();
+
+		MeshInterface*			mIMesh;			//!< Mesh interface (access to triangles & vertices) (*)
+		BuildSettings			mSettings;		//!< Builder's settings
+		bool					mNoLeaf;		//!< true => discard leaf nodes (else use a normal tree)
+		bool					mQuantized;		//!< true => quantize the tree (else use a normal tree)
+#ifdef __MESHMERIZER_H__
+		bool					mCollisionHull;	//!< true => use convex hull + GJK
+#endif // __MESHMERIZER_H__
+		bool					mKeepOriginal;	//!< true => keep a copy of the original tree (debug purpose)
+		bool					mCanRemap;		//!< true => allows OPCODE to reorganize client arrays
+
+		// (*) This pointer is saved internally and used by OPCODE until collision structures are released,
+		// so beware of the object's lifetime.
+	};
+
+	enum ModelFlag
+	{
+		OPC_QUANTIZED	= (1<<0),	//!< Compressed/uncompressed tree
+		OPC_NO_LEAF		= (1<<1),	//!< Leaf/NoLeaf tree
+		OPC_SINGLE_NODE	= (1<<2)	//!< Special case for 1-node models
+	};
+
+	class OPCODE_API BaseModel
+	{
+		public:
+		// Constructor/Destructor
+											BaseModel();
+		virtual								~BaseModel();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Builds a collision model.
+		 *	\param		create		[in] model creation structure
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual			bool				Build(const OPCODECREATE& create)	= 0;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the number of bytes used by the tree.
+		 *	\return		amount of bytes used
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual			udword				GetUsedBytes()		const			= 0;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Refits the collision model. This can be used to handle dynamic meshes. Usage is:
+		 *	1. modify your mesh vertices (keep the topology constant!)
+		 *	2. refit the tree (call this method)
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual			bool				Refit();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the source tree.
+		 *	\return		generic tree
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	const	AABBTree*			GetSourceTree()		const	{ return mSource;						}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the tree.
+		 *	\return		the collision tree
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	const	AABBOptimizedTree*	GetTree()			const	{ return mTree;							}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the tree.
+		 *	\return		the collision tree
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			AABBOptimizedTree*	GetTree()					{ return mTree;							}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the number of nodes in the tree.
+		 *	Should be 2*N-1 for normal trees and N-1 for optimized ones.
+		 *	\return		number of nodes
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			udword				GetNbNodes()		const	{ return mTree->GetNbNodes();			}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks whether the tree has leaf nodes or not.
+		 *	\return		true if the tree has leaf nodes (normal tree), else false (optimized tree)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL				HasLeafNodes()		const	{ return !(mModelCode & OPC_NO_LEAF);	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks whether the tree is quantized or not.
+		 *	\return		true if the tree is quantized
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL				IsQuantized()		const	{ return mModelCode & OPC_QUANTIZED;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks whether the model has a single node or not. This special case must be handled separately.
+		 *	\return		true if the model has only 1 node
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			BOOL				HasSingleNode()		const	{ return mModelCode & OPC_SINGLE_NODE;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the model's code.
+		 *	\return		model's code
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			udword				GetModelCode()		const	{ return mModelCode;					}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the mesh interface.
+		 *	\return		mesh interface
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	const	MeshInterface*		GetMeshInterface()	const						{ return mIMesh;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Sets the mesh interface.
+		 *	\param		imesh		[in] mesh interface
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void				SetMeshInterface(const MeshInterface* imesh)	{ mIMesh = imesh;	}
+
+		protected:
+				const	MeshInterface*		mIMesh;			//!< User-defined mesh interface
+						udword				mModelCode;		//!< Model code = combination of ModelFlag(s)
+						AABBTree*			mSource;		//!< Original source tree
+						AABBOptimizedTree*	mTree;			//!< Optimized tree owned by the model
+		// Internal methods
+						void				ReleaseBase();
+						bool				CreateTree(bool no_leaf, bool quantized);
+	};
+
+#endif //__OPC_BASEMODEL_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_BoxBoxOverlap.h	(revision 216)
@@ -0,0 +1,122 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	OBB-OBB overlap test using the separating axis theorem.
+ *	- original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID)
+ *	- optimized for AABB trees by computing the rotation matrix once (SOLID-fashion)
+ *	- the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory)
+ *	- Class III axes can be disabled... (SOLID & Intel fashion)
+ *	- ...or enabled to perform some profiling
+ *	- CPU comparisons used when appropriate
+ *	- lazy evaluation sometimes saves some work in case of early exits (unlike SOLID)
+ *
+ *	\param		ea	[in] extents from box A
+ *	\param		ca	[in] center from box A
+ *	\param		eb	[in] extents from box B
+ *	\param		cb	[in] center from box B
+ *	\return		true if boxes overlap
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb)
+{
+	// Stats
+	mNbBVBVTests++;
+
+	float t,t2;
+
+	// Class I : A's basis vectors
+	float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x;
+	t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0];
+	if(GREATER(Tx, t))	return FALSE;
+
+	float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y;
+	t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1];
+	if(GREATER(Ty, t))	return FALSE;
+
+	float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z;
+	t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2];
+	if(GREATER(Tz, t))	return FALSE;
+
+	// Class II : B's basis vectors
+	t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2];	t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x;
+	if(GREATER(t, t2))	return FALSE;
+
+	t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2];	t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y;
+	if(GREATER(t, t2))	return FALSE;
+
+	t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2];	t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z;
+	if(GREATER(t, t2))	return FALSE;
+
+	// Class III : 9 cross products
+	// Cool trick: always perform the full test for first level, regardless of settings.
+	// That way pathological cases (such as the pencils scene) are quickly rejected anyway !
+	if(mFullBoxBoxTest || mNbBVBVTests==1)
+	{
+		t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2];	t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0];	if(GREATER(t, t2))	return FALSE;	// L = A0 x B0
+		t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2];	t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0];	if(GREATER(t, t2))	return FALSE;	// L = A0 x B1
+		t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2];	t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0];	if(GREATER(t, t2))	return FALSE;	// L = A0 x B2
+		t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0];	t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1];	if(GREATER(t, t2))	return FALSE;	// L = A1 x B0
+		t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0];	t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1];	if(GREATER(t, t2))	return FALSE;	// L = A1 x B1
+		t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0];	t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1];	if(GREATER(t, t2))	return FALSE;	// L = A1 x B2
+		t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1];	t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2];	if(GREATER(t, t2))	return FALSE;	// L = A2 x B0
+		t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1];	t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2];	if(GREATER(t, t2))	return FALSE;	// L = A2 x B1
+		t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1];	t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2];	if(GREATER(t, t2))	return FALSE;	// L = A2 x B2
+	}
+	return TRUE;
+}
+
+//! A dedicated version when one box is constant
+inline_ BOOL OBBCollider::BoxBoxOverlap(const Point& extents, const Point& center)
+{
+	// Stats
+	mNbVolumeBVTests++;
+
+	float t,t2;
+
+	// Class I : A's basis vectors
+	float Tx = mTBoxToModel.x - center.x;	t = extents.x + mBBx1;	if(GREATER(Tx, t))	return FALSE;
+	float Ty = mTBoxToModel.y - center.y;	t = extents.y + mBBy1;	if(GREATER(Ty, t))	return FALSE;
+	float Tz = mTBoxToModel.z - center.z;	t = extents.z + mBBz1;	if(GREATER(Tz, t))	return FALSE;
+
+	// Class II : B's basis vectors
+	t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2];
+	t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x;
+	if(GREATER(t, t2))	return FALSE;
+
+	t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2];
+	t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y;
+	if(GREATER(t, t2))	return FALSE;
+
+	t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2];
+	t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z;
+	if(GREATER(t, t2))	return FALSE;
+
+	// Class III : 9 cross products
+	// Cool trick: always perform the full test for first level, regardless of settings.
+	// That way pathological cases (such as the pencils scene) are quickly rejected anyway !
+	if(mFullBoxBoxTest || mNbVolumeBVTests==1)
+	{
+		t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2];	t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1;	if(GREATER(t, t2))	return FALSE;	// L = A0 x B0
+		t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2];	t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2;	if(GREATER(t, t2))	return FALSE;	// L = A0 x B1
+		t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2];	t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3;	if(GREATER(t, t2))	return FALSE;	// L = A0 x B2
+		t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0];	t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4;	if(GREATER(t, t2))	return FALSE;	// L = A1 x B0
+		t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0];	t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5;	if(GREATER(t, t2))	return FALSE;	// L = A1 x B1
+		t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0];	t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6;	if(GREATER(t, t2))	return FALSE;	// L = A1 x B2
+		t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1];	t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7;	if(GREATER(t, t2))	return FALSE;	// L = A2 x B0
+		t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1];	t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8;	if(GREATER(t, t2))	return FALSE;	// L = A2 x B1
+		t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1];	t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9;	if(GREATER(t, t2))	return FALSE;	// L = A2 x B2
+	}
+	return TRUE;
+}
+
+//! A special version for 2 axis-aligned boxes
+inline_ BOOL AABBCollider::AABBAABBOverlap(const Point& extents, const Point& center)
+{
+	// Stats
+	mNbVolumeBVTests++;
+
+	float tx = mBox.mCenter.x - center.x;	float ex = extents.x + mBox.mExtents.x;	if(GREATER(tx, ex))	return FALSE;
+	float ty = mBox.mCenter.y - center.y;	float ey = extents.y + mBox.mExtents.y;	if(GREATER(ty, ey))	return FALSE;
+	float tz = mBox.mCenter.z - center.z;	float ez = extents.z + mBox.mExtents.z;	if(GREATER(tz, ez))	return FALSE;
+
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_BoxPruning.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_BoxPruning.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_BoxPruning.cpp	(revision 216)
@@ -0,0 +1,367 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for box pruning.
+ *	\file		IceBoxPruning.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	You could use a complex sweep-and-prune as implemented in I-Collide.
+	You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems.
+	You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2.
+
+	Or you could use this.
+	Faster ? I don't know. Probably not. It would be a shame. But who knows ?
+	Easier ? Definitely. Enjoy the sheer simplicity.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+*/
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+	inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max)
+	{
+		int First=index;
+		while(First<=last)
+		{
+			index = (First+last)>>1;
+
+			if(max>array[sorted[index]])	First	= index+1;
+			else							last	= index-1;
+		}
+	}
+// ### could be log(n) !
+// and maybe use cmp integers
+
+// InsertionSort has better coherence, RadixSort is better for one-shot queries.
+#define PRUNING_SORTER	RadixSort
+//#define PRUNING_SORTER	InsertionSort
+
+// Static for coherence
+static PRUNING_SORTER* gCompletePruningSorter = null;
+static PRUNING_SORTER* gBipartitePruningSorter0 = null;
+static PRUNING_SORTER* gBipartitePruningSorter1 = null;
+inline_ PRUNING_SORTER* GetCompletePruningSorter()
+{
+	if(!gCompletePruningSorter)	gCompletePruningSorter = new PRUNING_SORTER;
+	return gCompletePruningSorter;
+}
+inline_ PRUNING_SORTER* GetBipartitePruningSorter0()
+{
+	if(!gBipartitePruningSorter0)	gBipartitePruningSorter0 = new PRUNING_SORTER;
+	return gBipartitePruningSorter0;
+}
+inline_ PRUNING_SORTER* GetBipartitePruningSorter1()
+{
+	if(!gBipartitePruningSorter1)	gBipartitePruningSorter1 = new PRUNING_SORTER;
+	return gBipartitePruningSorter1;
+}
+void ReleasePruningSorters()
+{
+	DELETESINGLE(gBipartitePruningSorter1);
+	DELETESINGLE(gBipartitePruningSorter0);
+	DELETESINGLE(gCompletePruningSorter);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+ *	\param		nb0		[in] number of boxes in the first set
+ *	\param		array0	[in] array of boxes for the first set
+ *	\param		nb1		[in] number of boxes in the second set
+ *	\param		array1	[in] array of boxes for the second set
+ *	\param		pairs	[out] array of overlapping pairs
+ *	\param		axes	[in] projection order (0,2,1 is often best)
+ *	\return		true if success.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes)
+{
+	// Checkings
+	if(!nb0 || !array0 || !nb1 || !array1)	return false;
+
+	// Catch axes
+	udword Axis0 = axes.mAxis0;
+	udword Axis1 = axes.mAxis1;
+	udword Axis2 = axes.mAxis2;
+
+	// Allocate some temporary data
+	float* MinPosList0 = new float[nb0];
+	float* MinPosList1 = new float[nb1];
+
+	// 1) Build main lists using the primary axis
+	for(udword i=0;i<nb0;i++)	MinPosList0[i] = array0[i]->GetMin(Axis0);
+	for(udword i=0;i<nb1;i++)	MinPosList1[i] = array1[i]->GetMin(Axis0);
+
+	// 2) Sort the lists
+	PRUNING_SORTER* RS0 = GetBipartitePruningSorter0();
+	PRUNING_SORTER* RS1 = GetBipartitePruningSorter1();
+	const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks();
+	const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks();
+
+	// 3) Prune the lists
+	udword Index0, Index1;
+
+	const udword* const LastSorted0 = &Sorted0[nb0];
+	const udword* const LastSorted1 = &Sorted1[nb1];
+	const udword* RunningAddress0 = Sorted0;
+	const udword* RunningAddress1 = Sorted1;
+
+	while(RunningAddress1<LastSorted1 && Sorted0<LastSorted0)
+	{
+		Index0 = *Sorted0++;
+
+		while(RunningAddress1<LastSorted1 && MinPosList1[*RunningAddress1]<MinPosList0[Index0])	RunningAddress1++;
+
+		const udword* RunningAddress2_1 = RunningAddress1;
+
+		while(RunningAddress2_1<LastSorted1 && MinPosList1[Index1 = *RunningAddress2_1++]<=array0[Index0]->GetMax(Axis0))
+		{
+			if(array0[Index0]->Intersect(*array1[Index1], Axis1))
+			{
+				if(array0[Index0]->Intersect(*array1[Index1], Axis2))
+				{
+					pairs.AddPair(Index0, Index1);
+				}
+			}
+		}
+	}
+
+	////
+
+	while(RunningAddress0<LastSorted0 && Sorted1<LastSorted1)
+	{
+		Index0 = *Sorted1++;
+
+		while(RunningAddress0<LastSorted0 && MinPosList0[*RunningAddress0]<=MinPosList1[Index0])	RunningAddress0++;
+
+		const udword* RunningAddress2_0 = RunningAddress0;
+
+		while(RunningAddress2_0<LastSorted0 && MinPosList0[Index1 = *RunningAddress2_0++]<=array1[Index0]->GetMax(Axis0))
+		{
+			if(array0[Index1]->Intersect(*array1[Index0], Axis1))
+			{
+				if(array0[Index1]->Intersect(*array1[Index0], Axis2))
+				{
+					pairs.AddPair(Index1, Index0);
+				}
+			}
+
+		}
+	}
+
+	DELETEARRAY(MinPosList1);
+	DELETEARRAY(MinPosList0);
+
+	return true;
+}
+
+#define ORIGINAL_VERSION
+//#define JOAKIM
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+ *	\param		nb		[in] number of boxes
+ *	\param		array	[in] array of boxes
+ *	\param		pairs	[out] array of overlapping pairs
+ *	\param		axes	[in] projection order (0,2,1 is often best)
+ *	\return		true if success.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes)
+{
+	// Checkings
+	if(!nb || !array)	return false;
+
+	// Catch axes
+	udword Axis0 = axes.mAxis0;
+	udword Axis1 = axes.mAxis1;
+	udword Axis2 = axes.mAxis2;
+
+#ifdef ORIGINAL_VERSION
+	// Allocate some temporary data
+//	float* PosList = new float[nb];
+	float* PosList = new float[nb+1];
+
+	// 1) Build main list using the primary axis
+	for(udword i=0;i<nb;i++)	PosList[i] = array[i]->GetMin(Axis0);
+PosList[nb++] = MAX_FLOAT;
+
+	// 2) Sort the list
+	PRUNING_SORTER* RS = GetCompletePruningSorter();
+	const udword* Sorted = RS->Sort(PosList, nb).GetRanks();
+
+	// 3) Prune the list
+	const udword* const LastSorted = &Sorted[nb];
+	const udword* RunningAddress = Sorted;
+	udword Index0, Index1;
+	while(RunningAddress<LastSorted && Sorted<LastSorted)
+	{
+		Index0 = *Sorted++;
+
+//		while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
+		while(PosList[*RunningAddress++]<PosList[Index0]);
+
+		if(RunningAddress<LastSorted)
+		{
+			const udword* RunningAddress2 = RunningAddress;
+
+//			while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
+			while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
+			{
+//				if(Index0!=Index1)
+//				{
+					if(array[Index0]->Intersect(*array[Index1], Axis1))
+					{
+						if(array[Index0]->Intersect(*array[Index1], Axis2))
+						{
+							pairs.AddPair(Index0, Index1);
+						}
+					}
+//				}
+			}
+		}
+	}
+
+	DELETEARRAY(PosList);
+#endif
+
+#ifdef JOAKIM
+	// Allocate some temporary data
+//	float* PosList = new float[nb];
+	float* MinList = new float[nb+1];
+
+	// 1) Build main list using the primary axis
+	for(udword i=0;i<nb;i++)	MinList[i] = array[i]->GetMin(Axis0);
+	MinList[nb] = MAX_FLOAT;
+
+	// 2) Sort the list
+	PRUNING_SORTER* RS = GetCompletePruningSorter();
+	udword* Sorted = RS->Sort(MinList, nb+1).GetRanks();
+
+	// 3) Prune the list
+//	const udword* const LastSorted = &Sorted[nb];
+//	const udword* const LastSorted = &Sorted[nb-1];
+	const udword* RunningAddress = Sorted;
+	udword Index0, Index1;
+
+//	while(RunningAddress<LastSorted && Sorted<LastSorted)
+//	while(RunningAddress<LastSorted)
+	while(RunningAddress<&Sorted[nb])
+//	while(Sorted<LastSorted)
+	{
+//		Index0 = *Sorted++;
+		Index0 = *RunningAddress++;
+
+//		while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
+//		while(PosList[*RunningAddress++]<PosList[Index0]);
+//RunningAddress = Sorted;
+//		if(RunningAddress<LastSorted)
+		{
+			const udword* RunningAddress2 = RunningAddress;
+
+//			while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
+
+//			float CurrentMin = array[Index0]->GetMin(Axis0);
+			float CurrentMax = array[Index0]->GetMax(Axis0);
+
+			while(MinList[Index1 = *RunningAddress2] <= CurrentMax)
+//			while(PosList[Index1 = *RunningAddress] <= CurrentMax)
+			{
+//				if(Index0!=Index1)
+//				{
+					if(array[Index0]->Intersect(*array[Index1], Axis1))
+					{
+						if(array[Index0]->Intersect(*array[Index1], Axis2))
+						{
+							pairs.AddPair(Index0, Index1);
+						}
+					}
+//				}
+
+				RunningAddress2++;
+//				RunningAddress++;
+			}
+		}
+	}
+
+	DELETEARRAY(MinList);
+#endif
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Brute-force versions are kept:
+// - to check the optimized versions return the correct list of intersections
+// - to check the speed of the optimized code against the brute-force one
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set.
+ *	\param		nb0		[in] number of boxes in the first set
+ *	\param		array0	[in] array of boxes for the first set
+ *	\param		nb1		[in] number of boxes in the second set
+ *	\param		array1	[in] array of boxes for the second set
+ *	\param		pairs	[out] array of overlapping pairs
+ *	\return		true if success.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs)
+{
+	// Checkings
+	if(!nb0 || !array0 || !nb1 || !array1)	return false;
+
+	// Brute-force nb0*nb1 overlap tests
+	for(udword i=0;i<nb0;i++)
+	{
+		for(udword j=0;j<nb1;j++)
+		{
+			if(array0[i]->Intersect(*array1[j]))	pairs.AddPair(i, j);
+		}
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set.
+ *	\param		nb		[in] number of boxes
+ *	\param		array	[in] array of boxes
+ *	\param		pairs	[out] array of overlapping pairs
+ *	\return		true if success.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs)
+{
+	// Checkings
+	if(!nb || !array)	return false;
+
+	// Brute-force n(n-1)/2 overlap tests
+	for(udword i=0;i<nb;i++)
+	{
+		for(udword j=i+1;j<nb;j++)
+		{
+			if(array[i]->Intersect(*array[j]))	pairs.AddPair(i, j);
+		}
+	}
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_BoxPruning.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_BoxPruning.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_BoxPruning.h	(revision 216)
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for box pruning.
+ *	\file		IceBoxPruning.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_BOXPRUNING_H__
+#define __OPC_BOXPRUNING_H__
+
+	// Optimized versions
+	FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes);
+	FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes);
+
+	// Brute-force versions
+	FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs);
+	FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs);
+
+#endif //__OPC_BOXPRUNING_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Collider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Collider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Collider.cpp	(revision 216)
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains base collider class.
+ *	\file		OPC_Collider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains the abstract class for colliders.
+ *
+ *	\class		Collider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		June, 2, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Collider::Collider() :
+	mFlags			(0),
+	mCurrentModel	(null),
+	mIMesh			(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Collider::~Collider()
+{
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Collider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Collider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Collider.h	(revision 216)
@@ -0,0 +1,176 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains base collider class.
+ *	\file		OPC_Collider.h
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_COLLIDER_H__
+#define __OPC_COLLIDER_H__
+
+	enum CollisionFlag
+	{
+		OPC_FIRST_CONTACT		= (1<<0),		//!< Report all contacts (false) or only first one (true)
+		OPC_TEMPORAL_COHERENCE	= (1<<1),		//!< Use temporal coherence or not
+		OPC_CONTACT				= (1<<2),		//!< Final contact status after a collision query
+		OPC_TEMPORAL_HIT		= (1<<3),		//!< There has been an early exit due to temporal coherence
+		OPC_NO_PRIMITIVE_TESTS	= (1<<4),		//!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries)
+
+		OPC_CONTACT_FOUND		= OPC_FIRST_CONTACT | OPC_CONTACT,
+		OPC_TEMPORAL_CONTACT	= OPC_TEMPORAL_HIT | OPC_CONTACT,
+
+		OPC_FORCE_DWORD			= 0x7fffffff
+	};
+
+	class OPCODE_API Collider
+	{
+		public:
+		// Constructor / Destructor
+											Collider();
+		virtual								~Collider();
+
+		// Collision report
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the last collision status after a collision query.
+		 *	\return		true if a collision occured
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			GetContactStatus()			const	{ return mFlags & OPC_CONTACT;							}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the "first contact" mode.
+		 *	\return		true if "first contact" mode is on
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			FirstContactEnabled()		const	{ return mFlags & OPC_FIRST_CONTACT;					}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the temporal coherence mode.
+		 *	\return		true if temporal coherence is on
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			TemporalCoherenceEnabled()	const	{ return mFlags & OPC_TEMPORAL_COHERENCE;				}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks a first contact has already been found.
+		 *	\return		true if a first contact has been found and we can stop a query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			ContactFound()				const	{ return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks there's been an early exit due to temporal coherence;
+		 *	\return		true if a temporal hit has occured
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			TemporalHit()				const	{ return mFlags & OPC_TEMPORAL_HIT;						}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks primitive tests are enabled;
+		 *	\return		true if primitive tests must be skipped
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			SkipPrimitiveTests()		const	{ return mFlags & OPC_NO_PRIMITIVE_TESTS;				}
+
+		// Settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Reports all contacts (false) or first contact only (true)
+		 *	\param		flag		[in] true for first contact, false for all contacts
+		 *	\see		SetTemporalCoherence(bool flag)
+		 *	\see		ValidateSettings()
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetFirstContact(bool flag)
+											{
+												if(flag)	mFlags |= OPC_FIRST_CONTACT;
+												else		mFlags &= ~OPC_FIRST_CONTACT;
+											}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Enable/disable temporal coherence.
+		 *	\param		flag		[in] true to enable temporal coherence, false to discard it
+		 *	\see		SetFirstContact(bool flag)
+		 *	\see		ValidateSettings()
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetTemporalCoherence(bool flag)
+											{
+												if(flag)	mFlags |= OPC_TEMPORAL_COHERENCE;
+												else		mFlags &= ~OPC_TEMPORAL_COHERENCE;
+											}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Enable/disable primitive tests.
+		 *	\param		flag		[in] true to enable primitive tests, false to discard them
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetPrimitiveTests(bool flag)
+											{
+												if(!flag)	mFlags |= OPC_NO_PRIMITIVE_TESTS;
+												else		mFlags &= ~OPC_NO_PRIMITIVE_TESTS;
+											}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
+		 *	\return		null if everything is ok, else a string describing the problem
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual				const char*		ValidateSettings()	= 0;
+
+		protected:
+							udword			mFlags;			//!< Bit flags
+					const	BaseModel*		mCurrentModel;	//!< Current model for collision query (owner of touched faces)
+		// User mesh interface
+					const	MeshInterface*	mIMesh;			//!< User-defined mesh interface
+
+		// Internal methods
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups current collision model
+		 *	\param		model	[in] current collision model
+		 *	\return		TRUE if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				BOOL			Setup(const BaseModel* model)
+											{
+												// Keep track of current model
+												mCurrentModel = model;
+												if(!mCurrentModel)	return FALSE;
+
+												mIMesh = model->GetMeshInterface();
+												return mIMesh!=null;
+											}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Initializes a query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual inline_		void			InitQuery()		{ mFlags &= ~OPC_TEMPORAL_CONTACT;	}
+	};
+
+#endif // __OPC_COLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Common.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Common.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Common.cpp	(revision 216)
@@ -0,0 +1,48 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains common classes & defs used in OPCODE.
+ *	\file		OPC_Common.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	An AABB dedicated to collision detection.
+ *	We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends
+ *	on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth
+ *	using an extra special class.
+ *
+ *	\class		CollisionAABB
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A quantized AABB.
+ *	Center/Extent model, using 16-bits integers.
+ *
+ *	\class		QuantizedAABB
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Common.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Common.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Common.h	(revision 216)
@@ -0,0 +1,101 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains common classes & defs used in OPCODE.
+ *	\file		OPC_Common.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_COMMON_H__
+#define __OPC_COMMON_H__
+
+// [GOTTFRIED]: Just a small change for readability.
+#ifdef OPC_CPU_COMPARE
+	#define GREATER(x, y)	AIR(x) > IR(y)
+#else
+	#define GREATER(x, y)	fabsf(x) > (y)
+#endif
+
+	class OPCODE_API CollisionAABB
+	{
+		public:
+		//! Constructor
+		inline_				CollisionAABB()						{}
+		//! Constructor
+		inline_				CollisionAABB(const AABB& b)		{ b.GetCenter(mCenter);	b.GetExtents(mExtents);	}
+		//! Destructor
+		inline_				~CollisionAABB()					{}
+
+		//! Get min point of the box
+		inline_	void		GetMin(Point& min)		const		{ min = mCenter - mExtents;					}
+		//! Get max point of the box
+		inline_	void		GetMax(Point& max)		const		{ max = mCenter + mExtents;					}
+
+		//! Get component of the box's min point along a given axis
+		inline_	float		GetMin(udword axis)		const		{ return mCenter[axis] - mExtents[axis];	}
+		//! Get component of the box's max point along a given axis
+		inline_	float		GetMax(udword axis)		const		{ return mCenter[axis] + mExtents[axis];	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Setups an AABB from min & max vectors.
+		 *	\param		min			[in] the min point
+		 *	\param		max			[in] the max point
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	void		SetMinMax(const Point& min, const Point& max)		{ mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f;		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks a box is inside another box.
+		 *	\param		box		[in] the other box
+		 *	\return		true if current box is inside input box
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	BOOL		IsInside(const CollisionAABB& box) const
+							{
+								if(box.GetMin(0)>GetMin(0))	return FALSE;
+								if(box.GetMin(1)>GetMin(1))	return FALSE;
+								if(box.GetMin(2)>GetMin(2))	return FALSE;
+								if(box.GetMax(0)<GetMax(0))	return FALSE;
+								if(box.GetMax(1)<GetMax(1))	return FALSE;
+								if(box.GetMax(2)<GetMax(2))	return FALSE;
+								return TRUE;
+							}
+
+				Point		mCenter;				//!< Box center
+				Point		mExtents;				//!< Box extents
+	};
+
+	class OPCODE_API QuantizedAABB
+	{
+		public:
+		//! Constructor
+		inline_				QuantizedAABB()			{}
+		//! Destructor
+		inline_				~QuantizedAABB()		{}
+
+				sword		mCenter[3];				//!< Quantized center
+				uword		mExtents[3];			//!< Quantized extents
+	};
+
+	//! Quickly rotates & translates a vector
+	inline_ void TransformPoint(Point& dest, const Point& source, const Matrix3x3& rot, const Point& trans)
+	{
+		dest.x = trans.x + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
+		dest.y = trans.y + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
+		dest.z = trans.z + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
+	}
+
+#endif //__OPC_COMMON_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_HybridModel.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_HybridModel.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_HybridModel.cpp	(revision 216)
@@ -0,0 +1,466 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for hybrid models.
+ *	\file		OPC_HybridModel.cpp
+ *	\author		Pierre Terdiman
+ *	\date		May, 18, 2003
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	An hybrid collision model.
+ *	
+ *	The problem :
+ *	
+ *	Opcode really shines for mesh-mesh collision, especially when meshes are deeply overlapping
+ *	(it typically outperforms RAPID in those cases).
+ *	
+ *	Unfortunately this is not the typical scenario in games.
+ *	
+ *	For close-proximity cases, especially for volume-mesh queries, it's relatively easy to run faster
+ *	than Opcode, that suffers from a relatively high setup time.
+ *	
+ *	In particular, Opcode's "vanilla" trees in those cases -can- run faster. They can also use -less-
+ *	memory than the optimized ones, when you let the system stop at ~10 triangles / leaf for example
+ *	(i.e. when you don't use "complete" trees). However, those trees tend to fragment memory quite a
+ *	lot, increasing cache misses : since they're not "complete", we can't predict the final number of
+ *	nodes and we have to allocate nodes on-the-fly. For the same reasons we can't use Opcode's "optimized"
+ *	trees here, since they rely on a known layout to perform the "optimization".
+ *	
+ *	Hybrid trees :
+ *	
+ *	Hybrid trees try to combine best of both worlds :
+ *	
+ *	- they use a maximum limit of 16 triangles/leaf. "16" is used so that we'll be able to save the
+ *	number of triangles using 4 bits only.
+ *	
+ *	- they're still "complete" trees thanks to a two-passes building phase. First we create a "vanilla"
+ *	AABB-tree with Opcode, limited to 16 triangles/leaf. Then we create a *second* vanilla tree, this
+ *	time using the leaves of the first one. The trick is : this second tree is now "complete"... so we
+ *	can further transform it into an Opcode's optimized tree.
+ *	
+ *	- then we run the collision queries on that standard Opcode tree. The only difference is that leaf
+ *	nodes contain indices to leaf nodes of another tree. Also, we have to skip all primitive tests in
+ *	Opcode optimized trees, since our leaves don't contain triangles anymore.
+ *	
+ *	- finally, for each collided leaf, we simply loop through 16 triangles max, and collide them with
+ *	the bounding volume used in the query (we only support volume-vs-mesh queries here, not mesh-vs-mesh)
+ *	
+ *	All of that is wrapped in this "hybrid model" that contains the minimal data required for this to work.
+ *	It's a mix between old "vanilla" trees, and old "optimized" trees.
+ *
+ *	Extra advantages:
+ *
+ *	- If we use them for dynamic models, we're left with a very small number of leaf nodes to refit. It
+ *	might be a bit faster since we have less nodes to write back.
+ *
+ *	- In rigid body simulation, using temporal coherence and sleeping objects greatly reduce the actual
+ *	influence of one tree over another (i.e. the speed difference is often invisible). So memory is really
+ *	the key element to consider, and in this regard hybrid trees are just better.
+ *	
+ *	Information to take home:
+ *	- they use less ram
+ *	- they're not slower (they're faster or slower depending on cases, overall there's no significant
+ *	difference *as long as objects don't interpenetrate too much* - in which case Opcode's optimized trees
+ *	are still notably faster)
+ *
+ *	\class		HybridModel
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		May, 18, 2003
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridModel::HybridModel() :
+	mNbLeaves		(0),
+	mNbPrimitives	(0),
+	mTriangles		(null),
+	mIndices		(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridModel::~HybridModel()
+{
+	Release();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Releases everything.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void HybridModel::Release()
+{
+	ReleaseBase();
+	DELETEARRAY(mIndices);
+	DELETEARRAY(mTriangles);
+	mNbLeaves		= 0;
+	mNbPrimitives	= 0;
+}
+
+	struct Internal
+	{
+		Internal()
+		{
+			mNbLeaves	= 0;
+			mLeaves		= null;
+			mTriangles	= null;
+			mBase		= null;
+		}
+		~Internal()
+		{
+			DELETEARRAY(mLeaves);
+		}
+
+		udword			mNbLeaves;
+		AABB*			mLeaves;
+		LeafTriangles*	mTriangles;
+		const udword*	mBase;
+	};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds a collision model.
+ *	\param		create		[in] model creation structure
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool HybridModel::Build(const OPCODECREATE& create)
+{
+	// 1) Checkings
+	if(!create.mIMesh || !create.mIMesh->IsValid())	return false;
+
+	// Look for degenerate faces.
+	udword NbDegenerate = create.mIMesh->CheckTopology();
+	if(NbDegenerate)	Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate);
+	// We continue nonetheless.... 
+
+	Release();	// Make sure previous tree has been discarded
+
+	// 1-1) Setup mesh interface automatically
+	SetMeshInterface(create.mIMesh);
+
+	bool Status = false;
+	AABBTree* LeafTree = null;
+	Internal Data;
+
+	// 2) Build a generic AABB Tree.
+	mSource = new AABBTree;
+	CHECKALLOC(mSource);
+
+	// 2-1) Setup a builder. Our primitives here are triangles from input mesh,
+	// so we use an AABBTreeOfTrianglesBuilder.....
+	{
+		AABBTreeOfTrianglesBuilder TB;
+		TB.mIMesh			= create.mIMesh;
+		TB.mNbPrimitives	= create.mIMesh->GetNbTriangles();
+		TB.mSettings		= create.mSettings;
+		TB.mSettings.mLimit	= 16;	// ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ...
+		if(!mSource->Build(&TB))	goto FreeAndExit;
+	}
+
+	// 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time)
+	struct Local
+	{
+		// A callback to count leaf nodes
+		static bool CountLeaves(const AABBTreeNode* current, udword depth, void* user_data)
+		{
+			if(current->IsLeaf())
+			{
+				Internal* Data = (Internal*)user_data;
+				Data->mNbLeaves++;
+			}
+			return true;
+		}
+
+		// A callback to setup leaf nodes in our internal structures
+		static bool SetupLeafData(const AABBTreeNode* current, udword depth, void* user_data)
+		{
+			if(current->IsLeaf())
+			{
+				Internal* Data = (Internal*)user_data;
+
+				// Get current leaf's box
+				Data->mLeaves[Data->mNbLeaves] = *current->GetAABB();
+
+				// Setup leaf data
+				udword Index = udword((size_t(current->GetPrimitives()) - size_t(Data->mBase)) / sizeof(udword));
+				Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index);
+
+				Data->mNbLeaves++;
+			}
+			return true;
+		}
+	};
+
+	// Walk the tree & count number of leaves
+	Data.mNbLeaves = 0;
+	mSource->Walk(Local::CountLeaves, &Data);
+	mNbLeaves = Data.mNbLeaves;	// Keep track of it
+
+	// Special case for 1-leaf meshes
+	if(mNbLeaves==1)
+	{
+		mModelCode |= OPC_SINGLE_NODE;
+		Status = true;
+		goto FreeAndExit;
+	}
+
+	// Allocate our structures
+	Data.mLeaves = new AABB[Data.mNbLeaves];		CHECKALLOC(Data.mLeaves);
+	mTriangles = new LeafTriangles[Data.mNbLeaves];	CHECKALLOC(mTriangles);
+
+	// Walk the tree again & setup leaf data
+	Data.mTriangles	= mTriangles;
+	Data.mBase		= mSource->GetIndices();
+	Data.mNbLeaves	= 0;	// Reset for incoming walk
+	mSource->Walk(Local::SetupLeafData, &Data);
+
+	// Handle source indices
+	{
+		bool MustKeepIndices = true;
+		if(create.mCanRemap)
+		{
+			// We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays...
+			// Remap can fail when we use callbacks => keep track of indices in that case (it still
+			// works, only using more memory)
+			if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices()))
+			{
+				MustKeepIndices = false;
+			}
+		}
+
+		if(MustKeepIndices)
+		{
+			// Keep track of source indices (from vanilla tree)
+			mNbPrimitives = mSource->GetNbPrimitives();
+			mIndices = new udword[mNbPrimitives];
+			CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword));
+		}
+	}
+
+	// Now, create our optimized tree using previous leaf nodes
+	LeafTree = new AABBTree;
+	CHECKALLOC(LeafTree);
+	{
+		AABBTreeOfAABBsBuilder TB;	// Now using boxes !
+		TB.mSettings		= create.mSettings;
+		TB.mSettings.mLimit	= 1;	// We now want a complete tree so that we can "optimize" it
+		TB.mNbPrimitives	= Data.mNbLeaves;
+		TB.mAABBArray		= Data.mLeaves;
+		if(!LeafTree->Build(&TB))	goto FreeAndExit;
+	}
+
+	// 3) Create an optimized tree according to user-settings
+	if(!CreateTree(create.mNoLeaf, create.mQuantized))	goto FreeAndExit;
+
+	// 3-2) Create optimized tree
+	if(!mTree->Build(LeafTree))	goto FreeAndExit;
+
+	// Finally ok...
+	Status = true;
+
+FreeAndExit:	// Allow me this one...
+	DELETESINGLE(LeafTree);
+
+	// 3-3) Delete generic tree if needed
+	if(!create.mKeepOriginal)	DELETESINGLE(mSource);
+
+	return Status;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the number of bytes used by the tree.
+ *	\return		amount of bytes used
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword HybridModel::GetUsedBytes() const
+{
+	udword UsedBytes = 0;
+	if(mTree)		UsedBytes += mTree->GetUsedBytes();
+	if(mIndices)	UsedBytes += mNbPrimitives * sizeof(udword);	// mIndices
+	if(mTriangles)	UsedBytes += mNbLeaves * sizeof(LeafTriangles);	// mTriangles
+	return UsedBytes;
+}
+
+inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp)
+{
+	// Compute triangle's AABB = a leaf box
+#ifdef OPC_USE_FCOMI	// a 15% speedup on my machine, not much
+	min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
+	max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
+
+	min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
+	max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
+
+	min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
+	max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
+#else
+	min = *vp.Vertex[0];
+	max = *vp.Vertex[0];
+	min.Min(*vp.Vertex[1]);
+	max.Max(*vp.Vertex[1]);
+	min.Min(*vp.Vertex[2]);
+	max.Max(*vp.Vertex[2]);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the collision model. This can be used to handle dynamic meshes. Usage is:
+ *	1. modify your mesh vertices (keep the topology constant!)
+ *	2. refit the tree (call this method)
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool HybridModel::Refit()
+{
+	if(!mIMesh)	return false;
+	if(!mTree)	return false;
+
+	if(IsQuantized())	return false;
+	if(HasLeafNodes())	return false;
+
+	const LeafTriangles* LT = GetLeafTriangles();
+	const udword* Indices = GetIndices();
+
+	// Bottom-up update
+	VertexPointers VP;
+	Point Min,Max;
+	Point Min_,Max_;
+	udword Index = mTree->GetNbNodes();
+	AABBNoLeafNode* Nodes = (AABBNoLeafNode*)((AABBNoLeafTree*)mTree)->GetNodes();
+	while(Index--)
+	{
+		AABBNoLeafNode& Current = Nodes[Index];
+
+		if(Current.HasPosLeaf())
+		{
+			const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()];
+
+			Min.SetPlusInfinity();
+			Max.SetMinusInfinity();
+
+			Point TmpMin, TmpMax;
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					mIMesh->GetTriangle(VP, *T++);
+					ComputeMinMax(TmpMin, TmpMax, VP);
+					Min.Min(TmpMin);
+					Max.Max(TmpMax);
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					mIMesh->GetTriangle(VP, BaseIndex++);
+					ComputeMinMax(TmpMin, TmpMax, VP);
+					Min.Min(TmpMin);
+					Max.Max(TmpMax);
+				}
+			}
+		}
+		else
+		{
+			const CollisionAABB& CurrentBox = Current.GetPos()->mAABB;
+			CurrentBox.GetMin(Min);
+			CurrentBox.GetMax(Max);
+		}
+
+		if(Current.HasNegLeaf())
+		{
+			const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()];
+
+			Min_.SetPlusInfinity();
+			Max_.SetMinusInfinity();
+
+			Point TmpMin, TmpMax;
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					mIMesh->GetTriangle(VP, *T++);
+					ComputeMinMax(TmpMin, TmpMax, VP);
+					Min_.Min(TmpMin);
+					Max_.Max(TmpMax);
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					mIMesh->GetTriangle(VP, BaseIndex++);
+					ComputeMinMax(TmpMin, TmpMax, VP);
+					Min_.Min(TmpMin);
+					Max_.Max(TmpMax);
+				}
+			}
+		}
+		else
+		{
+			const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB;
+			CurrentBox.GetMin(Min_);
+			CurrentBox.GetMax(Max_);
+		}
+#ifdef OPC_USE_FCOMI
+		Min.x = FCMin2(Min.x, Min_.x);
+		Max.x = FCMax2(Max.x, Max_.x);
+		Min.y = FCMin2(Min.y, Min_.y);
+		Max.y = FCMax2(Max.y, Max_.y);
+		Min.z = FCMin2(Min.z, Min_.z);
+		Max.z = FCMax2(Max.z, Max_.z);
+#else
+		Min.Min(Min_);
+		Max.Max(Max_);
+#endif
+		Current.mAABB.SetMinMax(Min, Max);
+	}
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_HybridModel.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_HybridModel.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_HybridModel.h	(revision 216)
@@ -0,0 +1,106 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for hybrid models.
+ *	\file		OPC_HybridModel.h
+ *	\author		Pierre Terdiman
+ *	\date		May, 18, 2003
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_HYBRIDMODEL_H__
+#define __OPC_HYBRIDMODEL_H__
+
+	//! Leaf descriptor
+	struct LeafTriangles
+	{
+		udword			Data;		//!< Packed data
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets number of triangles in the leaf.
+		 *	\return		number of triangles N, with 0 < N <= 16
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	udword	GetNbTriangles()				const	{ return (Data & 15)+1;											}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices()
+		 *	\return		triangle index
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	udword	GetTriangleIndex()				const	{ return Data>>4;												}
+		inline_	void	SetData(udword nb, udword index)		{ ASSERT(nb>0 && nb<=16);	nb--;	Data = (index<<4)|(nb&15);	}
+	};
+
+	class OPCODE_API HybridModel : public BaseModel
+	{
+		public:
+		// Constructor/Destructor
+													HybridModel();
+		virtual										~HybridModel();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Builds a collision model.
+		 *	\param		create		[in] model creation structure
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(BaseModel)	bool					Build(const OPCODECREATE& create);
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the number of bytes used by the tree.
+		 *	\return		amount of bytes used
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(BaseModel)	udword					GetUsedBytes()		const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Refits the collision model. This can be used to handle dynamic meshes. Usage is:
+		 *	1. modify your mesh vertices (keep the topology constant!)
+		 *	2. refit the tree (call this method)
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(BaseModel)	bool					Refit();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets array of triangles.
+		 *	\return		array of triangles
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				const LeafTriangles*	GetLeafTriangles()	const	{ return mTriangles;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets array of indices.
+		 *	\return		array of indices
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				const udword*			GetIndices()		const	{ return mIndices;		}
+
+		private:
+							udword					mNbLeaves;		//!< Number of leaf nodes in the model
+							LeafTriangles*			mTriangles;		//!< Array of mNbLeaves leaf descriptors
+							udword					mNbPrimitives;	//!< Number of primitives in the model
+							udword*					mIndices;		//!< Array of primitive indices
+
+		// Internal methods
+							void					Release();
+	};
+
+#endif // __OPC_HYBRIDMODEL_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_IceHook.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_IceHook.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_IceHook.h	(revision 216)
@@ -0,0 +1,70 @@
+
+// Should be included by Opcode.h if needed
+
+	#define ICE_DONT_CHECK_COMPILER_OPTIONS
+
+	// From Windows...
+	typedef int                 BOOL;
+	#ifndef FALSE
+	#define FALSE               0
+	#endif
+
+	#ifndef TRUE
+	#define TRUE                1
+	#endif
+
+	#include <stdio.h>
+	#include <stdlib.h>
+	#include <assert.h>
+	#include <string.h>
+	#include <float.h>
+	#include <math.h>
+
+	#ifndef ASSERT
+		#define	ASSERT(exp)	{}
+	#endif
+	#define ICE_COMPILE_TIME_ASSERT(exp)	extern char ICE_Dummy[ (exp) ? 1 : -1 ]
+
+	#define	Log				{}
+	#define	SetIceError(a,b)	false
+	#define	EC_OUTOFMEMORY	"Out of memory"
+
+	#include "Ice/IcePreprocessor.h"
+
+	#undef ICECORE_API
+	#define ICECORE_API	OPCODE_API
+
+	#include "Ice/IceTypes.h"
+	#include "Ice/IceFPU.h"
+	#include "Ice/IceMemoryMacros.h"
+
+	namespace IceCore
+	{
+		#include "Ice/IceUtils.h"
+		#include "Ice/IceContainer.h"
+		#include "Ice/IcePairs.h"
+		#include "Ice/IceRevisitedRadix.h"
+		#include "Ice/IceRandom.h"
+	}
+	using namespace IceCore;
+
+	#define ICEMATHS_API	OPCODE_API
+	namespace IceMaths
+	{
+		#include "Ice/IceAxes.h"
+		#include "Ice/IcePoint.h"
+		#include "Ice/IceHPoint.h"
+		#include "Ice/IceMatrix3x3.h"
+		#include "Ice/IceMatrix4x4.h"
+		#include "Ice/IcePlane.h"
+		#include "Ice/IceRay.h"
+		#include "Ice/IceIndexedTriangle.h"
+		#include "Ice/IceTriangle.h"
+		#include "Ice/IceTriList.h"
+		#include "Ice/IceAABB.h"
+		#include "Ice/IceOBB.h"
+		#include "Ice/IceBoundingSphere.h"
+		#include "Ice/IceSegment.h"
+		#include "Ice/IceLSS.h"
+	}
+	using namespace IceMaths;
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_LSSAABBOverlap.h	(revision 216)
@@ -0,0 +1,523 @@
+
+// Following code from Magic-Software (http://www.magic-software.com/)
+// A bit modified for Opcode
+
+inline_ float OPC_PointAABBSqrDist(const Point& point, const Point& center, const Point& extents)
+{
+	// Compute coordinates of point in box coordinate system
+	Point Closest = point - center;
+
+	float SqrDistance = 0.0f;
+
+	if(Closest.x < -extents.x)
+	{
+		float Delta = Closest.x + extents.x;
+		SqrDistance += Delta*Delta;
+	}
+	else if(Closest.x > extents.x)
+	{
+		float Delta = Closest.x - extents.x;
+		SqrDistance += Delta*Delta;
+	}
+
+	if(Closest.y < -extents.y)
+	{
+		float Delta = Closest.y + extents.y;
+		SqrDistance += Delta*Delta;
+	}
+	else if(Closest.y > extents.y)
+	{
+		float Delta = Closest.y - extents.y;
+		SqrDistance += Delta*Delta;
+	}
+
+	if(Closest.z < -extents.z)
+	{
+		float Delta = Closest.z + extents.z;
+		SqrDistance += Delta*Delta;
+	}
+	else if(Closest.z > extents.z)
+	{
+		float Delta = Closest.z - extents.z;
+		SqrDistance += Delta*Delta;
+	}
+	return SqrDistance;
+}
+
+static void Face(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, const Point& rkPmE, float* pfLParam, float& rfSqrDistance)
+{
+    Point kPpE;
+    float fLSqr, fInv, fTmp, fParam, fT, fDelta;
+
+    kPpE[i1] = rkPnt[i1] + extents[i1];
+    kPpE[i2] = rkPnt[i2] + extents[i2];
+    if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0])
+    {
+        if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0])
+        {
+            // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0)
+            if(pfLParam)
+            {
+                rkPnt[i0] = extents[i0];
+                fInv = 1.0f/rkDir[i0];
+                rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv;
+                rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv;
+                *pfLParam = -rkPmE[i0]*fInv;
+            }
+        }
+        else
+        {
+            // v[i1] >= -e[i1], v[i2] < -e[i2]
+            fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2];
+            fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]);
+            if(fTmp <= 2.0f*fLSqr*extents[i1])
+            {
+                fT = fTmp/fLSqr;
+                fLSqr += rkDir[i1]*rkDir[i1];
+                fTmp = kPpE[i1] - fT;
+                fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2];
+                fParam = -fDelta/fLSqr;
+                rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam;
+
+                if(pfLParam)
+                {
+                    *pfLParam = fParam;
+                    rkPnt[i0] = extents[i0];
+                    rkPnt[i1] = fT - extents[i1];
+                    rkPnt[i2] = -extents[i2];
+                }
+            }
+            else
+            {
+                fLSqr += rkDir[i1]*rkDir[i1];
+                fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2];
+                fParam = -fDelta/fLSqr;
+                rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam;
+
+                if(pfLParam)
+                {
+                    *pfLParam = fParam;
+                    rkPnt[i0] = extents[i0];
+                    rkPnt[i1] = extents[i1];
+                    rkPnt[i2] = -extents[i2];
+                }
+            }
+        }
+    }
+    else
+    {
+        if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] )
+        {
+            // v[i1] < -e[i1], v[i2] >= -e[i2]
+            fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1];
+            fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]);
+            if(fTmp <= 2.0f*fLSqr*extents[i2])
+            {
+                fT = fTmp/fLSqr;
+                fLSqr += rkDir[i2]*rkDir[i2];
+                fTmp = kPpE[i2] - fT;
+                fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp;
+                fParam = -fDelta/fLSqr;
+                rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam;
+
+                if(pfLParam)
+                {
+                    *pfLParam = fParam;
+                    rkPnt[i0] = extents[i0];
+                    rkPnt[i1] = -extents[i1];
+                    rkPnt[i2] = fT - extents[i2];
+                }
+            }
+            else
+            {
+                fLSqr += rkDir[i2]*rkDir[i2];
+                fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2];
+                fParam = -fDelta/fLSqr;
+                rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam;
+
+                if(pfLParam)
+                {
+                    *pfLParam = fParam;
+                    rkPnt[i0] = extents[i0];
+                    rkPnt[i1] = -extents[i1];
+                    rkPnt[i2] = extents[i2];
+                }
+            }
+        }
+        else
+        {
+            // v[i1] < -e[i1], v[i2] < -e[i2]
+            fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2];
+            fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]);
+            if(fTmp >= 0.0f)
+            {
+                // v[i1]-edge is closest
+                if ( fTmp <= 2.0f*fLSqr*extents[i1] )
+                {
+                    fT = fTmp/fLSqr;
+                    fLSqr += rkDir[i1]*rkDir[i1];
+                    fTmp = kPpE[i1] - fT;
+                    fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2];
+                    fParam = -fDelta/fLSqr;
+                    rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam;
+
+                    if(pfLParam)
+                    {
+                        *pfLParam = fParam;
+                        rkPnt[i0] = extents[i0];
+                        rkPnt[i1] = fT - extents[i1];
+                        rkPnt[i2] = -extents[i2];
+                    }
+                }
+                else
+                {
+                    fLSqr += rkDir[i1]*rkDir[i1];
+                    fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2];
+                    fParam = -fDelta/fLSqr;
+                    rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam;
+
+                    if(pfLParam)
+                    {
+                        *pfLParam = fParam;
+                        rkPnt[i0] = extents[i0];
+                        rkPnt[i1] = extents[i1];
+                        rkPnt[i2] = -extents[i2];
+                    }
+                }
+                return;
+            }
+
+            fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1];
+            fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]);
+            if(fTmp >= 0.0f)
+            {
+                // v[i2]-edge is closest
+                if(fTmp <= 2.0f*fLSqr*extents[i2])
+                {
+                    fT = fTmp/fLSqr;
+                    fLSqr += rkDir[i2]*rkDir[i2];
+                    fTmp = kPpE[i2] - fT;
+                    fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp;
+                    fParam = -fDelta/fLSqr;
+                    rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam;
+
+                    if(pfLParam)
+                    {
+                        *pfLParam = fParam;
+                        rkPnt[i0] = extents[i0];
+                        rkPnt[i1] = -extents[i1];
+                        rkPnt[i2] = fT - extents[i2];
+                    }
+                }
+                else
+                {
+                    fLSqr += rkDir[i2]*rkDir[i2];
+                    fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2];
+                    fParam = -fDelta/fLSqr;
+                    rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam;
+
+                    if(pfLParam)
+                    {
+                        *pfLParam = fParam;
+                        rkPnt[i0] = extents[i0];
+                        rkPnt[i1] = -extents[i1];
+                        rkPnt[i2] = extents[i2];
+                    }
+                }
+                return;
+            }
+
+            // (v[i1],v[i2])-corner is closest
+            fLSqr += rkDir[i2]*rkDir[i2];
+            fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2];
+            fParam = -fDelta/fLSqr;
+            rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam;
+
+            if(pfLParam)
+            {
+                *pfLParam = fParam;
+                rkPnt[i0] = extents[i0];
+                rkPnt[i1] = -extents[i1];
+                rkPnt[i2] = -extents[i2];
+            }
+        }
+    }
+}
+
+static void CaseNoZeros(Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance)
+{
+    Point kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z);
+
+    float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz;
+
+    fProdDxPy = rkDir.x*kPmE.y;
+    fProdDyPx = rkDir.y*kPmE.x;
+    if(fProdDyPx >= fProdDxPy)
+    {
+        fProdDzPx = rkDir.z*kPmE.x;
+        fProdDxPz = rkDir.x*kPmE.z;
+        if(fProdDzPx >= fProdDxPz)
+        {
+            // line intersects x = e0
+            Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
+        }
+        else
+        {
+            // line intersects z = e2
+            Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
+        }
+    }
+    else
+    {
+        fProdDzPy = rkDir.z*kPmE.y;
+        fProdDyPz = rkDir.y*kPmE.z;
+        if(fProdDzPy >= fProdDyPz)
+        {
+            // line intersects y = e1
+            Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
+        }
+        else
+        {
+            // line intersects z = e2
+            Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance);
+        }
+    }
+}
+
+static void Case0(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance)
+{
+    float fPmE0 = rkPnt[i0] - extents[i0];
+    float fPmE1 = rkPnt[i1] - extents[i1];
+    float fProd0 = rkDir[i1]*fPmE0;
+    float fProd1 = rkDir[i0]*fPmE1;
+    float fDelta, fInvLSqr, fInv;
+
+    if(fProd0 >= fProd1)
+    {
+        // line intersects P[i0] = e[i0]
+        rkPnt[i0] = extents[i0];
+
+        float fPpE1 = rkPnt[i1] + extents[i1];
+        fDelta = fProd0 - rkDir[i0]*fPpE1;
+        if(fDelta >= 0.0f)
+        {
+            fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]);
+            rfSqrDistance += fDelta*fDelta*fInvLSqr;
+            if(pfLParam)
+            {
+                rkPnt[i1] = -extents[i1];
+                *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr;
+            }
+        }
+        else
+        {
+            if(pfLParam)
+            {
+                fInv = 1.0f/rkDir[i0];
+                rkPnt[i1] -= fProd0*fInv;
+                *pfLParam = -fPmE0*fInv;
+            }
+        }
+    }
+    else
+    {
+        // line intersects P[i1] = e[i1]
+        rkPnt[i1] = extents[i1];
+
+        float fPpE0 = rkPnt[i0] + extents[i0];
+        fDelta = fProd1 - rkDir[i1]*fPpE0;
+        if(fDelta >= 0.0f)
+        {
+            fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]);
+            rfSqrDistance += fDelta*fDelta*fInvLSqr;
+            if(pfLParam)
+            {
+                rkPnt[i0] = -extents[i0];
+                *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr;
+            }
+        }
+        else
+        {
+            if(pfLParam)
+            {
+                fInv = 1.0f/rkDir[i1];
+                rkPnt[i0] -= fProd1*fInv;
+                *pfLParam = -fPmE1*fInv;
+            }
+        }
+    }
+
+    if(rkPnt[i2] < -extents[i2])
+    {
+        fDelta = rkPnt[i2] + extents[i2];
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt[i2] = -extents[i2];
+    }
+    else if ( rkPnt[i2] > extents[i2] )
+    {
+        fDelta = rkPnt[i2] - extents[i2];
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt[i2] = extents[i2];
+    }
+}
+
+static void Case00(int i0, int i1, int i2, Point& rkPnt, const Point& rkDir, const Point& extents, float* pfLParam, float& rfSqrDistance)
+{
+    float fDelta;
+
+    if(pfLParam)
+        *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0];
+
+    rkPnt[i0] = extents[i0];
+
+    if(rkPnt[i1] < -extents[i1])
+    {
+        fDelta = rkPnt[i1] + extents[i1];
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt[i1] = -extents[i1];
+    }
+    else if(rkPnt[i1] > extents[i1])
+    {
+        fDelta = rkPnt[i1] - extents[i1];
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt[i1] = extents[i1];
+    }
+
+    if(rkPnt[i2] < -extents[i2])
+    {
+        fDelta = rkPnt[i2] + extents[i2];
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt[i1] = -extents[i2];
+    }
+    else if(rkPnt[i2] > extents[i2])
+    {
+        fDelta = rkPnt[i2] - extents[i2];
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt[i2] = extents[i2];
+    }
+}
+
+static void Case000(Point& rkPnt, const Point& extents, float& rfSqrDistance)
+{
+    float fDelta;
+
+    if(rkPnt.x < -extents.x)
+    {
+        fDelta = rkPnt.x + extents.x;
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt.x = -extents.x;
+    }
+    else if(rkPnt.x > extents.x)
+    {
+        fDelta = rkPnt.x - extents.x;
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt.x = extents.x;
+    }
+
+    if(rkPnt.y < -extents.y)
+    {
+        fDelta = rkPnt.y + extents.y;
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt.y = -extents.y;
+    }
+    else if(rkPnt.y > extents.y)
+    {
+        fDelta = rkPnt.y - extents.y;
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt.y = extents.y;
+    }
+
+    if(rkPnt.z < -extents.z)
+    {
+        fDelta = rkPnt.z + extents.z;
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt.z = -extents.z;
+    }
+    else if(rkPnt.z > extents.z)
+    {
+        fDelta = rkPnt.z - extents.z;
+        rfSqrDistance += fDelta*fDelta;
+        rkPnt.z = extents.z;
+    }
+}
+
+static float SqrDistance(const Ray& rkLine, const Point& center, const Point& extents, float* pfLParam)
+{
+    // compute coordinates of line in box coordinate system
+    Point kDiff = rkLine.mOrig - center;
+    Point kPnt = kDiff;
+    Point kDir = rkLine.mDir;
+
+    // Apply reflections so that direction vector has nonnegative components.
+    bool bReflect[3];
+    for(int i=0;i<3;i++)
+    {
+        if(kDir[i]<0.0f)
+        {
+            kPnt[i] = -kPnt[i];
+            kDir[i] = -kDir[i];
+            bReflect[i] = true;
+        }
+        else
+        {
+            bReflect[i] = false;
+        }
+    }
+
+    float fSqrDistance = 0.0f;
+
+    if(kDir.x>0.0f)
+    {
+        if(kDir.y>0.0f)
+        {
+            if(kDir.z>0.0f)	CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance);		// (+,+,+)
+            else			Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance);	// (+,+,0)
+        }
+        else
+        {
+            if(kDir.z>0.0f)	Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance);	// (+,0,+)
+            else			Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance);	// (+,0,0)
+        }
+    }
+    else
+    {
+        if(kDir.y>0.0f)
+        {
+            if(kDir.z>0.0f)	Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance);	// (0,+,+)
+            else			Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance);	// (0,+,0)
+        }
+        else
+        {
+            if(kDir.z>0.0f)	Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance);	// (0,0,+)
+            else
+            {
+							Case000(kPnt, extents, fSqrDistance);							// (0,0,0)
+							if(pfLParam)	*pfLParam = 0.0f;
+            }
+        }
+    }
+    return fSqrDistance;
+}
+
+inline_ float OPC_SegmentOBBSqrDist(const Segment& segment, const Point& c0, const Point& e0)
+{
+	float fLP;
+	float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP);
+	if(fLP>=0.0f)
+	{
+		if(fLP<=1.0f)	return fSqrDistance;
+		else			return OPC_PointAABBSqrDist(segment.mP1, c0, e0);
+	}
+	else				return OPC_PointAABBSqrDist(segment.mP0, c0, e0);
+}
+
+inline_ BOOL LSSCollider::LSSAABBOverlap(const Point& center, const Point& extents)
+{
+	// Stats
+	mNbVolumeBVTests++;
+
+	float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents);
+	if(s2<mRadius2)	return TRUE;
+
+	return FALSE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.cpp	(revision 216)
@@ -0,0 +1,725 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for an LSS collider.
+ *	\file		OPC_LSSCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		December, 28, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a lss-vs-tree collider.
+ *
+ *	\class		LSSCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		December, 28, 2002
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_LSSAABBOverlap.h"
+#include "OPC_LSSTriOverlap.h"
+
+#define SET_CONTACT(prim_index, flag)									\
+	/* Set contact status */											\
+	mFlags |= flag;														\
+	mTouchedPrimitives->Add(udword(prim_index));
+
+//! LSS-triangle overlap test
+#define LSS_PRIM(prim_index, flag)										\
+	/* Request vertices from the app */									\
+	VertexPointers VP;	mIMesh->GetTriangle(VP, prim_index);			\
+																		\
+	/* Perform LSS-tri overlap test */									\
+	if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))		\
+	{																	\
+		SET_CONTACT(prim_index, flag)									\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+LSSCollider::LSSCollider()
+{
+//	mCenter.Zero();
+//	mRadius2 = 0.0f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+LSSCollider::~LSSCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic collision query for generic OPCODE models. After the call, access the results:
+ *	- with GetContactStatus()
+ *	- with GetNbTouchedPrimitives()
+ *	- with GetTouchedPrimitives()
+ *
+ *	\param		cache			[in/out] an lss cache
+ *	\param		lss				[in] collision lss in local space
+ *	\param		model			[in] Opcode model to collide with
+ *	\param		worldl			[in] lss world matrix, or null
+ *	\param		worldm			[in] model's world matrix, or null
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm)
+{
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, lss, worldl, worldm))	return true;
+
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a collision query :
+ *	- reset stats & contact status
+ *	- setup matrices
+ *	- check temporal coherence
+ *
+ *	\param		cache		[in/out] an lss cache
+ *	\param		lss			[in] lss in local space
+ *	\param		worldl		[in] lss world matrix, or null
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		TRUE if we can return immediately
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm)
+{
+	// 1) Call the base method
+	VolumeCollider::InitQuery();
+
+	// 2) Compute LSS in model space:
+	// - Precompute R^2
+	mRadius2 = lss.mRadius * lss.mRadius;
+	// - Compute segment
+	mSeg.mP0 = lss.mP0;
+	mSeg.mP1 = lss.mP1;
+	// -> to world space
+	if(worldl)
+	{
+		mSeg.mP0 *= *worldl;
+		mSeg.mP1 *= *worldl;
+	}
+	// -> to model space
+	if(worldm)
+	{
+		// Invert model matrix
+		Matrix4x4 InvWorldM;
+		InvertPRMatrix(InvWorldM, *worldm);
+
+		mSeg.mP0 *= InvWorldM;
+		mSeg.mP1 *= InvWorldM;
+	}
+
+	// 3) Setup destination pointer
+	mTouchedPrimitives = &cache.TouchedPrimitives;
+
+	// 4) Special case: 1-triangle meshes [Opcode 1.3]
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		if(!SkipPrimitiveTests())
+		{
+			// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
+			mTouchedPrimitives->Reset();
+
+			// Perform overlap test between the unique triangle and the LSS (and set contact status if needed)
+			LSS_PRIM(udword(0), OPC_CONTACT)
+
+			// Return immediately regardless of status
+			return TRUE;
+		}
+	}
+
+	// 5) Check temporal coherence :
+	if(TemporalCoherenceEnabled())
+	{
+		// Here we use temporal coherence
+		// => check results from previous frame before performing the collision query
+		if(FirstContactEnabled())
+		{
+			// We're only interested in the first contact found => test the unique previously touched face
+			if(mTouchedPrimitives->GetNbEntries())
+			{
+				// Get index of previously touched face = the first entry in the array
+				udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
+
+				// Then reset the array:
+				// - if the overlap test below is successful, the index we'll get added back anyway
+				// - if it isn't, then the array should be reset anyway for the normal query
+				mTouchedPrimitives->Reset();
+
+				// Perform overlap test between the cached triangle and the LSS (and set contact status if needed)
+				LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
+
+				// Return immediately if possible
+				if(GetContactStatus())	return TRUE;
+			}
+			// else no face has been touched during previous query
+			// => we'll have to perform a normal query
+		}
+		else
+		{
+			// We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious):
+
+			// ### rewrite this
+
+			LSS Test(mSeg, lss.mRadius);	// in model space
+			LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius));
+
+//			if(cache.Previous.Contains(Test))
+			if(IsCacheValid(cache) && Previous.Contains(Test))
+			{
+				// - if N is included in P, return previous list
+				// => we simply leave the list (mTouchedFaces) unchanged
+
+				// Set contact status if needed
+				if(mTouchedPrimitives->GetNbEntries())	mFlags |= OPC_TEMPORAL_CONTACT;
+
+				// In any case we don't need to do a query
+				return TRUE;
+			}
+			else
+			{
+				// - else do the query using a fat N
+
+				// Reset cache since we'll about to perform a real query
+				mTouchedPrimitives->Reset();
+
+				// Make a fat sphere so that coherence will work for subsequent frames
+				mRadius2 *= cache.FatCoeff;
+//				mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff);
+
+
+				// Update cache with query data (signature for cached faces)
+				cache.Previous.mP0 = mSeg.mP0;
+				cache.Previous.mP1 = mSeg.mP1;
+				cache.Previous.mRadius = mRadius2;
+			}
+		}
+	}
+	else
+	{
+		// Here we don't use temporal coherence => do a normal query
+		mTouchedPrimitives->Reset();
+	}
+
+	return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for vanilla AABB trees.
+ *	\param		cache		[in/out] an lss cache
+ *	\param		lss			[in] collision lss in world space
+ *	\param		tree		[in] AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree)
+{
+	// This is typically called for a scene tree, full of -AABBs-, not full of triangles.
+	// So we don't really have "primitives" to deal with. Hence it doesn't work with
+	// "FirstContact" + "TemporalCoherence".
+	ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
+
+	// Checkings
+	if(!tree)	return false;
+
+	// Init collision query
+	if(InitQuery(cache, lss))	return true;
+
+	// Perform collision query
+	_Collide(tree);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the LSS completely contains the box. In which case we can end the query sooner.
+ *	\param		bc	[in] box center
+ *	\param		be	[in] box extents
+ *	\return		true if the LSS contains the whole box
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL LSSCollider::LSSContainsBox(const Point& bc, const Point& be)
+{
+	// Not implemented
+	return FALSE;
+}
+
+#define TEST_BOX_IN_LSS(center, extents)	\
+	if(LSSContainsBox(center, extents))		\
+	{										\
+		/* Set contact status */			\
+		mFlags |= OPC_CONTACT;				\
+		_Dump(node);						\
+		return;								\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_Collide(const AABBCollisionNode* node)
+{
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
+{
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_Collide(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_LSS(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_LSS(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_Collide(const AABBNoLeafNode* node)
+{
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
+{
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_LSS(Center, Extents)
+
+	if(node->HasPosLeaf())	{ LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform LSS-AABB overlap test
+	if(!LSSAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_LSS(Center, Extents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for vanilla AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void LSSCollider::_Collide(const AABBTreeNode* node)
+{
+	// Perform LSS-AABB overlap test
+	Point Center, Extents;
+	node->GetAABB()->GetCenter(Center);
+	node->GetAABB()->GetExtents(Extents);
+	if(!LSSAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf() || LSSContainsBox(Center, Extents))
+	{
+		mFlags |= OPC_CONTACT;
+		mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
+	}
+	else
+	{
+		_Collide(node->GetPos());
+		_Collide(node->GetNeg());
+	}
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridLSSCollider::HybridLSSCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridLSSCollider::~HybridLSSCollider()
+{
+}
+
+bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm)
+{
+	// We don't want primitive tests here!
+	mFlags |= OPC_NO_PRIMITIVE_TESTS;
+
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, lss, worldl, worldm))	return true;
+
+	// Special case for 1-leaf trees
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
+		udword Nb = mIMesh->GetNbTriangles();
+
+		// Loop through all triangles
+		for(udword i=0;i<Nb;i++)
+		{
+			LSS_PRIM(i, OPC_CONTACT)
+		}
+		return true;
+	}
+
+	// Override destination array since we're only going to get leaf boxes here
+	mTouchedBoxes.Reset();
+	mTouchedPrimitives = &mTouchedBoxes;
+
+	// Now, do the actual query against leaf boxes
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+
+	// We only have a list of boxes so far
+	if(GetContactStatus())
+	{
+		// Reset contact status, since it currently only reflects collisions with leaf boxes
+		Collider::InitQuery();
+
+		// Change dest container so that we can use built-in overlap tests and get collided primitives
+		cache.TouchedPrimitives.Reset();
+		mTouchedPrimitives = &cache.TouchedPrimitives;
+
+		// Read touched leaf boxes
+		udword Nb = mTouchedBoxes.GetNbEntries();
+		const udword* Touched = mTouchedBoxes.GetEntries();
+
+		const LeafTriangles* LT = model.GetLeafTriangles();
+		const udword* Indices = model.GetIndices();
+
+		// Loop through touched leaves
+		while(Nb--)
+		{
+			const LeafTriangles& CurrentLeaf = LT[*Touched++];
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = *T++;
+					LSS_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = BaseIndex++;
+					LSS_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+		}
+	}
+
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.h	(revision 216)
@@ -0,0 +1,99 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for an LSS collider.
+ *	\file		OPC_LSSCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		December, 28, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_LSSCOLLIDER_H__
+#define __OPC_LSSCOLLIDER_H__
+
+	struct OPCODE_API LSSCache : VolumeCache
+	{
+					LSSCache()
+					{
+						Previous.mP0 = Point(0.0f, 0.0f, 0.0f);
+						Previous.mP1 = Point(0.0f, 0.0f, 0.0f);
+						Previous.mRadius = 0.0f;
+						FatCoeff = 1.1f;
+					}
+
+		// Cached faces signature
+		LSS			Previous;	//!< LSS used when performing the query resulting in cached faces
+		// User settings
+		float		FatCoeff;	//!< mRadius2 multiplier used to create a fat LSS
+	};
+
+	class OPCODE_API LSSCollider : public VolumeCollider
+	{
+		public:
+		// Constructor / Destructor
+											LSSCollider();
+		virtual								~LSSCollider();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic collision query for generic OPCODE models. After the call, access the results:
+		 *	- with GetContactStatus()
+		 *	- with GetNbTouchedPrimitives()
+		 *	- with GetTouchedPrimitives()
+		 *
+		 *	\param		cache			[in/out] an lss cache
+		 *	\param		lss				[in] collision lss in local space
+		 *	\param		model			[in] Opcode model to collide with
+		 *	\param		worldl			[in] lss world matrix, or null
+		 *	\param		worldm			[in] model's world matrix, or null
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null);
+		// 
+							bool			Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree);
+		protected:
+		// LSS in model space
+							Segment			mSeg;			//!< Segment
+							float			mRadius2;		//!< LSS radius squared
+		// Internal methods
+							void			_Collide(const AABBCollisionNode* node);
+							void			_Collide(const AABBNoLeafNode* node);
+							void			_Collide(const AABBQuantizedNode* node);
+							void			_Collide(const AABBQuantizedNoLeafNode* node);
+							void			_Collide(const AABBTreeNode* node);
+							void			_CollideNoPrimitiveTest(const AABBCollisionNode* node);
+							void			_CollideNoPrimitiveTest(const AABBNoLeafNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
+			// Overlap tests
+		inline_				BOOL			LSSContainsBox(const Point& bc, const Point& be);
+		inline_				BOOL			LSSAABBOverlap(const Point& center, const Point& extents);
+		inline_				BOOL			LSSTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
+			// Init methods
+							BOOL			InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null);
+	};
+
+	class OPCODE_API HybridLSSCollider : public LSSCollider
+	{
+		public:
+		// Constructor / Destructor
+											HybridLSSCollider();
+		virtual								~HybridLSSCollider();
+
+							bool			Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null);
+		protected:
+							Container		mTouchedBoxes;
+	};
+
+#endif // __OPC_LSSCOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_LSSTriOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_LSSTriOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_LSSTriOverlap.h	(revision 216)
@@ -0,0 +1,679 @@
+// Following code from Magic-Software (http://www.magic-software.com/)
+// A bit modified for Opcode
+
+static const float gs_fTolerance = 1e-05f;
+
+static float OPC_PointTriangleSqrDist(const Point& point, const Point& p0, const Point& p1, const Point& p2)
+{
+	// Hook
+	Point TriEdge0 = p1 - p0;
+	Point TriEdge1 = p2 - p0;
+
+	Point kDiff	= p0 - point;
+	float fA00	= TriEdge0.SquareMagnitude();
+	float fA01	= TriEdge0 | TriEdge1;
+	float fA11	= TriEdge1.SquareMagnitude();
+	float fB0	= kDiff | TriEdge0;
+	float fB1	= kDiff | TriEdge1;
+	float fC	= kDiff.SquareMagnitude();
+	float fDet	= fabsf(fA00*fA11 - fA01*fA01);
+	float fS	= fA01*fB1-fA11*fB0;
+	float fT	= fA01*fB0-fA00*fB1;
+	float fSqrDist;
+
+	if(fS + fT <= fDet)
+	{
+		if(fS < 0.0f)
+		{
+			if(fT < 0.0f)  // region 4
+			{
+				if(fB0 < 0.0f)
+				{
+					if(-fB0 >= fA00)		fSqrDist = fA00+2.0f*fB0+fC;
+					else					fSqrDist = fB0*(-fB0/fA00)+fC;
+				}
+				else
+				{
+					if(fB1 >= 0.0f)			fSqrDist = fC;
+					else if(-fB1 >= fA11)	fSqrDist = fA11+2.0f*fB1+fC;
+					else					fSqrDist = fB1*(-fB1/fA11)+fC;
+				}
+			}
+			else  // region 3
+			{
+				if(fB1 >= 0.0f)				fSqrDist = fC;
+				else if(-fB1 >= fA11)		fSqrDist = fA11+2.0f*fB1+fC;
+				else						fSqrDist = fB1*(-fB1/fA11)+fC;
+			}
+		}
+		else if(fT < 0.0f)  // region 5
+		{
+			if(fB0 >= 0.0f)					fSqrDist = fC;
+			else if(-fB0 >= fA00)			fSqrDist = fA00+2.0f*fB0+fC;
+			else							fSqrDist = fB0*(-fB0/fA00)+fC;
+		}
+		else  // region 0
+		{
+			// minimum at interior point
+			if(fDet==0.0f)
+			{
+				fSqrDist = MAX_FLOAT;
+			}
+			else
+			{
+				float fInvDet = 1.0f/fDet;
+				fS *= fInvDet;
+				fT *= fInvDet;
+				fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
+			}
+		}
+	}
+	else
+	{
+		float fTmp0, fTmp1, fNumer, fDenom;
+
+		if(fS < 0.0f)  // region 2
+		{
+			fTmp0 = fA01 + fB0;
+			fTmp1 = fA11 + fB1;
+			if(fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-2.0f*fA01+fA11;
+				if(fNumer >= fDenom)
+				{
+					fSqrDist = fA00+2.0f*fB0+fC;
+				}
+				else
+				{
+					fS = fNumer/fDenom;
+					fT = 1.0f - fS;
+					fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
+				}
+			}
+			else
+			{
+				if(fTmp1 <= 0.0f)		fSqrDist = fA11+2.0f*fB1+fC;
+				else if(fB1 >= 0.0f)	fSqrDist = fC;
+				else					fSqrDist = fB1*(-fB1/fA11)+fC;
+			}
+		}
+		else if(fT < 0.0f)  // region 6
+		{
+			fTmp0 = fA01 + fB1;
+			fTmp1 = fA00 + fB0;
+			if(fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-2.0f*fA01+fA11;
+				if(fNumer >= fDenom)
+				{
+					fSqrDist = fA11+2.0f*fB1+fC;
+				}
+				else
+				{
+					fT = fNumer/fDenom;
+					fS = 1.0f - fT;
+					fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
+				}
+			}
+			else
+			{
+				if(fTmp1 <= 0.0f)		fSqrDist = fA00+2.0f*fB0+fC;
+				else if(fB0 >= 0.0f)	fSqrDist = fC;
+				else					fSqrDist = fB0*(-fB0/fA00)+fC;
+			}
+		}
+		else  // region 1
+		{
+			fNumer = fA11 + fB1 - fA01 - fB0;
+			if(fNumer <= 0.0f)
+			{
+				fSqrDist = fA11+2.0f*fB1+fC;
+			}
+			else
+			{
+				fDenom = fA00-2.0f*fA01+fA11;
+				if(fNumer >= fDenom)
+				{
+					fSqrDist = fA00+2.0f*fB0+fC;
+				}
+				else
+				{
+					fS = fNumer/fDenom;
+					fT = 1.0f - fS;
+					fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
+				}
+			}
+		}
+	}
+	return fabsf(fSqrDist);
+}
+
+static float OPC_SegmentSegmentSqrDist(const Segment& rkSeg0, const Segment& rkSeg1)
+{
+	// Hook
+	Point rkSeg0Direction	= rkSeg0.ComputeDirection();
+	Point rkSeg1Direction	= rkSeg1.ComputeDirection();
+
+	Point kDiff	= rkSeg0.mP0 - rkSeg1.mP0;
+	float fA00	= rkSeg0Direction.SquareMagnitude();
+	float fA01	= -rkSeg0Direction.Dot(rkSeg1Direction);
+	float fA11	= rkSeg1Direction.SquareMagnitude();
+	float fB0	= kDiff.Dot(rkSeg0Direction);
+	float fC	= kDiff.SquareMagnitude();
+	float fDet	= fabsf(fA00*fA11-fA01*fA01);
+
+	float fB1, fS, fT, fSqrDist, fTmp;
+
+	if(fDet>=gs_fTolerance)
+	{
+		// line segments are not parallel
+		fB1 = -kDiff.Dot(rkSeg1Direction);
+		fS = fA01*fB1-fA11*fB0;
+		fT = fA01*fB0-fA00*fB1;
+
+		if(fS >= 0.0f)
+		{
+			if(fS <= fDet)
+			{
+				if(fT >= 0.0f)
+				{
+					if(fT <= fDet)  // region 0 (interior)
+					{
+						// minimum at two interior points of 3D lines
+						float fInvDet = 1.0f/fDet;
+						fS *= fInvDet;
+						fT *= fInvDet;
+						fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC;
+					}
+					else  // region 3 (side)
+					{
+						fTmp = fA01+fB0;
+						if(fTmp>=0.0f)			fSqrDist = fA11+2.0f*fB1+fC;
+						else if(-fTmp>=fA00)	fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp);
+						else					fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC;
+					}
+				}
+				else  // region 7 (side)
+				{
+					if(fB0>=0.0f)				fSqrDist = fC;
+					else if(-fB0>=fA00)			fSqrDist = fA00+2.0f*fB0+fC;
+					else						fSqrDist = fB0*(-fB0/fA00)+fC;
+				}
+			}
+			else
+			{
+				if ( fT >= 0.0 )
+				{
+					if ( fT <= fDet )  // region 1 (side)
+					{
+						fTmp = fA01+fB1;
+						if(fTmp>=0.0f)			fSqrDist = fA00+2.0f*fB0+fC;
+						else if(-fTmp>=fA11)	fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
+						else					fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC;
+					}
+					else  // region 2 (corner)
+					{
+						fTmp = fA01+fB0;
+						if ( -fTmp <= fA00 )
+						{
+							if(fTmp>=0.0f)		fSqrDist = fA11+2.0f*fB1+fC;
+							else				fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC;
+						}
+						else
+						{
+							fTmp = fA01+fB1;
+							if(fTmp>=0.0f)			fSqrDist = fA00+2.0f*fB0+fC;
+							else if(-fTmp>=fA11)	fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
+							else					fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC;
+						}
+					}
+				}
+				else  // region 8 (corner)
+				{
+					if ( -fB0 < fA00 )
+					{
+						if(fB0>=0.0f)	fSqrDist = fC;
+						else			fSqrDist = fB0*(-fB0/fA00)+fC;
+					}
+					else
+					{
+						fTmp = fA01+fB1;
+						if(fTmp>=0.0f)			fSqrDist = fA00+2.0f*fB0+fC;
+						else if(-fTmp>=fA11)	fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp);
+						else					fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC;
+					}
+				}
+			}
+		}
+		else 
+		{
+			if ( fT >= 0.0f )
+			{
+				if ( fT <= fDet )  // region 5 (side)
+				{
+					if(fB1>=0.0f)		fSqrDist = fC;
+					else if(-fB1>=fA11)	fSqrDist = fA11+2.0f*fB1+fC;
+					else				fSqrDist = fB1*(-fB1/fA11)+fC;
+				}
+				else  // region 4 (corner)
+				{
+					fTmp = fA01+fB0;
+					if ( fTmp < 0.0f )
+					{
+						if(-fTmp>=fA00)	fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp);
+						else			fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC;
+					}
+					else
+					{
+						if(fB1>=0.0f)		fSqrDist = fC;
+						else if(-fB1>=fA11)	fSqrDist = fA11+2.0f*fB1+fC;
+						else				fSqrDist = fB1*(-fB1/fA11)+fC;
+					}
+				}
+			}
+			else   // region 6 (corner)
+			{
+				if ( fB0 < 0.0f )
+				{
+					if(-fB0>=fA00)	fSqrDist = fA00+2.0f*fB0+fC;
+					else			fSqrDist = fB0*(-fB0/fA00)+fC;
+				}
+				else
+				{
+					if(fB1>=0.0f)		fSqrDist = fC;
+					else if(-fB1>=fA11)	fSqrDist = fA11+2.0f*fB1+fC;
+					else				fSqrDist = fB1*(-fB1/fA11)+fC;
+				}
+			}
+		}
+	}
+	else
+	{
+		// line segments are parallel
+		if ( fA01 > 0.0f )
+		{
+			// direction vectors form an obtuse angle
+			if ( fB0 >= 0.0f )
+			{
+				fSqrDist = fC;
+			}
+			else if ( -fB0 <= fA00 )
+			{
+				fSqrDist = fB0*(-fB0/fA00)+fC;
+			}
+			else
+			{
+				fB1 = -kDiff.Dot(rkSeg1Direction);
+				fTmp = fA00+fB0;
+				if ( -fTmp >= fA01 )
+				{
+					fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1);
+				}
+				else
+				{
+					fT = -fTmp/fA01;
+					fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1));
+				}
+			}
+		}
+		else
+		{
+			// direction vectors form an acute angle
+			if ( -fB0 >= fA00 )
+			{
+				fSqrDist = fA00+2.0f*fB0+fC;
+			}
+			else if ( fB0 <= 0.0f )
+			{
+				fSqrDist = fB0*(-fB0/fA00)+fC;
+			}
+			else
+			{
+				fB1 = -kDiff.Dot(rkSeg1Direction);
+				if ( fB0 >= -fA01 )
+				{
+					fSqrDist = fA11+2.0f*fB1+fC;
+				}
+				else
+				{
+					fT = -fB0/fA01;
+					fSqrDist = fC+fT*(2.0f*fB1+fA11*fT);
+				}
+			}
+		}
+	}
+	return fabsf(fSqrDist);
+}
+
+inline_ float OPC_SegmentRaySqrDist(const Segment& rkSeg0, const Ray& rkSeg1)
+{
+	return OPC_SegmentSegmentSqrDist(rkSeg0, Segment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir));
+}
+
+static float OPC_SegmentTriangleSqrDist(const Segment& segment, const Point& p0, const Point& p1, const Point& p2)
+{
+	// Hook
+	const Point TriEdge0 = p1 - p0;
+	const Point TriEdge1 = p2 - p0;
+
+	const Point& rkSegOrigin	= segment.GetOrigin();
+	Point rkSegDirection		= segment.ComputeDirection();
+
+	Point kDiff = p0 - rkSegOrigin;
+	float fA00 = rkSegDirection.SquareMagnitude();
+	float fA01 = -rkSegDirection.Dot(TriEdge0);
+	float fA02 = -rkSegDirection.Dot(TriEdge1);
+	float fA11 = TriEdge0.SquareMagnitude();
+	float fA12 = TriEdge0.Dot(TriEdge1);
+	float fA22 = TriEdge1.Dot(TriEdge1);
+	float fB0  = -kDiff.Dot(rkSegDirection);
+	float fB1  = kDiff.Dot(TriEdge0);
+	float fB2  = kDiff.Dot(TriEdge1);
+	float fCof00 = fA11*fA22-fA12*fA12;
+	float fCof01 = fA02*fA12-fA01*fA22;
+	float fCof02 = fA01*fA12-fA02*fA11;
+	float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02;
+
+	Ray kTriSeg;
+	Point kPt;
+	float fSqrDist, fSqrDist0;
+
+	if(fabsf(fDet)>=gs_fTolerance)
+	{
+		float fCof11 = fA00*fA22-fA02*fA02;
+		float fCof12 = fA02*fA01-fA00*fA12;
+		float fCof22 = fA00*fA11-fA01*fA01;
+		float fInvDet = 1.0f/fDet;
+		float fRhs0 = -fB0*fInvDet;
+		float fRhs1 = -fB1*fInvDet;
+		float fRhs2 = -fB2*fInvDet;
+
+		float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2;
+		float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2;
+		float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2;
+
+		if ( fR < 0.0f )
+		{
+			if ( fS+fT <= 1.0f )
+			{
+				if ( fS < 0.0f )
+				{
+					if ( fT < 0.0f )  // region 4m
+					{
+						// min on face s=0 or t=0 or r=0
+						kTriSeg.mOrig = p0;
+						kTriSeg.mDir = TriEdge1;
+						fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+						kTriSeg.mOrig = p0;
+						kTriSeg.mDir = TriEdge0;
+						fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+						if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+						fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+						if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    }
+                    else  // region 3m
+                    {
+                        // min on face s=0 or r=0
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge1;
+                        fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                        fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+                        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    }
+                }
+                else if ( fT < 0.0f )  // region 5m
+                {
+                    // min on face t=0 or r=0
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else  // region 0m
+                {
+                    // min on face r=0
+                    fSqrDist = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+                }
+            }
+            else
+            {
+                if ( fS < 0.0f )  // region 2m
+                {
+                    // min on face s=0 or s+t=1 or r=0
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge1;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else if ( fT < 0.0f )  // region 6m
+                {
+                    // min on face t=0 or s+t=1 or r=0
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else  // region 1m
+                {
+                    // min on face s+t=1 or r=0
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+            }
+        }
+        else if ( fR <= 1.0f )
+        {
+            if ( fS+fT <= 1.0f )
+            {
+                if ( fS < 0.0f )
+                {
+                    if ( fT < 0.0f )  // region 4
+                    {
+                        // min on face s=0 or t=0
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge1;
+                        fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge0;
+                        fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    }
+                    else  // region 3
+                    {
+                        // min on face s=0
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge1;
+                        fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    }
+                }
+                else if ( fT < 0.0f )  // region 5
+                {
+                    // min on face t=0
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                }
+                else  // region 0
+                {
+                    // global minimum is interior, done
+                    fSqrDist = fR*(fA00*fR+fA01*fS+fA02*fT+2.0f*fB0)
+                          +fS*(fA01*fR+fA11*fS+fA12*fT+2.0f*fB1)
+                          +fT*(fA02*fR+fA12*fS+fA22*fT+2.0f*fB2)
+                          +kDiff.SquareMagnitude();
+                }
+            }
+            else
+            {
+                if ( fS < 0.0f )  // region 2
+                {
+                    // min on face s=0 or s+t=1
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge1;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else if ( fT < 0.0f )  // region 6
+                {
+                    // min on face t=0 or s+t=1
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else  // region 1
+                {
+                    // min on face s+t=1
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                }
+            }
+        }
+        else  // fR > 1
+        {
+            if ( fS+fT <= 1.0f )
+            {
+                if ( fS < 0.0f )
+                {
+                    if ( fT < 0.0f )  // region 4p
+                    {
+                        // min on face s=0 or t=0 or r=1
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge1;
+                        fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge0;
+                        fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                        kPt = rkSegOrigin+rkSegDirection;
+                        fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    }
+                    else  // region 3p
+                    {
+                        // min on face s=0 or r=1
+                        kTriSeg.mOrig = p0;
+                        kTriSeg.mDir = TriEdge1;
+                        fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                        kPt = rkSegOrigin+rkSegDirection;
+                        fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    }
+                }
+                else if ( fT < 0.0f )  // region 5p
+                {
+                    // min on face t=0 or r=1
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kPt = rkSegOrigin+rkSegDirection;
+                    fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else  // region 0p
+                {
+                    // min face on r=1
+                    kPt = rkSegOrigin+rkSegDirection;
+                    fSqrDist = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                }
+            }
+            else
+            {
+                if ( fS < 0.0f )  // region 2p
+                {
+                    // min on face s=0 or s+t=1 or r=1
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge1;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    kPt = rkSegOrigin+rkSegDirection;
+                    fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else if ( fT < 0.0f )  // region 6p
+                {
+                    // min on face t=0 or s+t=1 or r=1
+                    kTriSeg.mOrig = p0;
+                    kTriSeg.mDir = TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                    kPt = rkSegOrigin+rkSegDirection;
+                    fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+                else  // region 1p
+                {
+                    // min on face s+t=1 or r=1
+                    kTriSeg.mOrig = p1;
+                    kTriSeg.mDir = TriEdge1-TriEdge0;
+                    fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+                    kPt = rkSegOrigin+rkSegDirection;
+                    fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+                    if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+                }
+            }
+        }
+    }
+    else
+    {
+        // segment and triangle are parallel
+        kTriSeg.mOrig = p0;
+        kTriSeg.mDir = TriEdge0;
+        fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg);
+
+        kTriSeg.mDir = TriEdge1;
+        fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+
+        kTriSeg.mOrig = p1;
+        kTriSeg.mDir = TriEdge1 - TriEdge0;
+        fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg);
+        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+
+        fSqrDist0 = OPC_PointTriangleSqrDist(rkSegOrigin, p0, p1, p2);
+        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+
+        kPt = rkSegOrigin+rkSegDirection;
+        fSqrDist0 = OPC_PointTriangleSqrDist(kPt, p0, p1, p2);
+        if(fSqrDist0<fSqrDist)	fSqrDist = fSqrDist0;
+    }
+    return fabsf(fSqrDist);
+}
+
+inline_ BOOL LSSCollider::LSSTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
+{
+	// Stats
+	mNbVolumePrimTests++;
+
+	float s2 = OPC_SegmentTriangleSqrDist(mSeg, vert0, vert1, vert2);
+	if(s2<mRadius2)	return TRUE;
+	return FALSE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.cpp	(revision 216)
@@ -0,0 +1,303 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a mesh interface.
+ *	\file		OPC_MeshInterface.cpp
+ *	\author		Pierre Terdiman
+ *	\date		November, 27, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	This structure holds 3 vertex-pointers. It's mainly used by collision callbacks so that the app doesn't have
+ *	to return 3 vertices to OPCODE (36 bytes) but only 3 pointers (12 bytes). It seems better but I never profiled
+ *	the alternative.
+ *
+ *	\class		VertexPointers
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	This class is an interface between us and user-defined meshes. Meshes can be defined in a lot of ways, and here we
+ *	try to support most of them.
+ *
+ *	Basically you have two options:
+ *	- callbacks, if OPC_USE_CALLBACKS is defined in OPC_Settings.h.
+ *	- else pointers.
+ *
+ *	If using pointers, you can also use strides or not. Strides are used when OPC_USE_STRIDE is defined.
+ *
+ *
+ *	CALLBACKS:
+ *
+ *	Using callbacks is the most generic way to feed OPCODE with your meshes. Indeed, you just have to give
+ *	access to three vertices at the end of the day. It's up to you to fetch them from your database, using
+ *	whatever method you want. Hence your meshes can lie in system memory or AGP, be indexed or not, use 16
+ *	or 32-bits indices, you can decompress them on-the-fly if needed, etc. On the other hand, a callback is
+ *	called each time OPCODE needs access to a particular triangle, so there might be a slight overhead.
+ *
+ *	To make things clear: geometry & topology are NOT stored in the collision system,
+ *	in order to save some ram. So, when the system needs them to perform accurate intersection
+ *	tests, you're requested to provide the triangle-vertices corresponding to a given face index.
+ *
+ *	Ex:
+ *
+ *	\code
+ *		static void ColCallback(udword triangle_index, VertexPointers& triangle, udword user_data)
+ *		{
+ *			// Get back Mesh0 or Mesh1 (you also can use 2 different callbacks)
+ *			Mesh* MyMesh = (Mesh*)user_data;
+ *			// Get correct triangle in the app-controlled database
+ *			const Triangle* Tri = MyMesh->GetTriangle(triangle_index);
+ *			// Setup pointers to vertices for the collision system
+ *			triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]);
+ *			triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]);
+ *			triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]);
+ *		}
+ *
+ *		// Setup callbacks
+ *		MeshInterface0->SetCallback(ColCallback, udword(Mesh0));
+ *		MeshInterface1->SetCallback(ColCallback, udword(Mesh1));
+ *	\endcode
+ *
+ *	Of course, you should make this callback as fast as possible. And you're also not supposed
+ *	to modify the geometry *after* the collision trees have been built. The alternative was to
+ *	store the geometry & topology in the collision system as well (as in RAPID) but we have found
+ *	this approach to waste a lot of ram in many cases.
+ *
+ *
+ *	POINTERS:
+ *
+ *	If you're internally using the following canonical structures:
+ *	- a vertex made of three 32-bits floating point values
+ *	- a triangle made of three 32-bits integer vertex references
+ *	...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly
+ *	use provided pointers to access the topology and geometry, without using a callback. It might be faster,
+ *	but probably not as safe. Pointers have been introduced in OPCODE 1.2.
+ *
+ *	Ex:
+ *
+ *	\code
+ *		// Setup pointers
+ *		MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts());
+ *		MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts());
+ *	\endcode
+ *
+ *
+ *	STRIDES:
+ *
+ *	If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates
+ *	(i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE
+ *	doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase
+ *	cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers !
+ *
+ *
+ *	In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so
+ *	choose what's best for your application. All of this has been wrapped into this MeshInterface.
+ *
+ *	\class		MeshInterface
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		November, 27, 2002
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+Point MeshInterface::VertexCache[3];
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+MeshInterface::MeshInterface() :
+#ifdef OPC_USE_CALLBACKS
+	mUserData		(null),
+	mObjCallback	(null),
+#else
+	mTris			(null),
+	mVerts			(null),
+	#ifdef OPC_USE_STRIDE
+	mTriStride		(sizeof(IndexedTriangle)),
+	mVertexStride	(sizeof(Point)),
+	#endif
+#endif
+	mNbTris			(0),
+	mNbVerts		(0),
+
+	Single(true)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+MeshInterface::~MeshInterface()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the mesh interface is valid, i.e. things have been setup correctly.
+ *	\return		true if valid
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool MeshInterface::IsValid() const
+{
+	if(!mNbTris || !mNbVerts)	return false;
+#ifdef OPC_USE_CALLBACKS
+	if(!mObjCallback)			return false;
+#else
+	if(!mTris || !mVerts)		return false;
+#endif
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the mesh itself is valid.
+ *	Currently we only look for degenerate faces.
+ *	\return		number of degenerate faces
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword MeshInterface::CheckTopology()	const
+{
+	// Check topology. If the model contains degenerate faces, collision report can be wrong in some cases.
+	// e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner
+	// you can try this: www.codercorner.com/Consolidation.zip
+
+	udword NbDegenerate = 0;
+
+	VertexPointers VP;
+
+	// Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for
+	// redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides).
+	for(udword i=0;i<mNbTris;i++)
+	{
+		GetTriangle(VP, i);
+
+		if(		(VP.Vertex[0]==VP.Vertex[1])
+			||	(VP.Vertex[1]==VP.Vertex[2])
+			||	(VP.Vertex[2]==VP.Vertex[0]))	NbDegenerate++;
+	}
+
+	return NbDegenerate;
+}
+
+#ifdef OPC_USE_CALLBACKS
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Callback control: setups object callback. Must provide triangle-vertices for a given triangle index.
+ *	\param		callback	[in] user-defined callback
+ *	\param		user_data	[in] user-defined data
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool MeshInterface::SetCallback(RequestCallback callback, void* user_data)
+{
+	if(!callback)	return SetIceError("MeshInterface::SetCallback: callback pointer is null");
+
+	mObjCallback	= callback;
+	mUserData		= user_data;
+	return true;
+}
+#else
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Pointers control: setups object pointers. Must provide access to faces and vertices for a given object.
+ *	\param		tris	[in] pointer to triangles
+ *	\param		verts	[in] pointer to vertices
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool MeshInterface::SetPointers(const IndexedTriangle* tris, const Point* verts)
+{
+	if(!tris || !verts)	return SetIceError("MeshInterface::SetPointers: pointer is null", null);
+
+	mTris	= tris;
+	mVerts	= verts;
+	return true;
+}
+#ifdef OPC_USE_STRIDE
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Strides control
+ *	\param		tri_stride		[in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices.
+ *	\param		vertex_stride	[in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position.
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool MeshInterface::SetStrides(udword tri_stride, udword vertex_stride)
+{
+	if(tri_stride<sizeof(IndexedTriangle))	return SetIceError("MeshInterface::SetStrides: invalid triangle stride", null);
+	if(vertex_stride<sizeof(Point))			return SetIceError("MeshInterface::SetStrides: invalid vertex stride", null);
+
+	mTriStride		= tri_stride;
+	mVertexStride	= vertex_stride;
+	return true;
+}
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Remaps client's mesh according to a permutation.
+ *	\param		nb_indices	[in] number of indices in the permutation (will be checked against number of triangles)
+ *	\param		permutation	[in] list of triangle indices
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool MeshInterface::RemapClient(udword nb_indices, const udword* permutation) const
+{
+	// Checkings
+	if(!nb_indices || !permutation)	return false;
+	if(nb_indices!=mNbTris)			return false;
+
+#ifdef OPC_USE_CALLBACKS
+	// We can't really do that using callbacks
+	return false;
+#else
+	IndexedTriangle* Tmp = new IndexedTriangle[mNbTris];
+	CHECKALLOC(Tmp);
+
+	#ifdef OPC_USE_STRIDE
+	udword Stride = mTriStride;
+	#else
+	udword Stride = sizeof(IndexedTriangle);
+	#endif
+
+	for(udword i=0;i<mNbTris;i++)
+	{
+		const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
+		Tmp[i] = *T;
+	}
+
+	for(udword i=0;i<mNbTris;i++)
+	{
+		IndexedTriangle* T = (IndexedTriangle*)(((ubyte*)mTris) + i * Stride);
+		*T = Tmp[permutation[i]];
+	}
+
+	DELETEARRAY(Tmp);
+#endif
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_MeshInterface.h	(revision 216)
@@ -0,0 +1,199 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a mesh interface.
+ *	\file		OPC_MeshInterface.h
+ *	\author		Pierre Terdiman
+ *	\date		November, 27, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_MESHINTERFACE_H__
+#define __OPC_MESHINTERFACE_H__
+
+	struct VertexPointers
+	{
+		const Point*	Vertex[3];
+
+		bool BackfaceCulling(const Point& source)
+		{
+			const Point& p0 = *Vertex[0];
+			const Point& p1 = *Vertex[1];
+			const Point& p2 = *Vertex[2];
+
+			// Compute normal direction
+			Point Normal = (p2 - p1)^(p0 - p1);
+
+			// Backface culling
+			return (Normal | (source - p0)) >= 0.0f;
+		}
+	};
+
+#ifdef OPC_USE_CALLBACKS
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	User-callback, called by OPCODE to request vertices from the app.
+	 *	\param		triangle_index	[in] face index for which the system is requesting the vertices
+	 *	\param		triangle		[out] triangle's vertices (must be provided by the user)
+	 *	\param		user_data		[in] user-defined data from SetCallback()
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	typedef void	(*RequestCallback)	(udword triangle_index, VertexPointers& triangle, void* user_data);
+#endif
+
+	class OPCODE_API MeshInterface
+	{
+		public:
+		// Constructor / Destructor
+											MeshInterface();
+											~MeshInterface();
+		// Common settings
+		inline_			udword				GetNbTriangles()	const	{ return mNbTris;	}
+		inline_			udword				GetNbVertices()		const	{ return mNbVerts;	}
+		inline_			void				SetNbTriangles(udword nb)	{ mNbTris = nb;		}
+		inline_			void				SetNbVertices(udword nb)	{ mNbVerts = nb;	}
+
+#ifdef OPC_USE_CALLBACKS
+		// Callback settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Callback control: setups object callback. Must provide triangle-vertices for a given triangle index.
+		 *	\param		callback	[in] user-defined callback
+		 *	\param		user_data	[in] user-defined data
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						bool				SetCallback(RequestCallback callback, void* user_data);
+		inline_			void*				GetUserData()		const	{ return mUserData;		}
+		inline_			RequestCallback		GetCallback()		const	{ return mObjCallback;	}
+#else
+		// Pointers settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Pointers control: setups object pointers. Must provide access to faces and vertices for a given object.
+		 *	\param		tris	[in] pointer to triangles
+		 *	\param		verts	[in] pointer to vertices
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						bool				SetPointers(const IndexedTriangle* tris, const Point* verts);
+		inline_	const	IndexedTriangle*	GetTris()			const	{ return mTris;			}
+		inline_	const	Point*				GetVerts()			const	{ return mVerts;		}
+
+	#ifdef OPC_USE_STRIDE
+		// Strides settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Strides control
+		 *	\param		tri_stride		[in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices.
+		 *	\param		vertex_stride	[in] size of a vertex in bytes. The first sizeof(Point) bytes are used to get vertex position.
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						bool				SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(Point));
+		inline_			udword				GetTriStride()		const	{ return mTriStride;	}
+		inline_			udword				GetVertexStride()	const	{ return mVertexStride;	}
+	#endif
+#endif
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Fetches a triangle given a triangle index.
+		 *	\param		vp		[out] required triangle's vertex pointers
+		 *	\param		index	[in] triangle index
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_			void				GetTriangle(VertexPointers& vp, udword index)	const
+											{
+#ifdef OPC_USE_CALLBACKS
+												(mObjCallback)(index, vp, mUserData);
+#else
+	#ifdef OPC_USE_STRIDE
+												const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride);
+
+												if (Single){
+													vp.Vertex[0] = (const Point*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride);
+													vp.Vertex[1] = (const Point*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride);
+													vp.Vertex[2] = (const Point*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride);
+												}
+												else{
+													for (int i = 0; i < 3; i++){
+														const double* v = (const double*)(((ubyte*)mVerts) + T->mVRef[i] * mVertexStride);
+
+														VertexCache[i].x = (float)v[0];
+														VertexCache[i].y = (float)v[1];
+														VertexCache[i].z = (float)v[2];
+														vp.Vertex[i] = &VertexCache[i];
+													}
+												}
+	#else
+												const IndexedTriangle* T = &mTris[index];
+												vp.Vertex[0] = &mVerts[T->mVRef[0]];
+												vp.Vertex[1] = &mVerts[T->mVRef[1]];
+												vp.Vertex[2] = &mVerts[T->mVRef[2]];
+	#endif
+#endif
+											}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Remaps client's mesh according to a permutation.
+		 *	\param		nb_indices	[in] number of indices in the permutation (will be checked against number of triangles)
+		 *	\param		permutation	[in] list of triangle indices
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		bool				RemapClient(udword nb_indices, const udword* permutation)	const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the mesh interface is valid, i.e. things have been setup correctly.
+		 *	\return		true if valid
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						bool				IsValid()		const;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Checks the mesh itself is valid.
+		 *	Currently we only look for degenerate faces.
+		 *	\return		number of degenerate faces
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+						udword				CheckTopology()	const;
+		private:
+
+						udword				mNbTris;			//!< Number of triangles in the input model
+						udword				mNbVerts;			//!< Number of vertices in the input model
+#ifdef OPC_USE_CALLBACKS
+		// User callback
+						void*				mUserData;			//!< User-defined data sent to callback
+						RequestCallback		mObjCallback;		//!< Object callback
+#else
+		// User pointers
+				const	IndexedTriangle*	mTris;				//!< Array of indexed triangles
+				const	Point*				mVerts;				//!< Array of vertices
+	#ifdef OPC_USE_STRIDE
+						udword				mTriStride;			//!< Possible triangle stride in bytes [Opcode 1.3]
+						udword				mVertexStride;		//!< Possible vertex stride in bytes [Opcode 1.3]
+	#endif
+		public:
+						bool Single;							//!< Use single or double precision vertices
+		private:
+						static Point VertexCache[3];
+#endif
+	};
+
+#endif //__OPC_MESHINTERFACE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Model.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Model.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Model.cpp	(revision 216)
@@ -0,0 +1,222 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for OPCODE models.
+ *	\file		OPC_Model.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	The main collision wrapper, for all trees. Supported trees are:
+ *	- Normal trees (2*N-1 nodes, full size)
+ *	- No-leaf trees (N-1 nodes, full size)
+ *	- Quantized trees (2*N-1 nodes, half size)
+ *	- Quantized no-leaf trees (N-1 nodes, half size)
+ *
+ *	Usage:
+ *
+ *	1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp).
+ *	Keep it around in your app, since a pointer to this interface is saved internally and
+ *	used until you release the collision structures.
+ *
+ *	2) Build a Model using a creation structure:
+ *
+ *	\code
+ *		Model Sample;
+ *
+ *		OPCODECREATE OPCC;
+ *		OPCC.IMesh			= ...;
+ *		OPCC.Rules			= ...;
+ *		OPCC.NoLeaf			= ...;
+ *		OPCC.Quantized		= ...;
+ *		OPCC.KeepOriginal	= ...;
+ *		bool Status = Sample.Build(OPCC);
+ *	\endcode
+ *
+ *	3) Create a tree collider and set it up:
+ *
+ *	\code
+ *		AABBTreeCollider TC;
+ *		TC.SetFirstContact(...);
+ *		TC.SetFullBoxBoxTest(...);
+ *		TC.SetFullPrimBoxTest(...);
+ *		TC.SetTemporalCoherence(...);
+ *	\endcode
+ *
+ *	4) Perform a collision query
+ *
+ *	\code
+ *		// Setup cache
+ *		static BVTCache ColCache;
+ *		ColCache.Model0 = &Model0;
+ *		ColCache.Model1 = &Model1;
+ *
+ *		// Collision query
+ *		bool IsOk = TC.Collide(ColCache, World0, World1);
+ *
+ *		// Get collision status => if true, objects overlap
+ *		BOOL Status = TC.GetContactStatus();
+ *
+ *		// Number of colliding pairs and list of pairs
+ *		udword NbPairs = TC.GetNbPairs();
+ *		const Pair* p = TC.GetPairs()
+ *	\endcode
+ *
+ *	5) Stats
+ *
+ *	\code
+ *		Model0.GetUsedBytes()	= number of bytes used for this collision tree
+ *		TC.GetNbBVBVTests()		= number of BV-BV overlap tests performed during last query
+ *		TC.GetNbPrimPrimTests()	= number of Triangle-Triangle overlap tests performed during last query
+ *		TC.GetNbBVPrimTests()	= number of Triangle-BV overlap tests performed during last query
+ *	\endcode
+ *
+ *	\class		Model
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Model::Model()
+{
+#ifdef __MESHMERIZER_H__	// Collision hulls only supported within ICE !
+	mHull	= null;
+#endif // __MESHMERIZER_H__
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+Model::~Model()
+{
+	Release();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Releases the model.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Model::Release()
+{
+	ReleaseBase();
+#ifdef __MESHMERIZER_H__	// Collision hulls only supported within ICE !
+	DELETESINGLE(mHull);
+#endif // __MESHMERIZER_H__
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds a collision model.
+ *	\param		create		[in] model creation structure
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool Model::Build(const OPCODECREATE& create)
+{
+	// 1) Checkings
+	if(!create.mIMesh || !create.mIMesh->IsValid())	return false;
+
+	// For this model, we only support complete trees
+	if(create.mSettings.mLimit!=1)	return SetIceError("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null);
+
+	// Look for degenerate faces.
+	udword NbDegenerate = create.mIMesh->CheckTopology();
+	if(NbDegenerate)	Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate);
+	// We continue nonetheless.... 
+
+	Release();	// Make sure previous tree has been discarded [Opcode 1.3, thanks Adam]
+
+	// 1-1) Setup mesh interface automatically [Opcode 1.3]
+	SetMeshInterface(create.mIMesh);
+
+	// Special case for 1-triangle meshes [Opcode 1.3]
+	udword NbTris = create.mIMesh->GetNbTriangles();
+	if(NbTris==1)
+	{
+		// We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway.
+		// It's a waste to use a "model" for this but at least it will work.
+		mModelCode |= OPC_SINGLE_NODE;
+		return true;
+	}
+
+	// 2) Build a generic AABB Tree.
+	mSource = new AABBTree;
+	CHECKALLOC(mSource);
+
+	// 2-1) Setup a builder. Our primitives here are triangles from input mesh,
+	// so we use an AABBTreeOfTrianglesBuilder.....
+	{
+		AABBTreeOfTrianglesBuilder TB;
+		TB.mIMesh			= create.mIMesh;
+		TB.mSettings		= create.mSettings;
+		TB.mNbPrimitives	= NbTris;
+		if(!mSource->Build(&TB))	return false;
+	}
+
+	// 3) Create an optimized tree according to user-settings
+	if(!CreateTree(create.mNoLeaf, create.mQuantized))	return false;
+
+	// 3-2) Create optimized tree
+	if(!mTree->Build(mSource))	return false;
+
+	// 3-3) Delete generic tree if needed
+	if(!create.mKeepOriginal)	DELETESINGLE(mSource);
+
+#ifdef __MESHMERIZER_H__
+	// 4) Convex hull
+	if(create.mCollisionHull)
+	{
+		// Create hull
+		mHull = new CollisionHull;
+		CHECKALLOC(mHull);
+
+		CONVEXHULLCREATE CHC;
+		// ### doesn't work with strides
+		CHC.NbVerts			= create.mIMesh->GetNbVertices();
+		CHC.Vertices		= create.mIMesh->GetVerts();
+		CHC.UnifyNormals	= true;
+		CHC.ReduceVertices	= true;
+		CHC.WordFaces		= false;
+		mHull->Compute(CHC);
+	}
+#endif // __MESHMERIZER_H__
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets the number of bytes used by the tree.
+ *	\return		amount of bytes used
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+udword Model::GetUsedBytes() const
+{
+	if(!mTree)	return 0;
+	return mTree->GetUsedBytes();
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Model.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Model.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Model.h	(revision 216)
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for OPCODE models.
+ *	\file		OPC_Model.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_MODEL_H__
+#define __OPC_MODEL_H__
+
+	class OPCODE_API Model : public BaseModel
+	{
+		public:
+		// Constructor/Destructor
+												Model();
+		virtual									~Model();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Builds a collision model.
+		 *	\param		create		[in] model creation structure
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(BaseModel)	bool				Build(const OPCODECREATE& create);
+
+#ifdef __MESHMERIZER_H__
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the collision hull.
+		 *	\return		the collision hull if it exists
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_	const		CollisionHull*		GetHull()		const	{ return mHull;		}
+#endif // __MESHMERIZER_H__
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the number of bytes used by the tree.
+		 *	\return		amount of bytes used
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(BaseModel)	udword				GetUsedBytes()	const;
+
+		private:
+#ifdef __MESHMERIZER_H__
+							CollisionHull*		mHull;			//!< Possible convex hull
+#endif // __MESHMERIZER_H__
+		// Internal methods
+							void				Release();
+	};
+
+#endif //__OPC_MODEL_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_OBBCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_OBBCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_OBBCollider.cpp	(revision 216)
@@ -0,0 +1,767 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for an OBB collider.
+ *	\file		OPC_OBBCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 1st, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains an OBB-vs-tree collider.
+ *
+ *	\class		OBBCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		January, 1st, 2002
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_BoxBoxOverlap.h"
+#include "OPC_TriBoxOverlap.h"
+
+#define SET_CONTACT(prim_index, flag)											\
+	/* Set contact status */													\
+	mFlags |= flag;																\
+	mTouchedPrimitives->Add(udword(prim_index));
+
+//! OBB-triangle test
+#define OBB_PRIM(prim_index, flag)												\
+	/* Request vertices from the app */											\
+	VertexPointers VP;	mIMesh->GetTriangle(VP, prim_index);					\
+	/* Transform them in a common space */										\
+	TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox);	\
+	TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox);	\
+	TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox);	\
+	/* Perform triangle-box overlap test */										\
+	if(TriBoxOverlap())															\
+	{																			\
+		SET_CONTACT(prim_index, flag)											\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OBBCollider::OBBCollider() : mFullBoxBoxTest(true)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+OBBCollider::~OBBCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Validates current settings. You should call this method after all the settings and callbacks have been defined.
+ *	\return		null if everything is ok, else a string describing the problem
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const char* OBBCollider::ValidateSettings()
+{
+	if(TemporalCoherenceEnabled() && !FirstContactEnabled())	return "Temporal coherence only works with ""First contact"" mode!";
+
+	return VolumeCollider::ValidateSettings();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic collision query for generic OPCODE models. After the call, access the results:
+ *	- with GetContactStatus()
+ *	- with GetNbTouchedPrimitives()
+ *	- with GetTouchedPrimitives()
+ *
+ *	\param		cache		[in/out] a box cache
+ *	\param		box			[in] collision OBB in local space
+ *	\param		model		[in] Opcode model to collide with
+ *	\param		worldb		[in] OBB's world matrix, or null
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm)
+{
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, box, worldb, worldm))	return true;
+
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a collision query :
+ *	- reset stats & contact status
+ *	- setup matrices
+ *	- check temporal coherence
+ *
+ *	\param		cache		[in/out] a box cache
+ *	\param		box			[in] obb in local space
+ *	\param		worldb		[in] obb's world matrix, or null
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		TRUE if we can return immediately
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm)
+{
+	// 1) Call the base method
+	VolumeCollider::InitQuery();
+
+	// 2) Compute obb in world space
+	mBoxExtents = box.mExtents;
+
+	Matrix4x4 WorldB;
+
+	if(worldb)
+	{
+		WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) );
+		WorldB.SetTrans(box.mCenter * *worldb);
+	}
+	else
+	{
+		WorldB = box.mRot;
+		WorldB.SetTrans(box.mCenter);
+	}
+
+	// Setup matrices
+	Matrix4x4 InvWorldB;
+	InvertPRMatrix(InvWorldB, WorldB);
+
+	if(worldm)
+	{
+		Matrix4x4 InvWorldM;
+		InvertPRMatrix(InvWorldM, *worldm);
+
+		Matrix4x4 WorldBtoM = WorldB * InvWorldM;
+		Matrix4x4 WorldMtoB = *worldm * InvWorldB;
+
+		mRModelToBox = WorldMtoB;		WorldMtoB.GetTrans(mTModelToBox);
+		mRBoxToModel = WorldBtoM;		WorldBtoM.GetTrans(mTBoxToModel);
+	}
+	else
+	{
+		mRModelToBox = InvWorldB;	InvWorldB.GetTrans(mTModelToBox);
+		mRBoxToModel = WorldB;		WorldB.GetTrans(mTBoxToModel);
+	}
+
+	// 3) Setup destination pointer
+	mTouchedPrimitives = &cache.TouchedPrimitives;
+
+	// 4) Special case: 1-triangle meshes [Opcode 1.3]
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		if(!SkipPrimitiveTests())
+		{
+			// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
+			mTouchedPrimitives->Reset();
+
+			// Perform overlap test between the unique triangle and the box (and set contact status if needed)
+			OBB_PRIM(udword(0), OPC_CONTACT)
+
+			// Return immediately regardless of status
+			return TRUE;
+		}
+	}
+
+	// 5) Check temporal coherence:
+	if(TemporalCoherenceEnabled())
+	{
+		// Here we use temporal coherence
+		// => check results from previous frame before performing the collision query
+		if(FirstContactEnabled())
+		{
+			// We're only interested in the first contact found => test the unique previously touched face
+			if(mTouchedPrimitives->GetNbEntries())
+			{
+				// Get index of previously touched face = the first entry in the array
+				udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
+
+				// Then reset the array:
+				// - if the overlap test below is successful, the index we'll get added back anyway
+				// - if it isn't, then the array should be reset anyway for the normal query
+				mTouchedPrimitives->Reset();
+
+				// Perform overlap test between the cached triangle and the box (and set contact status if needed)
+				OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
+
+				// Return immediately if possible
+				if(GetContactStatus())	return TRUE;
+			}
+			// else no face has been touched during previous query
+			// => we'll have to perform a normal query
+		}
+		else
+		{
+			// ### rewrite this
+			OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel);
+
+			// We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious):
+			if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox))
+			{
+				// - if N is included in P, return previous list
+				// => we simply leave the list (mTouchedFaces) unchanged
+
+				// Set contact status if needed
+				if(mTouchedPrimitives->GetNbEntries())	mFlags |= OPC_TEMPORAL_CONTACT;
+
+				// In any case we don't need to do a query
+				return TRUE;
+			}
+			else
+			{
+				// - else do the query using a fat N
+
+				// Reset cache since we'll about to perform a real query
+				mTouchedPrimitives->Reset();
+
+				// Make a fat box so that coherence will work for subsequent frames
+				TestBox.mExtents *= cache.FatCoeff;
+				mBoxExtents *= cache.FatCoeff;
+
+				// Update cache with query data (signature for cached faces)
+				cache.FatBox = TestBox;
+			}
+		}
+	}
+	else
+	{
+		// Here we don't use temporal coherence => do a normal query
+		mTouchedPrimitives->Reset();
+	}
+
+	// Now we can precompute box-box data
+
+	// Precompute absolute box-to-model rotation matrix
+	for(udword i=0;i<3;i++)
+	{
+		for(udword j=0;j<3;j++)
+		{
+			// Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID)
+			mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]);
+		}
+	}
+
+	// Precompute bounds for box-in-box test
+	mB0 = mBoxExtents - mTModelToBox;
+	mB1 = - mBoxExtents - mTModelToBox;
+
+	// Precompute box-box data - Courtesy of Erwin de Vries
+	mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0];
+	mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1];
+	mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2];
+
+	mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0];
+	mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0];
+	mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0];
+	mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1];
+	mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1];
+	mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1];
+	mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2];
+	mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2];
+	mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2];
+
+	return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the OBB completely contains the box. In which case we can end the query sooner.
+ *	\param		bc	[in] box center
+ *	\param		be	[in] box extents
+ *	\return		true if the OBB contains the whole box
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL OBBCollider::OBBContainsBox(const Point& bc, const Point& be)
+{
+	// I assume if all 8 box vertices are inside the OBB, so does the whole box.
+	// Sounds ok but maybe there's a better way?
+/*
+#define TEST_PT(a,b,c)																												\
+	p.x=a;	p.y=b;	p.z=c;		p+=bc;																								\
+	f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0];	if(f>mB0.x || f<mB1.x) return FALSE;\
+	f = p.x * mRModelToBox.m[0][1] + p.y * mRModelToBox.m[1][1] + p.z * mRModelToBox.m[2][1];	if(f>mB0.y || f<mB1.y) return FALSE;\
+	f = p.x * mRModelToBox.m[0][2] + p.y * mRModelToBox.m[1][2] + p.z * mRModelToBox.m[2][2];	if(f>mB0.z || f<mB1.z) return FALSE;
+
+	Point p;
+	float f;
+
+	TEST_PT(be.x, be.y, be.z)
+	TEST_PT(-be.x, be.y, be.z)
+	TEST_PT(be.x, -be.y, be.z)
+	TEST_PT(-be.x, -be.y, be.z)
+	TEST_PT(be.x, be.y, -be.z)
+	TEST_PT(-be.x, be.y, -be.z)
+	TEST_PT(be.x, -be.y, -be.z)
+	TEST_PT(-be.x, -be.y, -be.z)
+
+	return TRUE;
+*/
+
+	// Yes there is:
+	// - compute model-box's AABB in OBB space
+	// - test AABB-in-AABB
+	float NCx = bc.x * mRModelToBox.m[0][0] + bc.y * mRModelToBox.m[1][0] + bc.z * mRModelToBox.m[2][0];
+	float NEx = fabsf(mRModelToBox.m[0][0] * be.x) + fabsf(mRModelToBox.m[1][0] * be.y) + fabsf(mRModelToBox.m[2][0] * be.z);
+
+	if(mB0.x < NCx+NEx)	return FALSE;
+	if(mB1.x > NCx-NEx)	return FALSE;
+
+	float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1];
+	float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z);
+
+	if(mB0.y < NCy+NEy)	return FALSE;
+	if(mB1.y > NCy-NEy)	return FALSE;
+
+	float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2];
+	float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z);
+
+	if(mB0.z < NCz+NEz)	return FALSE;
+	if(mB1.z > NCz-NEz)	return FALSE;
+
+	return TRUE;
+}
+
+#define TEST_BOX_IN_OBB(center, extents)	\
+	if(OBBContainsBox(center, extents))		\
+	{										\
+		/* Set contact status */			\
+		mFlags |= OPC_CONTACT;				\
+		_Dump(node);						\
+		return;								\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_Collide(const AABBCollisionNode* node)
+{
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		OBB_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
+{
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_Collide(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_OBB(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		OBB_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_OBB(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_Collide(const AABBNoLeafNode* node)
+{
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
+{
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter))	return;
+
+	TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_OBB(Center, Extents)
+
+	if(node->HasPosLeaf())	{ OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform OBB-AABB overlap test
+	if(!BoxBoxOverlap(Extents, Center))	return;
+
+	TEST_BOX_IN_OBB(Center, Extents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridOBBCollider::HybridOBBCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridOBBCollider::~HybridOBBCollider()
+{
+}
+
+bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm)
+{
+	// We don't want primitive tests here!
+	mFlags |= OPC_NO_PRIMITIVE_TESTS;
+
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, box, worldb, worldm))	return true;
+
+	// Special case for 1-leaf trees
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
+		udword Nb = mIMesh->GetNbTriangles();
+
+		// Loop through all triangles
+		for(udword i=0;i<Nb;i++)
+		{
+			OBB_PRIM(i, OPC_CONTACT)
+		}
+		return true;
+	}
+
+	// Override destination array since we're only going to get leaf boxes here
+	mTouchedBoxes.Reset();
+	mTouchedPrimitives = &mTouchedBoxes;
+
+	// Now, do the actual query against leaf boxes
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+
+	// We only have a list of boxes so far
+	if(GetContactStatus())
+	{
+		// Reset contact status, since it currently only reflects collisions with leaf boxes
+		Collider::InitQuery();
+
+		// Change dest container so that we can use built-in overlap tests and get collided primitives
+		cache.TouchedPrimitives.Reset();
+		mTouchedPrimitives = &cache.TouchedPrimitives;
+
+		// Read touched leaf boxes
+		udword Nb = mTouchedBoxes.GetNbEntries();
+		const udword* Touched = mTouchedBoxes.GetEntries();
+
+		const LeafTriangles* LT = model.GetLeafTriangles();
+		const udword* Indices = model.GetIndices();
+
+		// Loop through touched leaves
+		while(Nb--)
+		{
+			const LeafTriangles& CurrentLeaf = LT[*Touched++];
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = *T++;
+					OBB_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = BaseIndex++;
+					OBB_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+		}
+	}
+
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_OBBCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_OBBCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_OBBCollider.h	(revision 216)
@@ -0,0 +1,142 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for an OBB collider.
+ *	\file		OPC_OBBCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 1st, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_OBBCOLLIDER_H__
+#define __OPC_OBBCOLLIDER_H__
+
+	struct OPCODE_API OBBCache : VolumeCache
+	{
+					OBBCache() : FatCoeff(1.1f)
+					{
+						FatBox.mCenter.Zero();
+						FatBox.mExtents.Zero();
+						FatBox.mRot.Identity();
+					}
+
+		// Cached faces signature
+		OBB				FatBox;		//!< Box used when performing the query resulting in cached faces
+		// User settings
+		float			FatCoeff;	//!< extents multiplier used to create a fat box
+	};
+
+	class OPCODE_API OBBCollider : public VolumeCollider
+	{
+		public:
+		// Constructor / Destructor
+											OBBCollider();
+		virtual								~OBBCollider();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic collision query for generic OPCODE models. After the call, access the results:
+		 *	- with GetContactStatus()
+		 *	- with GetNbTouchedPrimitives()
+		 *	- with GetTouchedPrimitives()
+		 *
+		 *	\param		cache			[in/out] a box cache
+		 *	\param		box				[in] collision OBB in local space
+		 *	\param		model			[in] Opcode model to collide with
+		 *	\param		worldb			[in] OBB's world matrix, or null
+		 *	\param		worldm			[in] model's world matrix, or null
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null);
+
+		// Settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded)
+		 *	\param		flag		[in] true for full tests, false for coarse tests
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetFullBoxBoxTest(bool flag)	{ mFullBoxBoxTest = flag;	}
+
+		// Settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
+		 *	\return		null if everything is ok, else a string describing the problem
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(Collider)	const char*		ValidateSettings();
+
+		protected:
+		// Precomputed data
+							Matrix3x3		mAR;				//!< Absolute rotation matrix
+							Matrix3x3		mRModelToBox;		//!< Rotation from model space to obb space
+							Matrix3x3		mRBoxToModel;		//!< Rotation from obb space to model space
+							Point			mTModelToBox;		//!< Translation from model space to obb space
+							Point			mTBoxToModel;		//!< Translation from obb space to model space
+
+							Point			mBoxExtents;
+							Point			mB0;				//!< - mTModelToBox + mBoxExtents
+							Point			mB1;				//!< - mTModelToBox - mBoxExtents
+
+							float			mBBx1;
+							float			mBBy1;
+							float			mBBz1;
+
+							float			mBB_1;
+							float			mBB_2;
+							float			mBB_3;
+							float			mBB_4;
+							float			mBB_5;
+							float			mBB_6;
+							float			mBB_7;
+							float			mBB_8;
+							float			mBB_9;
+
+		// Leaf description
+							Point			mLeafVerts[3];		//!< Triangle vertices
+		// Settings
+							bool			mFullBoxBoxTest;	//!< Perform full BV-BV tests (true) or SAT-lite tests (false)
+		// Internal methods
+							void			_Collide(const AABBCollisionNode* node);
+							void			_Collide(const AABBNoLeafNode* node);
+							void			_Collide(const AABBQuantizedNode* node);
+							void			_Collide(const AABBQuantizedNoLeafNode* node);
+							void			_CollideNoPrimitiveTest(const AABBCollisionNode* node);
+							void			_CollideNoPrimitiveTest(const AABBNoLeafNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
+			// Overlap tests
+		inline_				BOOL			OBBContainsBox(const Point& bc, const Point& be);
+		inline_				BOOL			BoxBoxOverlap(const Point& extents, const Point& center);
+		inline_				BOOL			TriBoxOverlap();
+			// Init methods
+							BOOL			InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null);
+	};
+
+	class OPCODE_API HybridOBBCollider : public OBBCollider
+	{
+		public:
+		// Constructor / Destructor
+											HybridOBBCollider();
+		virtual								~HybridOBBCollider();
+
+							bool			Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null);
+		protected:
+							Container		mTouchedBoxes;
+	};
+
+#endif // __OPC_OBBCOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_OptimizedTree.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_OptimizedTree.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_OptimizedTree.cpp	(revision 216)
@@ -0,0 +1,782 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for optimized trees. Implements 4 trees:
+ *	- normal
+ *	- no leaf
+ *	- quantized
+ *	- no leaf / quantized
+ *
+ *	\file		OPC_OptimizedTree.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A standard AABB tree.
+ *
+ *	\class		AABBCollisionTree
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A no-leaf AABB tree.
+ *
+ *	\class		AABBNoLeafTree
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A quantized AABB tree.
+ *
+ *	\class		AABBQuantizedTree
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A quantized no-leaf AABB tree.
+ *
+ *	\class		AABBQuantizedNoLeafTree
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+//! Compilation flag:
+//! - true to fix quantized boxes (i.e. make sure they enclose the original ones)
+//! - false to see the effects of quantization errors (faster, but wrong results in some cases)
+static bool gFixQuantized = true;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative
+ *	box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one.
+ *
+ *	Layout for implicit trees:
+ *	Node:
+ *			- box
+ *			- data (32-bits value)
+ *
+ *	if data's LSB = 1 =>	remaining bits are a primitive pointer
+ *	else					remaining bits are a P-node pointer, and N = P + 1
+ *
+ *	\relates	AABBCollisionNode
+ *	\fn			_BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
+ *	\param		linear			[in] base address of destination nodes
+ *	\param		box_id			[in] index of destination node
+ *	\param		current_id		[in] current running index
+ *	\param		current_node	[in] current node from input tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
+{
+	// Current node from input tree is "current_node". Must be flattened into "linear[boxid]".
+
+	// Store the AABB
+	current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter);
+	current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents);
+	// Store remaining info
+	if(current_node->IsLeaf())
+	{
+		// The input tree must be complete => i.e. one primitive/leaf
+		ASSERT(current_node->GetNbPrimitives()==1);
+		// Get the primitive index from the input tree
+		udword PrimitiveIndex = current_node->GetPrimitives()[0];
+		// Setup box data as the primitive index, marked as leaf
+		linear[box_id].mData = (PrimitiveIndex<<1)|1;
+	}
+	else
+	{
+		// To make the negative one implicit, we must store P and N in successive order
+		udword PosID = current_id++;	// Get a new id for positive child
+		udword NegID = current_id++;	// Get a new id for negative child
+		// Setup box data as the forthcoming new P pointer
+		linear[box_id].mData = (size_t)&linear[PosID];
+		// Make sure it's not marked as leaf
+		ASSERT(!(linear[box_id].mData&1));
+		// Recurse with new IDs
+		_BuildCollisionTree(linear, PosID, current_id, current_node->GetPos());
+		_BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed.
+ *
+ *	Layout for no-leaf trees:
+ *
+ *	Node:
+ *			- box
+ *			- P pointer => a node (LSB=0) or a primitive (LSB=1)
+ *			- N pointer => a node (LSB=0) or a primitive (LSB=1)
+ *
+ *	\relates	AABBNoLeafNode
+ *	\fn			_BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
+ *	\param		linear			[in] base address of destination nodes
+ *	\param		box_id			[in] index of destination node
+ *	\param		current_id		[in] current running index
+ *	\param		current_node	[in] current node from input tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node)
+{
+	const AABBTreeNode* P = current_node->GetPos();
+	const AABBTreeNode* N = current_node->GetNeg();
+	// Leaf nodes here?!
+	ASSERT(P);
+	ASSERT(N);
+	// Internal node => keep the box
+	current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter);
+	current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents);
+
+	if(P->IsLeaf())
+	{
+		// The input tree must be complete => i.e. one primitive/leaf
+		ASSERT(P->GetNbPrimitives()==1);
+		// Get the primitive index from the input tree
+		udword PrimitiveIndex = P->GetPrimitives()[0];
+		// Setup prev box data as the primitive index, marked as leaf
+		linear[box_id].mPosData = (PrimitiveIndex<<1)|1;
+	}
+	else
+	{
+		// Get a new id for positive child
+		udword PosID = current_id++;
+		// Setup box data
+		linear[box_id].mPosData = (size_t)&linear[PosID];
+		// Make sure it's not marked as leaf
+		ASSERT(!(linear[box_id].mPosData&1));
+		// Recurse
+		_BuildNoLeafTree(linear, PosID, current_id, P);
+	}
+
+	if(N->IsLeaf())
+	{
+		// The input tree must be complete => i.e. one primitive/leaf
+		ASSERT(N->GetNbPrimitives()==1);
+		// Get the primitive index from the input tree
+		udword PrimitiveIndex = N->GetPrimitives()[0];
+		// Setup prev box data as the primitive index, marked as leaf
+		linear[box_id].mNegData = (PrimitiveIndex<<1)|1;
+	}
+	else
+	{
+		// Get a new id for negative child
+		udword NegID = current_id++;
+		// Setup box data
+		linear[box_id].mNegData = (size_t)&linear[NegID];
+		// Make sure it's not marked as leaf
+		ASSERT(!(linear[box_id].mNegData&1));
+		// Recurse
+		_BuildNoLeafTree(linear, NegID, current_id, N);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBCollisionTree::AABBCollisionTree() : mNodes(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBCollisionTree::~AABBCollisionTree()
+{
+	DELETEARRAY(mNodes);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds the collision tree from a generic AABB tree.
+ *	\param		tree			[in] generic AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBCollisionTree::Build(AABBTree* tree)
+{
+	// Checkings
+	if(!tree)	return false;
+	// Check the input tree is complete
+	udword NbTriangles	= tree->GetNbPrimitives();
+	udword NbNodes		= tree->GetNbNodes();
+	if(NbNodes!=NbTriangles*2-1)	return false;
+
+	// Get nodes
+	if(mNbNodes!=NbNodes)	// Same number of nodes => keep moving
+	{
+		mNbNodes = NbNodes;
+		DELETEARRAY(mNodes);
+		mNodes = new AABBCollisionNode[mNbNodes];
+		CHECKALLOC(mNodes);
+	}
+
+	// Build the tree
+	udword CurID = 1;
+	_BuildCollisionTree(mNodes, 0, CurID, tree);
+	ASSERT(CurID==mNbNodes);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the collision tree after vertices have been modified.
+ *	\param		mesh_interface	[in] mesh interface for current model
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBCollisionTree::Refit(const MeshInterface* mesh_interface)
+{
+	ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!");
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Walks the tree and call the user back for each node.
+ *	\param		callback	[in] walking callback
+ *	\param		user_data	[in] callback's user data
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const
+{
+	if(!callback)	return false;
+
+	struct Local
+	{
+		static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data)
+		{
+			if(!current_node || !(callback)(current_node, user_data))	return;
+
+			if(!current_node->IsLeaf())
+			{
+				_Walk(current_node->GetPos(), callback, user_data);
+				_Walk(current_node->GetNeg(), callback, user_data);
+			}
+		}
+	};
+	Local::_Walk(mNodes, callback, user_data);
+	return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBNoLeafTree::AABBNoLeafTree() : mNodes(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBNoLeafTree::~AABBNoLeafTree()
+{
+	DELETEARRAY(mNodes);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds the collision tree from a generic AABB tree.
+ *	\param		tree			[in] generic AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBNoLeafTree::Build(AABBTree* tree)
+{
+	// Checkings
+	if(!tree)	return false;
+	// Check the input tree is complete
+	udword NbTriangles	= tree->GetNbPrimitives();
+	udword NbNodes		= tree->GetNbNodes();
+	if(NbNodes!=NbTriangles*2-1)	return false;
+
+	// Get nodes
+	if(mNbNodes!=NbTriangles-1)	// Same number of nodes => keep moving
+	{
+		mNbNodes = NbTriangles-1;
+		DELETEARRAY(mNodes);
+		mNodes = new AABBNoLeafNode[mNbNodes];
+		CHECKALLOC(mNodes);
+	}
+
+	// Build the tree
+	udword CurID = 1;
+	_BuildNoLeafTree(mNodes, 0, CurID, tree);
+	ASSERT(CurID==mNbNodes);
+
+	return true;
+}
+
+inline_ void ComputeMinMax(Point& min, Point& max, const VertexPointers& vp)
+{
+	// Compute triangle's AABB = a leaf box
+#ifdef OPC_USE_FCOMI	// a 15% speedup on my machine, not much
+	min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
+	max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x);
+
+	min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
+	max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y);
+
+	min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
+	max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z);
+#else
+	min = *vp.Vertex[0];
+	max = *vp.Vertex[0];
+	min.Min(*vp.Vertex[1]);
+	max.Max(*vp.Vertex[1]);
+	min.Min(*vp.Vertex[2]);
+	max.Max(*vp.Vertex[2]);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the collision tree after vertices have been modified.
+ *	\param		mesh_interface	[in] mesh interface for current model
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface)
+{
+	// Checkings
+	if(!mesh_interface)	return false;
+
+	// Bottom-up update
+	VertexPointers VP;
+	Point Min,Max;
+	Point Min_,Max_;
+	udword Index = mNbNodes;
+	while(Index--)
+	{
+		AABBNoLeafNode& Current = mNodes[Index];
+
+		if(Current.HasPosLeaf())
+		{
+			mesh_interface->GetTriangle(VP, Current.GetPosPrimitive());
+			ComputeMinMax(Min, Max, VP);
+		}
+		else
+		{
+			const CollisionAABB& CurrentBox = Current.GetPos()->mAABB;
+			CurrentBox.GetMin(Min);
+			CurrentBox.GetMax(Max);
+		}
+
+		if(Current.HasNegLeaf())
+		{
+			mesh_interface->GetTriangle(VP, Current.GetNegPrimitive());
+			ComputeMinMax(Min_, Max_, VP);
+		}
+		else
+		{
+			const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB;
+			CurrentBox.GetMin(Min_);
+			CurrentBox.GetMax(Max_);
+		}
+#ifdef OPC_USE_FCOMI
+		Min.x = FCMin2(Min.x, Min_.x);
+		Max.x = FCMax2(Max.x, Max_.x);
+		Min.y = FCMin2(Min.y, Min_.y);
+		Max.y = FCMax2(Max.y, Max_.y);
+		Min.z = FCMin2(Min.z, Min_.z);
+		Max.z = FCMax2(Max.z, Max_.z);
+#else
+		Min.Min(Min_);
+		Max.Max(Max_);
+#endif
+		Current.mAABB.SetMinMax(Min, Max);
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Walks the tree and call the user back for each node.
+ *	\param		callback	[in] walking callback
+ *	\param		user_data	[in] callback's user data
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
+{
+	if(!callback)	return false;
+
+	struct Local
+	{
+		static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
+		{
+			if(!current_node || !(callback)(current_node, user_data))	return;
+
+			if(!current_node->HasPosLeaf())	_Walk(current_node->GetPos(), callback, user_data);
+			if(!current_node->HasNegLeaf())	_Walk(current_node->GetNeg(), callback, user_data);
+		}
+	};
+	Local::_Walk(mNodes, callback, user_data);
+	return true;
+}
+
+// Quantization notes:
+// - We could use the highest bits of mData to store some more quantized bits. Dequantization code
+//   would be slightly more complex, but number of overlap tests would be reduced (and anyhow those
+//   bits are currently wasted). Of course it's not possible if we move to 16 bits mData.
+// - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion.
+// - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some
+//   lazy-dequantization which may save some work in case of early exits). At the very least some
+//   muls could be saved by precomputing several more matrices. But maybe not worth the pain.
+// - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has
+//   been scaled, for example.
+// - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed
+//   number of quantization bits. Even better, could probably be best delta-encoded.
+
+
+// Find max values. Some people asked why I wasn't simply using the first node. Well, I can't.
+// I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal
+// centers/extents in order to quantize them. The first node would only give a single center and
+// a single extents. While extents would be the biggest, the center wouldn't.
+#define FIND_MAX_VALUES																			\
+	/* Get max values */																		\
+	Point CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);												\
+	Point EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);												\
+	for(udword i=0;i<mNbNodes;i++)																\
+	{																							\
+		if(fabsf(Nodes[i].mAABB.mCenter.x)>CMax.x)	CMax.x = fabsf(Nodes[i].mAABB.mCenter.x);	\
+		if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y)	CMax.y = fabsf(Nodes[i].mAABB.mCenter.y);	\
+		if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z)	CMax.z = fabsf(Nodes[i].mAABB.mCenter.z);	\
+		if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x)	EMax.x = fabsf(Nodes[i].mAABB.mExtents.x);	\
+		if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y)	EMax.y = fabsf(Nodes[i].mAABB.mExtents.y);	\
+		if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z)	EMax.z = fabsf(Nodes[i].mAABB.mExtents.z);	\
+	}
+
+#define INIT_QUANTIZATION													\
+	udword nbc=15;	/* Keep one bit for sign */								\
+	udword nbe=15;	/* Keep one bit for fix */								\
+	if(!gFixQuantized) nbe++;												\
+																			\
+	/* Compute quantization coeffs */										\
+	Point CQuantCoeff, EQuantCoeff;											\
+	CQuantCoeff.x = CMax.x!=0.0f ? float((1<<nbc)-1)/CMax.x : 0.0f;			\
+	CQuantCoeff.y = CMax.y!=0.0f ? float((1<<nbc)-1)/CMax.y : 0.0f;			\
+	CQuantCoeff.z = CMax.z!=0.0f ? float((1<<nbc)-1)/CMax.z : 0.0f;			\
+	EQuantCoeff.x = EMax.x!=0.0f ? float((1<<nbe)-1)/EMax.x : 0.0f;			\
+	EQuantCoeff.y = EMax.y!=0.0f ? float((1<<nbe)-1)/EMax.y : 0.0f;			\
+	EQuantCoeff.z = EMax.z!=0.0f ? float((1<<nbe)-1)/EMax.z : 0.0f;			\
+	/* Compute and save dequantization coeffs */							\
+	mCenterCoeff.x = CQuantCoeff.x!=0.0f ? 1.0f / CQuantCoeff.x : 0.0f;		\
+	mCenterCoeff.y = CQuantCoeff.y!=0.0f ? 1.0f / CQuantCoeff.y : 0.0f;		\
+	mCenterCoeff.z = CQuantCoeff.z!=0.0f ? 1.0f / CQuantCoeff.z : 0.0f;		\
+	mExtentsCoeff.x = EQuantCoeff.x!=0.0f ? 1.0f / EQuantCoeff.x : 0.0f;	\
+	mExtentsCoeff.y = EQuantCoeff.y!=0.0f ? 1.0f / EQuantCoeff.y : 0.0f;	\
+	mExtentsCoeff.z = EQuantCoeff.z!=0.0f ? 1.0f / EQuantCoeff.z : 0.0f;	\
+
+#define PERFORM_QUANTIZATION														\
+	/* Quantize */																	\
+	mNodes[i].mAABB.mCenter[0] = sword(Nodes[i].mAABB.mCenter.x * CQuantCoeff.x);	\
+	mNodes[i].mAABB.mCenter[1] = sword(Nodes[i].mAABB.mCenter.y * CQuantCoeff.y);	\
+	mNodes[i].mAABB.mCenter[2] = sword(Nodes[i].mAABB.mCenter.z * CQuantCoeff.z);	\
+	mNodes[i].mAABB.mExtents[0] = uword(Nodes[i].mAABB.mExtents.x * EQuantCoeff.x);	\
+	mNodes[i].mAABB.mExtents[1] = uword(Nodes[i].mAABB.mExtents.y * EQuantCoeff.y);	\
+	mNodes[i].mAABB.mExtents[2] = uword(Nodes[i].mAABB.mExtents.z * EQuantCoeff.z);	\
+	/* Fix quantized boxes */														\
+	if(gFixQuantized)																\
+	{																				\
+		/* Make sure the quantized box is still valid */							\
+		Point Max = Nodes[i].mAABB.mCenter + Nodes[i].mAABB.mExtents;				\
+		Point Min = Nodes[i].mAABB.mCenter - Nodes[i].mAABB.mExtents;				\
+		/* For each axis */															\
+		for(udword j=0;j<3;j++)														\
+		{	/* Dequantize the box center */											\
+			float qc = float(mNodes[i].mAABB.mCenter[j]) * mCenterCoeff[j];			\
+			bool FixMe=true;														\
+			do																		\
+			{	/* Dequantize the box extent */										\
+				float qe = float(mNodes[i].mAABB.mExtents[j]) * mExtentsCoeff[j];	\
+				/* Compare real & dequantized values */								\
+				if(qc+qe<Max[j] || qc-qe>Min[j])	mNodes[i].mAABB.mExtents[j]++;	\
+				else								FixMe=false;					\
+				/* Prevent wrapping */												\
+				if(!mNodes[i].mAABB.mExtents[j])									\
+				{																	\
+					mNodes[i].mAABB.mExtents[j]=0xffff;								\
+					FixMe=false;													\
+				}																	\
+			}while(FixMe);															\
+		}																			\
+	}
+
+#define REMAP_DATA(member)											\
+	/* Fix data */													\
+	Data = Nodes[i].member;											\
+	if(!(Data&1))													\
+	{																\
+		/* Compute box number */									\
+		size_t Nb = (Data - size_t(Nodes))/Nodes[i].GetNodeSize();	\
+		Data = (size_t) &mNodes[Nb];								\
+	}																\
+	/* ...remapped */												\
+	mNodes[i].member = Data;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBQuantizedTree::AABBQuantizedTree() : mNodes(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBQuantizedTree::~AABBQuantizedTree()
+{
+	DELETEARRAY(mNodes);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds the collision tree from a generic AABB tree.
+ *	\param		tree			[in] generic AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBQuantizedTree::Build(AABBTree* tree)
+{
+	// Checkings
+	if(!tree)	return false;
+	// Check the input tree is complete
+	udword NbTriangles	= tree->GetNbPrimitives();
+	udword NbNodes		= tree->GetNbNodes();
+	if(NbNodes!=NbTriangles*2-1)	return false;
+
+	// Get nodes
+	mNbNodes = NbNodes;
+	DELETEARRAY(mNodes);
+	AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes];
+	CHECKALLOC(Nodes);
+
+	// Build the tree
+	udword CurID = 1;
+	_BuildCollisionTree(Nodes, 0, CurID, tree);
+
+	// Quantize
+	{
+		mNodes = new AABBQuantizedNode[mNbNodes];
+		CHECKALLOC(mNodes);
+
+		// Get max values
+		FIND_MAX_VALUES
+
+		// Quantization
+		INIT_QUANTIZATION
+
+		// Quantize
+		size_t Data;
+		for(udword i=0;i<mNbNodes;i++)
+		{
+			PERFORM_QUANTIZATION
+			REMAP_DATA(mData)
+		}
+
+		DELETEARRAY(Nodes);
+	}
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the collision tree after vertices have been modified.
+ *	\param		mesh_interface	[in] mesh interface for current model
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBQuantizedTree::Refit(const MeshInterface* mesh_interface)
+{
+	ASSERT(!"Not implemented since requantizing is painful !");
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Walks the tree and call the user back for each node.
+ *	\param		callback	[in] walking callback
+ *	\param		user_data	[in] callback's user data
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBQuantizedTree::Walk(GenericWalkingCallback callback, void* user_data) const
+{
+	if(!callback)	return false;
+
+	struct Local
+	{
+		static void _Walk(const AABBQuantizedNode* current_node, GenericWalkingCallback callback, void* user_data)
+		{
+			if(!current_node || !(callback)(current_node, user_data))	return;
+
+			if(!current_node->IsLeaf())
+			{
+				_Walk(current_node->GetPos(), callback, user_data);
+				_Walk(current_node->GetNeg(), callback, user_data);
+			}
+		}
+	};
+	Local::_Walk(mNodes, callback, user_data);
+	return true;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree()
+{
+	DELETEARRAY(mNodes);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Builds the collision tree from a generic AABB tree.
+ *	\param		tree			[in] generic AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBQuantizedNoLeafTree::Build(AABBTree* tree)
+{
+	// Checkings
+	if(!tree)	return false;
+	// Check the input tree is complete
+	udword NbTriangles	= tree->GetNbPrimitives();
+	udword NbNodes		= tree->GetNbNodes();
+	if(NbNodes!=NbTriangles*2-1)	return false;
+
+	// Get nodes
+	mNbNodes = NbTriangles-1;
+	DELETEARRAY(mNodes);
+	AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes];
+	CHECKALLOC(Nodes);
+
+	// Build the tree
+	udword CurID = 1;
+	_BuildNoLeafTree(Nodes, 0, CurID, tree);
+	ASSERT(CurID==mNbNodes);
+
+	// Quantize
+	{
+		mNodes = new AABBQuantizedNoLeafNode[mNbNodes];
+		CHECKALLOC(mNodes);
+
+		// Get max values
+		FIND_MAX_VALUES
+
+		// Quantization
+		INIT_QUANTIZATION
+
+		// Quantize
+		size_t Data;
+		for(udword i=0;i<mNbNodes;i++)
+		{
+			PERFORM_QUANTIZATION
+			REMAP_DATA(mPosData)
+			REMAP_DATA(mNegData)
+		}
+
+		DELETEARRAY(Nodes);
+	}
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Refits the collision tree after vertices have been modified.
+ *	\param		mesh_interface	[in] mesh interface for current model
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBQuantizedNoLeafTree::Refit(const MeshInterface* mesh_interface)
+{
+	ASSERT(!"Not implemented since requantizing is painful !");
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Walks the tree and call the user back for each node.
+ *	\param		callback	[in] walking callback
+ *	\param		user_data	[in] callback's user data
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBQuantizedNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const
+{
+	if(!callback)	return false;
+
+	struct Local
+	{
+		static void _Walk(const AABBQuantizedNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data)
+		{
+			if(!current_node || !(callback)(current_node, user_data))	return;
+
+			if(!current_node->HasPosLeaf())	_Walk(current_node->GetPos(), callback, user_data);
+			if(!current_node->HasNegLeaf())	_Walk(current_node->GetNeg(), callback, user_data);
+		}
+	};
+	Local::_Walk(mNodes, callback, user_data);
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_OptimizedTree.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_OptimizedTree.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_OptimizedTree.h	(revision 216)
@@ -0,0 +1,206 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for optimized trees.
+ *	\file		OPC_OptimizedTree.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_OPTIMIZEDTREE_H__
+#define __OPC_OPTIMIZEDTREE_H__
+
+	//! Common interface for a node of an implicit tree
+	#define IMPLEMENT_IMPLICIT_NODE(base_class, volume)														\
+		public:																								\
+		/* Constructor / Destructor */																		\
+		inline_								base_class() : mData(0)	{}										\
+		inline_								~base_class()			{}										\
+		/* Leaf test */																						\
+		inline_			BOOL				IsLeaf()		const	{ return (mData&1)!=0;					}	\
+		/* Data access */																					\
+		inline_			const base_class*	GetPos()		const	{ return (base_class*)mData;		}	\
+		inline_			const base_class*	GetNeg()		const	{ return ((base_class*)mData)+1;	}	\
+		inline_			size_t				GetPrimitive()	const	{ return (mData>>1);				}	\
+		/* Stats */																							\
+		inline_			udword				GetNodeSize()	const	{ return SIZEOFOBJECT;				}	\
+																											\
+						volume				mAABB;															\
+						size_t				mData;
+
+	//! Common interface for a node of a no-leaf tree
+	#define IMPLEMENT_NOLEAF_NODE(base_class, volume)														\
+		public:																								\
+		/* Constructor / Destructor */																		\
+		inline_								base_class() : mPosData(0), mNegData(0)	{}						\
+		inline_								~base_class()							{}						\
+		/* Leaf tests */																					\
+		inline_			BOOL				HasPosLeaf()		const	{ return (mPosData&1)!=0;			}	\
+		inline_			BOOL				HasNegLeaf()		const	{ return (mNegData&1)!=0;			}	\
+		/* Data access */																					\
+		inline_			const base_class*	GetPos()			const	{ return (base_class*)mPosData;	}	\
+		inline_			const base_class*	GetNeg()			const	{ return (base_class*)mNegData;	}	\
+		inline_			size_t				GetPosPrimitive()	const	{ return (mPosData>>1);			}	\
+		inline_			size_t				GetNegPrimitive()	const	{ return (mNegData>>1);			}	\
+		/* Stats */																							\
+		inline_			udword				GetNodeSize()		const	{ return SIZEOFOBJECT;			}	\
+																											\
+						volume				mAABB;															\
+						size_t				mPosData;														\
+						size_t				mNegData;
+
+	class OPCODE_API AABBCollisionNode
+	{
+		IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB)
+
+		inline_			float				GetVolume()		const	{ return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z;	}
+		inline_			float				GetSize()		const	{ return mAABB.mExtents.SquareMagnitude();	}
+		inline_			udword				GetRadius()		const
+											{
+												udword* Bits = (udword*)&mAABB.mExtents.x;
+												udword Max = Bits[0];
+												if(Bits[1]>Max)	Max = Bits[1];
+												if(Bits[2]>Max)	Max = Bits[2];
+												return Max;
+											}
+
+		// NB: using the square-magnitude or the true volume of the box, seems to yield better results
+		// (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size"
+		// otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's
+		// needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is
+		// always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices
+		// whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very
+		// good strategy.
+	};
+
+	class OPCODE_API AABBQuantizedNode
+	{
+		IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB)
+
+		inline_			uword				GetSize()		const
+											{
+												const uword* Bits = mAABB.mExtents;
+												uword Max = Bits[0];
+												if(Bits[1]>Max)	Max = Bits[1];
+												if(Bits[2]>Max)	Max = Bits[2];
+												return Max;
+											}
+		// NB: for quantized nodes I don't feel like computing a square-magnitude with integers all
+		// over the place.......!
+	};
+
+	class OPCODE_API AABBNoLeafNode
+	{
+		IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB)
+	};
+
+	class OPCODE_API AABBQuantizedNoLeafNode
+	{
+		IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB)
+	};
+
+	//! Common interface for a collision tree
+	#define IMPLEMENT_COLLISION_TREE(base_class, node)																\
+		public:																										\
+		/* Constructor / Destructor */																				\
+													base_class();													\
+		virtual										~base_class();													\
+		/* Builds from a standard tree */																			\
+		override(AABBOptimizedTree)	bool			Build(AABBTree* tree);											\
+		/* Refits the tree */																						\
+		override(AABBOptimizedTree)	bool			Refit(const MeshInterface* mesh_interface);						\
+		/* Walks the tree */																						\
+		override(AABBOptimizedTree)	bool			Walk(GenericWalkingCallback callback, void* user_data) const;	\
+		/* Data access */																							\
+		inline_						const node*		GetNodes()		const	{ return mNodes;					}	\
+		/* Stats */																									\
+		override(AABBOptimizedTree)	udword			GetUsedBytes()	const	{ return mNbNodes*sizeof(node);		}	\
+		private:																									\
+									node*			mNodes;
+
+	typedef		bool				(*GenericWalkingCallback)	(const void* current, void* user_data);
+
+	class OPCODE_API AABBOptimizedTree
+	{
+		public:
+		// Constructor / Destructor
+											AABBOptimizedTree() :
+												mNbNodes	(0)
+																							{}
+		virtual								~AABBOptimizedTree()							{}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Builds the collision tree from a generic AABB tree.
+		 *	\param		tree			[in] generic AABB tree
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual			bool				Build(AABBTree* tree)											= 0;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Refits the collision tree after vertices have been modified.
+		 *	\param		mesh_interface	[in] mesh interface for current model
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual			bool				Refit(const MeshInterface* mesh_interface)						= 0;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Walks the tree and call the user back for each node.
+		 *	\param		callback	[in] walking callback
+		 *	\param		user_data	[in] callback's user data
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual			bool				Walk(GenericWalkingCallback callback, void* user_data) const	= 0;
+
+		// Data access
+		virtual			udword				GetUsedBytes()		const										= 0;
+		inline_			udword				GetNbNodes()		const						{ return mNbNodes;	}
+
+		protected:
+						udword				mNbNodes;
+	};
+
+	class OPCODE_API AABBCollisionTree : public AABBOptimizedTree
+	{
+		IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode)
+	};
+
+	class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree
+	{
+		IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode)
+	};
+
+	class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree
+	{
+		IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode)
+
+		public:
+						Point				mCenterCoeff;
+						Point				mExtentsCoeff;
+	};
+
+	class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree
+	{
+		IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode)
+
+		public:
+						Point				mCenterCoeff;
+						Point				mExtentsCoeff;
+	};
+
+#endif // __OPC_OPTIMIZEDTREE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Picking.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Picking.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Picking.cpp	(revision 216)
@@ -0,0 +1,182 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code to perform "picking".
+ *	\file		OPC_Picking.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#ifdef OPC_RAYHIT_CALLBACK
+
+/*
+	Possible RayCollider usages:
+	- boolean query (shadow feeler)
+	- closest hit
+	- all hits
+	- number of intersection (boolean)
+
+*/
+
+bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts)
+{
+	struct Local
+	{
+		static void AllContacts(const CollisionFace& hit, void* user_data)
+		{
+			CollisionFaces* CF = (CollisionFaces*)user_data;
+			CF->AddFace(hit);
+		}
+	};
+
+	collider.SetFirstContact(false);
+	collider.SetHitCallback(Local::AllContacts);
+	collider.SetUserData(&contacts);
+	return true;
+}
+
+bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact)
+{
+	struct Local
+	{
+		static void ClosestContact(const CollisionFace& hit, void* user_data)
+		{
+			CollisionFace* CF = (CollisionFace*)user_data;
+			if(hit.mDistance<CF->mDistance)	*CF = hit;
+		}
+	};
+
+	collider.SetFirstContact(false);
+	collider.SetHitCallback(Local::ClosestContact);
+	collider.SetUserData(&closest_contact);
+	closest_contact.mDistance = MAX_FLOAT;
+	return true;
+}
+
+bool Opcode::SetupShadowFeeler(RayCollider& collider)
+{
+	collider.SetFirstContact(true);
+	collider.SetHitCallback(null);
+	return true;
+}
+
+bool Opcode::SetupInOutTest(RayCollider& collider)
+{
+	collider.SetFirstContact(false);
+	collider.SetHitCallback(null);
+	// Results with collider.GetNbIntersections()
+	return true;
+}
+
+bool Opcode::Picking(
+CollisionFace& picked_face,
+const Ray& world_ray, const Model& model, const Matrix4x4* world,
+float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data)
+{
+	struct Local
+	{
+		struct CullData
+		{
+			CollisionFace*			Closest;
+			float					MinLimit;
+			CullModeCallback		Callback;
+			void*					UserData;
+			Point					ViewPoint;
+			const MeshInterface*	IMesh;
+		};
+
+		// Called for each stabbed face
+		static void RenderCullingCallback(const CollisionFace& hit, void* user_data)
+		{
+			CullData* Data = (CullData*)user_data;
+
+			// Discard face if we already have a closer hit
+			if(hit.mDistance>=Data->Closest->mDistance)	return;
+
+			// Discard face if hit point is smaller than min limit. This mainly happens when the face is in front
+			// of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an
+			// object that he may not even be able to see, which is very annoying.
+			if(hit.mDistance<=Data->MinLimit)	return;
+
+			// This is the index of currently stabbed triangle.
+			udword StabbedFaceIndex = hit.mFaceID;
+
+			// We may keep it or not, depending on backface culling
+			bool KeepIt = true;
+
+			// Catch *render* cull mode for this face
+			CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData);
+
+			if(CM!=CULLMODE_NONE)	// Don't even compute culling for double-sided triangles
+			{
+				// Compute backface culling for current face
+
+				VertexPointers VP;
+				Data->IMesh->GetTriangle(VP, StabbedFaceIndex);
+				if(VP.BackfaceCulling(Data->ViewPoint))
+				{
+					if(CM==CULLMODE_CW)		KeepIt = false;
+				}
+				else
+				{
+					if(CM==CULLMODE_CCW)	KeepIt = false;
+				}
+			}
+
+			if(KeepIt)	*Data->Closest = hit;
+		}
+	};
+
+	RayCollider RC;
+	RC.SetMaxDist(max_dist);
+	RC.SetTemporalCoherence(false);
+	RC.SetCulling(false);		// We need all faces since some of them can be double-sided
+	RC.SetFirstContact(false);
+	RC.SetHitCallback(Local::RenderCullingCallback);
+
+	picked_face.mFaceID		= INVALID_ID;
+	picked_face.mDistance	= MAX_FLOAT;
+	picked_face.mU			= 0.0f;
+	picked_face.mV			= 0.0f;
+
+	Local::CullData Data;
+	Data.Closest			= &picked_face;
+	Data.MinLimit			= min_dist;
+	Data.Callback			= callback;
+	Data.UserData			= user_data;
+	Data.ViewPoint			= view_point;
+	Data.IMesh				= model.GetMeshInterface();
+
+	if(world)
+	{
+		// Get matrices
+		Matrix4x4 InvWorld;
+		InvertPRMatrix(InvWorld, *world);
+
+		// Compute camera position in mesh space
+		Data.ViewPoint *= InvWorld;
+	}
+
+	RC.SetUserData(&Data);
+	if(RC.Collide(world_ray, model, world))
+	{
+		return picked_face.mFaceID!=INVALID_ID;
+	}
+	return false;
+}
+
+#endif
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Picking.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Picking.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Picking.h	(revision 216)
@@ -0,0 +1,45 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code to perform "picking".
+ *	\file		OPC_Picking.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_PICKING_H__
+#define __OPC_PICKING_H__
+
+#ifdef OPC_RAYHIT_CALLBACK
+
+	enum CullMode
+	{
+		CULLMODE_NONE	= 0,
+		CULLMODE_CW		= 1,
+		CULLMODE_CCW	= 2
+	};
+
+	typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data);
+
+	OPCODE_API	bool SetupAllHits		(RayCollider& collider, CollisionFaces& contacts);
+	OPCODE_API	bool SetupClosestHit	(RayCollider& collider, CollisionFace& closest_contact);
+	OPCODE_API	bool SetupShadowFeeler	(RayCollider& collider);
+	OPCODE_API	bool SetupInOutTest		(RayCollider& collider);
+
+	OPCODE_API	bool Picking(
+						CollisionFace& picked_face,
+						const Ray& world_ray, const Model& model, const Matrix4x4* world,
+						float min_dist, float max_dist, const Point& view_point, CullModeCallback callback, void* user_data);
+#endif
+
+#endif //__OPC_PICKING_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesAABBOverlap.h	(revision 216)
@@ -0,0 +1,50 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Planes-AABB overlap test.
+ *	- original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list)
+ *	- almost used "as-is", I even left the comments (hence the frustum-related notes)
+ *
+ *	\param		center			[in] box center
+ *	\param		extents			[in] box extents
+ *	\param		out_clip_mask	[out] bitmask for active planes
+ *	\param		in_clip_mask	[in] bitmask for active planes
+ *	\return		TRUE if boxes overlap planes
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL PlanesCollider::PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask)
+{
+	// Stats
+	mNbVolumeBVTests++;
+
+	const Plane* p = mPlanes;
+
+	// Evaluate through all active frustum planes. We determine the relation 
+	// between the AABB and a plane by using the concept of "near" and "far"
+	// vertices originally described by Zhang (and later by Möller). Our
+	// variant here uses 3 fabs ops, 6 muls, 7 adds and two floating point
+	// comparisons per plane. The routine early-exits if the AABB is found
+	// to be outside any of the planes. The loop also constructs a new output
+	// clip mask. Most FPUs have a native single-cycle fabsf() operation.
+
+	udword Mask				= 1;			// current mask index (1,2,4,8,..)
+	udword TmpOutClipMask	= 0;			// initialize output clip mask into empty. 
+
+	while(Mask<=in_clip_mask)				// keep looping while we have active planes left...
+	{
+		if(in_clip_mask & Mask)				// if clip plane is active, process it..
+		{               
+			float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z);	// ### fabsf could be precomputed
+			float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d;
+
+			if(NP < MP)						// near vertex behind the clip plane... 
+				return FALSE;				// .. so there is no intersection..
+			if((-NP) < MP)					// near and far vertices on different sides of plane..
+				TmpOutClipMask |= Mask;		// .. so update the clip mask...
+		}
+		Mask+=Mask;							// mk = (1<<plane)
+		p++;								// advance to next plane
+	}
+
+	out_clip_mask = TmpOutClipMask;			// copy output value (temp used to resolve aliasing!)
+	return TRUE;							// indicate that AABB intersects frustum
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesCollider.cpp	(revision 216)
@@ -0,0 +1,653 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a planes collider.
+ *	\file		OPC_PlanesCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 1st, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a Planes-vs-tree collider.
+ *
+ *	\class		PlanesCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		January, 1st, 2002
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_PlanesAABBOverlap.h"
+#include "OPC_PlanesTriOverlap.h"
+
+#define SET_CONTACT(prim_index, flag)		\
+	/* Set contact status */				\
+	mFlags |= flag;							\
+	mTouchedPrimitives->Add(udword(prim_index));
+
+//! Planes-triangle test
+#define PLANES_PRIM(prim_index, flag)		\
+	/* Request vertices from the app */		\
+	mIMesh->GetTriangle(mVP, prim_index);	\
+	/* Perform triangle-box overlap test */	\
+	if(PlanesTriOverlap(clip_mask))			\
+	{										\
+		SET_CONTACT(prim_index, flag)		\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+PlanesCollider::PlanesCollider() :
+	mPlanes		(null),
+	mNbPlanes	(0)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+PlanesCollider::~PlanesCollider()
+{
+	DELETEARRAY(mPlanes);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Validates current settings. You should call this method after all the settings and callbacks have been defined.
+ *	\return		null if everything is ok, else a string describing the problem
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const char* PlanesCollider::ValidateSettings()
+{
+	if(TemporalCoherenceEnabled() && !FirstContactEnabled())	return "Temporal coherence only works with ""First contact"" mode!";
+
+	return VolumeCollider::ValidateSettings();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic collision query for generic OPCODE models. After the call, access the results:
+ *	- with GetContactStatus()
+ *	- with GetNbTouchedPrimitives()
+ *	- with GetTouchedPrimitives()
+ *
+ *	\param		cache		[in/out] a planes cache
+ *	\param		planes		[in] list of planes in world space
+ *	\param		nb_planes	[in] number of planes
+ *	\param		model		[in] Opcode model to collide with
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool PlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm)
+{
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, planes, nb_planes, worldm))	return true;
+
+	udword PlaneMask = (1<<nb_planes)-1;
+
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+			else						_Collide(Tree->GetNodes(), PlaneMask);
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+			else						_Collide(Tree->GetNodes(), PlaneMask);
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+			else						_Collide(Tree->GetNodes(), PlaneMask);
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+			else						_Collide(Tree->GetNodes(), PlaneMask);
+		}
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a collision query :
+ *	- reset stats & contact status
+ *	- compute planes in model space
+ *	- check temporal coherence
+ *
+ *	\param		cache		[in/out] a planes cache
+ *	\param		planes		[in] list of planes
+ *	\param		nb_planes	[in] number of planes
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		TRUE if we can return immediately
+ *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL PlanesCollider::InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm)
+{
+	// 1) Call the base method
+	VolumeCollider::InitQuery();
+
+	// 2) Compute planes in model space
+	if(nb_planes>mNbPlanes)
+	{
+		DELETEARRAY(mPlanes);
+		mPlanes = new Plane[nb_planes];
+	}
+	mNbPlanes = nb_planes;
+
+	if(worldm)
+	{
+		Matrix4x4 InvWorldM;
+		InvertPRMatrix(InvWorldM, *worldm);
+
+//		for(udword i=0;i<nb_planes;i++)	mPlanes[i] = planes[i] * InvWorldM;
+		for(udword i=0;i<nb_planes;i++)	TransformPlane(mPlanes[i], planes[i], InvWorldM);
+	}
+	else CopyMemory(mPlanes, planes, nb_planes*sizeof(Plane));
+
+	// 3) Setup destination pointer
+	mTouchedPrimitives = &cache.TouchedPrimitives;
+
+	// 4) Special case: 1-triangle meshes [Opcode 1.3]
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		if(!SkipPrimitiveTests())
+		{
+			// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
+			mTouchedPrimitives->Reset();
+
+			// Perform overlap test between the unique triangle and the planes (and set contact status if needed)
+			udword clip_mask = (1<<mNbPlanes)-1;
+			PLANES_PRIM(udword(0), OPC_CONTACT)
+
+			// Return immediately regardless of status
+			return TRUE;
+		}
+	}
+
+	// 4) Check temporal coherence:
+	if(TemporalCoherenceEnabled())
+	{
+		// Here we use temporal coherence
+		// => check results from previous frame before performing the collision query
+		if(FirstContactEnabled())
+		{
+			// We're only interested in the first contact found => test the unique previously touched face
+			if(mTouchedPrimitives->GetNbEntries())
+			{
+				// Get index of previously touched face = the first entry in the array
+				udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
+
+				// Then reset the array:
+				// - if the overlap test below is successful, the index we'll get added back anyway
+				// - if it isn't, then the array should be reset anyway for the normal query
+				mTouchedPrimitives->Reset();
+
+				// Perform overlap test between the cached triangle and the planes (and set contact status if needed)
+				udword clip_mask = (1<<mNbPlanes)-1;
+				PLANES_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
+
+				// Return immediately if possible
+				if(GetContactStatus())	return TRUE;
+			}
+			// else no face has been touched during previous query
+			// => we'll have to perform a normal query
+		}
+		else mTouchedPrimitives->Reset();
+	}
+	else
+	{
+		// Here we don't use temporal coherence => do a normal query
+		mTouchedPrimitives->Reset();
+	}
+
+	return FALSE;
+}
+
+#define TEST_CLIP_MASK																					\
+	/* If the box is completely included, so are its children. We don't need to do extra tests, we */	\
+	/* can immediately output a list of visible children. Those ones won't need to be clipped. */		\
+	if(!OutClipMask)																					\
+	{																									\
+		/* Set contact status */																		\
+		mFlags |= OPC_CONTACT;																			\
+		_Dump(node);																					\
+		return;																							\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask)
+{
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->IsLeaf())
+	{
+		PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos(), OutClipMask);
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg(), OutClipMask);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask)
+{
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->IsLeaf())
+	{
+		PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos(), OutClipMask);
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg(), OutClipMask);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask)
+{
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->HasPosLeaf())	{ PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos(), OutClipMask);
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg(), OutClipMask);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask)
+{
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->HasPosLeaf())	{ PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos(), OutClipMask);
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg(), OutClipMask);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Test the box against the planes. If the box is completely culled, so are its children, hence we exit.
+	udword OutClipMask;
+	if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask))	return;
+
+	TEST_CLIP_MASK
+
+	// Else the box straddles one or several planes, so we need to recurse down the tree.
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
+}
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridPlanesCollider::HybridPlanesCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridPlanesCollider::~HybridPlanesCollider()
+{
+}
+
+bool HybridPlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm)
+{
+	// We don't want primitive tests here!
+	mFlags |= OPC_NO_PRIMITIVE_TESTS;
+
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, planes, nb_planes, worldm))	return true;
+
+	// Special case for 1-leaf trees
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
+		udword Nb = mIMesh->GetNbTriangles();
+
+		// Loop through all triangles
+		udword clip_mask = (1<<mNbPlanes)-1;
+		for(udword i=0;i<Nb;i++)
+		{
+			PLANES_PRIM(i, OPC_CONTACT)
+		}
+		return true;
+	}
+
+	// Override destination array since we're only going to get leaf boxes here
+	mTouchedBoxes.Reset();
+	mTouchedPrimitives = &mTouchedBoxes;
+
+	udword PlaneMask = (1<<nb_planes)-1;
+
+	// Now, do the actual query against leaf boxes
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
+		}
+	}
+
+	// We only have a list of boxes so far
+	if(GetContactStatus())
+	{
+		// Reset contact status, since it currently only reflects collisions with leaf boxes
+		Collider::InitQuery();
+
+		// Change dest container so that we can use built-in overlap tests and get collided primitives
+		cache.TouchedPrimitives.Reset();
+		mTouchedPrimitives = &cache.TouchedPrimitives;
+
+		// Read touched leaf boxes
+		udword Nb = mTouchedBoxes.GetNbEntries();
+		const udword* Touched = mTouchedBoxes.GetEntries();
+
+		const LeafTriangles* LT = model.GetLeafTriangles();
+		const udword* Indices = model.GetIndices();
+
+		// Loop through touched leaves
+		udword clip_mask = (1<<mNbPlanes)-1;
+		while(Nb--)
+		{
+			const LeafTriangles& CurrentLeaf = LT[*Touched++];
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = *T++;
+					PLANES_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = BaseIndex++;
+					PLANES_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+		}
+	}
+
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesCollider.h	(revision 216)
@@ -0,0 +1,121 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a planes collider.
+ *	\file		OPC_PlanesCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 1st, 2002
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_PLANESCOLLIDER_H__
+#define __OPC_PLANESCOLLIDER_H__
+
+	struct OPCODE_API PlanesCache : VolumeCache
+	{
+					PlanesCache()
+					{
+					}
+	};
+
+	class OPCODE_API PlanesCollider : public VolumeCollider
+	{
+		public:
+		// Constructor / Destructor
+											PlanesCollider();
+		virtual								~PlanesCollider();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic collision query for generic OPCODE models. After the call, access the results:
+		 *	- with GetContactStatus()
+		 *	- with GetNbTouchedPrimitives()
+		 *	- with GetTouchedPrimitives()
+		 *
+		 *	\param		cache			[in/out] a planes cache
+		 *	\param		planes			[in] list of planes in world space
+		 *	\param		nb_planes		[in] number of planes
+		 *	\param		model			[in] Opcode model to collide with
+		 *	\param		worldm			[in] model's world matrix, or null
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm=null);
+
+		// Mutant box-with-planes collision queries
+		inline_				bool			Collide(PlanesCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null)
+											{
+												Plane PL[6];
+
+												if(worldb)
+												{
+													// Create a new OBB in world space
+													OBB WorldBox;
+													box.Rotate(*worldb, WorldBox);
+													// Compute planes from the sides of the box
+													WorldBox.ComputePlanes(PL);
+												}
+												else
+												{
+													// Compute planes from the sides of the box
+													box.ComputePlanes(PL);
+												}
+
+												// Collide with box planes
+												return Collide(cache, PL, 6, model, worldm);
+											}
+		// Settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
+		 *	\return		null if everything is ok, else a string describing the problem
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(Collider)	const char*		ValidateSettings();
+
+		protected:
+		// Planes in model space
+							udword			mNbPlanes;
+							Plane*			mPlanes;
+		// Leaf description
+							VertexPointers	mVP;
+		// Internal methods
+							void			_Collide(const AABBCollisionNode* node, udword clip_mask);
+							void			_Collide(const AABBNoLeafNode* node, udword clip_mask);
+							void			_Collide(const AABBQuantizedNode* node, udword clip_mask);
+							void			_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask);
+							void			_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask);
+							void			_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask);
+			// Overlap tests
+		inline_				BOOL			PlanesAABBOverlap(const Point& center, const Point& extents, udword& out_clip_mask, udword in_clip_mask);
+		inline_				BOOL			PlanesTriOverlap(udword in_clip_mask);
+			// Init methods
+							BOOL			InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm=null);
+	};
+
+	class OPCODE_API HybridPlanesCollider : public PlanesCollider
+	{
+		public:
+		// Constructor / Destructor
+											HybridPlanesCollider();
+		virtual								~HybridPlanesCollider();
+
+							bool			Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm=null);
+		protected:
+							Container		mTouchedBoxes;
+	};
+
+#endif // __OPC_PLANESCOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_PlanesTriOverlap.h	(revision 216)
@@ -0,0 +1,40 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Planes-triangle overlap test.
+ *	\param		in_clip_mask	[in] bitmask for active planes
+ *	\return		TRUE if triangle overlap planes
+ *	\warning	THIS IS A CONSERVATIVE TEST !! Some triangles will be returned as intersecting, while they're not!
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL PlanesCollider::PlanesTriOverlap(udword in_clip_mask)
+{
+	// Stats
+	mNbVolumePrimTests++;
+
+	const Plane* p = mPlanes;
+	udword Mask = 1;
+
+	while(Mask<=in_clip_mask)
+	{
+		if(in_clip_mask & Mask)
+		{
+			float d0 = p->Distance(*mVP.Vertex[0]);
+			float d1 = p->Distance(*mVP.Vertex[1]);
+			float d2 = p->Distance(*mVP.Vertex[2]);
+			if(d0>0.0f && d1>0.0f && d2>0.0f)	return FALSE;
+//			if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK))	return FALSE;
+		}
+		Mask+=Mask;
+		p++;
+	}
+/*
+	for(udword i=0;i<6;i++)
+	{
+		float d0 = p[i].Distance(mLeafVerts[0]);
+		float d1 = p[i].Distance(mLeafVerts[1]);
+		float d2 = p[i].Distance(mLeafVerts[2]);
+		if(d0>0.0f && d1>0.0f && d2>0.0f)	return false;
+	}
+*/
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_RayAABBOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_RayAABBOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_RayAABBOverlap.h	(revision 216)
@@ -0,0 +1,63 @@
+// Opcode 1.1: ray-AABB overlap tests based on Woo's code
+// Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem
+//
+// The point of intersection is not computed anymore. The distance to impact is not needed anymore
+// since we now have two different queries for segments or rays.
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes a segment-AABB overlap test using the separating axis theorem. Segment is cached within the class.
+ *	\param		center	[in] AABB center
+ *	\param		extents	[in] AABB extents
+ *	\return		true on overlap
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL RayCollider::SegmentAABBOverlap(const Point& center, const Point& extents)
+{
+	// Stats
+	mNbRayBVTests++;
+
+	float Dx = mData2.x - center.x;		if(fabsf(Dx) > extents.x + mFDir.x)	return FALSE;
+	float Dy = mData2.y - center.y;		if(fabsf(Dy) > extents.y + mFDir.y)	return FALSE;
+	float Dz = mData2.z - center.z;		if(fabsf(Dz) > extents.z + mFDir.z)	return FALSE;
+
+	float f;
+	f = mData.y * Dz - mData.z * Dy;	if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y)	return FALSE;
+	f = mData.z * Dx - mData.x * Dz;	if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x)	return FALSE;
+	f = mData.x * Dy - mData.y * Dx;	if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x)	return FALSE;
+
+	return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class.
+ *	\param		center	[in] AABB center
+ *	\param		extents	[in] AABB extents
+ *	\return		true on overlap
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL RayCollider::RayAABBOverlap(const Point& center, const Point& extents)
+{
+	// Stats
+	mNbRayBVTests++;
+
+//	float Dx = mOrigin.x - center.x;	if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f)	return FALSE;
+//	float Dy = mOrigin.y - center.y;	if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f)	return FALSE;
+//	float Dz = mOrigin.z - center.z;	if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f)	return FALSE;
+
+	float Dx = mOrigin.x - center.x;	if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f)	return FALSE;
+	float Dy = mOrigin.y - center.y;	if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f)	return FALSE;
+	float Dz = mOrigin.z - center.z;	if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f)	return FALSE;
+
+//	float Dx = mOrigin.x - center.x;	if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f)	return FALSE;
+//	float Dy = mOrigin.y - center.y;	if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f)	return FALSE;
+//	float Dz = mOrigin.z - center.z;	if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f)	return FALSE;
+
+	float f;
+	f = mDir.y * Dz - mDir.z * Dy;		if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y)	return FALSE;
+	f = mDir.z * Dx - mDir.x * Dz;		if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x)	return FALSE;
+	f = mDir.x * Dy - mDir.y * Dx;		if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x)	return FALSE;
+
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_RayCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_RayCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_RayCollider.cpp	(revision 216)
@@ -0,0 +1,762 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a ray collider.
+ *	\file		OPC_RayCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a ray-vs-tree collider.
+ *	This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision.
+ *
+ *	HIGHER DISTANCE BOUND:
+ *
+ *		If P0 and P1 are two 3D points, let's define:
+ *		- d = distance between P0 and P1
+ *		- Origin	= P0
+ *		- Direction	= (P1 - P0) / d = normalized direction vector
+ *		- A parameter t such as a point P on the line (P0,P1) is P = Origin + t * Direction
+ *		- t = 0  -->  P = P0
+ *		- t = d  -->  P = P1
+ *
+ *		Then we can define a general "ray" as:
+ *
+ *			struct Ray
+ *			{
+ *				Point	Origin;
+ *				Point	Direction;
+ *			};
+ *
+ *		But it actually maps three different things:
+ *		- a segment,   when 0 <= t <= d
+ *		- a half-line, when 0 <= t < +infinity, or -infinity < t <= d
+ *		- a line,      when -infinity < t < +infinity
+ *
+ *		In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity.
+ *		We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin.
+ *
+ *		In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist().
+ *
+ *		Query	|segment			|half-line		|line
+ *		--------|-------------------|---------------|----------------
+ *		Usages	|-shadow feelers	|-raytracing	|-
+ *				|-sweep tests		|-in/out tests	|
+ *
+ *	FIRST CONTACT:
+ *
+ *		- You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact().
+ *		- In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where
+ *		you want to know whether the path to the light is free or not (a boolean answer is enough).
+ *		- In "all contacts" mode we return all faces hit by the ray.
+ *
+ *	TEMPORAL COHERENCE:
+ *
+ *		- You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence().
+ *		- It currently only works in "first contact" mode.
+ *		- If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries
+ *		start by colliding the ray against the cached triangle. If they still collide, we return immediately.
+ *
+ *	CLOSEST HIT:
+ *
+ *		- You can enable or disable "closest hit" with RayCollider::SetClosestHit().
+ *		- It currently only works in "all contacts" mode.
+ *		- If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported.
+ *
+ *	BACKFACE CULLING:
+ *
+ *		- You can enable or disable backface culling with RayCollider::SetCulling().
+ *		- If culling is enabled, ray will not hit back faces (only front faces).
+ *		
+ *
+ *
+ *	\class		RayCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		June, 2, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	This class describes a face hit by a ray or segment.
+ *	This is a particular class dedicated to stabbing queries.
+ *
+ *	\class		CollisionFace
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	This class is a dedicated collection of CollisionFace.
+ *
+ *	\class		CollisionFaces
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_RayAABBOverlap.h"
+#include "OPC_RayTriOverlap.h"
+
+#define SET_CONTACT(prim_index, flag)											\
+	mNbIntersections++;															\
+	/* Set contact status */													\
+	mFlags |= flag;																\
+	/* In any case the contact has been found and recorded in mStabbedFace  */	\
+	mStabbedFace.mFaceID = prim_index;
+
+#ifdef OPC_RAYHIT_CALLBACK
+
+	#define HANDLE_CONTACT(prim_index, flag)													\
+		SET_CONTACT(prim_index, flag)															\
+																								\
+		if(mHitCallback)	(mHitCallback)(mStabbedFace, mUserData);
+
+	#define UPDATE_CACHE					\
+		if(cache && GetContactStatus())		\
+		{									\
+			*cache	= mStabbedFace.mFaceID;	\
+		}
+#else
+
+	#define HANDLE_CONTACT(prim_index, flag)													\
+		SET_CONTACT(prim_index, flag)															\
+																								\
+		/* Now we can also record it in mStabbedFaces if available */							\
+		if(mStabbedFaces)																		\
+		{																						\
+			/* If we want all faces or if that's the first one we hit */						\
+			if(!mClosestHit || !mStabbedFaces->GetNbFaces())									\
+			{																					\
+				mStabbedFaces->AddFace(mStabbedFace);											\
+			}																					\
+			else																				\
+			{																					\
+				/* We only keep closest hit */													\
+				CollisionFace* Current = const_cast<CollisionFace*>(mStabbedFaces->GetFaces());	\
+				if(Current && mStabbedFace.mDistance<Current->mDistance)						\
+				{																				\
+					*Current = mStabbedFace;													\
+				}																				\
+			}																					\
+		}
+
+	#define UPDATE_CACHE												\
+		if(cache && GetContactStatus() && mStabbedFaces)				\
+		{																\
+			const CollisionFace* Current = mStabbedFaces->GetFaces();	\
+			if(Current)	*cache	= Current->mFaceID;						\
+			else		*cache	= INVALID_ID;							\
+		}
+#endif
+
+#define SEGMENT_PRIM(prim_index, flag)														\
+	/* Request vertices from the app */														\
+	VertexPointers VP;	mIMesh->GetTriangle(VP, prim_index);								\
+																							\
+	/* Perform ray-tri overlap test and return */											\
+	if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))							\
+	{																						\
+		/* Intersection point is valid if dist < segment's length */						\
+		/* We know dist>0 so we can use integers */											\
+		if(IR(mStabbedFace.mDistance)<IR(mMaxDist))											\
+		{																					\
+			HANDLE_CONTACT(prim_index, flag)												\
+		}																					\
+	}
+
+#define RAY_PRIM(prim_index, flag)															\
+	/* Request vertices from the app */														\
+	VertexPointers VP;	mIMesh->GetTriangle(VP, prim_index);								\
+																							\
+	/* Perform ray-tri overlap test and return */											\
+	if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))							\
+	{																						\
+		HANDLE_CONTACT(prim_index, flag)													\
+	}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+RayCollider::RayCollider() :
+	mNbRayBVTests		(0),
+	mNbRayPrimTests		(0),
+	mNbIntersections	(0),
+	mCulling			(true),
+#ifdef OPC_RAYHIT_CALLBACK
+	mHitCallback		(null),
+	mUserData			(0),
+#else
+	mClosestHit			(false),
+	mStabbedFaces		(null),
+#endif
+	mMaxDist			(MAX_FLOAT)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+RayCollider::~RayCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Validates current settings. You should call this method after all the settings and callbacks have been defined.
+ *	\return		null if everything is ok, else a string describing the problem
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const char* RayCollider::ValidateSettings()
+{
+	if(mMaxDist<0.0f)											return "Higher distance bound must be positive!";
+	if(TemporalCoherenceEnabled() && !FirstContactEnabled())	return "Temporal coherence only works with ""First contact"" mode!";
+#ifndef OPC_RAYHIT_CALLBACK
+	if(mClosestHit && FirstContactEnabled())					return "Closest hit doesn't work with ""First contact"" mode!";
+	if(TemporalCoherenceEnabled() && mClosestHit)				return "Temporal coherence can't guarantee to report closest hit!";
+#endif
+	if(SkipPrimitiveTests())									return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)";
+	return null;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic stabbing query for generic OPCODE models. After the call, access the results:
+ *	- with GetContactStatus()
+ *	- in the user-provided destination array
+ *
+ *	\param		world_ray		[in] stabbing ray in world space
+ *	\param		model			[in] Opcode model to collide with
+ *	\param		world			[in] model's world matrix, or null
+ *	\param		cache			[in] a possibly cached face index, or null
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache)
+{
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(world_ray, world, cache))	return true;
+
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform stabbing query
+			if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_SegmentStab(Tree->GetNodes());
+			else								_RayStab(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform stabbing query
+			if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_SegmentStab(Tree->GetNodes());
+			else								_RayStab(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform stabbing query
+			if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_SegmentStab(Tree->GetNodes());
+			else								_RayStab(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform stabbing query
+			if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_SegmentStab(Tree->GetNodes());
+			else								_RayStab(Tree->GetNodes());
+		}
+	}
+
+	// Update cache if needed
+	UPDATE_CACHE
+	return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a stabbing query :
+ *	- reset stats & contact status
+ *	- compute ray in local space
+ *	- check temporal coherence
+ *
+ *	\param		world_ray	[in] stabbing ray in world space
+ *	\param		world		[in] object's world matrix, or null
+ *	\param		face_id		[in] index of previously stabbed triangle
+ *	\return		TRUE if we can return immediately
+ *	\warning	SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id)
+{
+	// Reset stats & contact status
+	Collider::InitQuery();
+	mNbRayBVTests		= 0;
+	mNbRayPrimTests		= 0;
+	mNbIntersections	= 0;
+#ifndef OPC_RAYHIT_CALLBACK
+	if(mStabbedFaces)	mStabbedFaces->Reset();
+#endif
+
+	// Compute ray in local space
+	// The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests)
+	if(world)
+	{
+		Matrix3x3 InvWorld = *world;
+		mDir = InvWorld * world_ray.mDir;
+
+		Matrix4x4 World;
+		InvertPRMatrix(World, *world);
+		mOrigin = world_ray.mOrig * World;
+	}
+	else
+	{
+		mDir	= world_ray.mDir;
+		mOrigin	= world_ray.mOrig;
+	}
+
+	// 4) Special case: 1-triangle meshes [Opcode 1.3]
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
+		if(!SkipPrimitiveTests())
+		{
+			// Perform overlap test between the unique triangle and the ray (and set contact status if needed)
+			SEGMENT_PRIM(udword(0), OPC_CONTACT)
+
+			// Return immediately regardless of status
+			return TRUE;
+		}
+	}
+
+	// Check temporal coherence :
+
+	// Test previously colliding primitives first
+	if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID)
+	{
+#ifdef OLD_CODE
+#ifndef OPC_RAYHIT_CALLBACK
+		if(!mClosestHit)
+#endif
+		{
+			// Request vertices from the app
+			VertexPointers VP;
+			mIMesh->GetTriangle(VP, *face_id);
+			// Perform ray-cached tri overlap test
+			if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
+			{
+				// Intersection point is valid if:
+				// - distance is positive (else it can just be a face behind the orig point)
+				// - distance is smaller than a given max distance (useful for shadow feelers)
+//				if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistance<mMaxDist)
+				if(IR(mStabbedFace.mDistance)<IR(mMaxDist))	// The other test is already performed in RayTriOverlap
+				{
+					// Set contact status
+					mFlags |= OPC_TEMPORAL_CONTACT;
+
+					mStabbedFace.mFaceID = *face_id;
+
+#ifndef OPC_RAYHIT_CALLBACK
+					if(mStabbedFaces)	mStabbedFaces->AddFace(mStabbedFace);
+#endif
+					return TRUE;
+				}
+			}
+		}
+#else
+		// New code
+		// We handle both Segment/ray queries with the same segment code, and a possible infinite limit
+		SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT)
+
+		// Return immediately if possible
+		if(GetContactStatus())	return TRUE;
+#endif
+	}
+
+	// Precompute data (moved after temporal coherence since only needed for ray-AABB)
+	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)
+	{
+		// For Segment-AABB overlap
+		mData = 0.5f * mDir * mMaxDist;
+		mData2 = mOrigin + mData;
+
+		// Precompute mFDir;
+		mFDir.x = fabsf(mData.x);
+		mFDir.y = fabsf(mData.y);
+		mFDir.z = fabsf(mData.z);
+	}
+	else
+	{
+		// For Ray-AABB overlap
+//		udword x = SIR(mDir.x)-1;
+//		udword y = SIR(mDir.y)-1;
+//		udword z = SIR(mDir.z)-1;
+//		mData.x = FR(x);
+//		mData.y = FR(y);
+//		mData.z = FR(z);
+
+		// Precompute mFDir;
+		mFDir.x = fabsf(mDir.x);
+		mFDir.y = fabsf(mDir.y);
+		mFDir.z = fabsf(mDir.z);
+	}
+
+	return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Stabbing query for vanilla AABB trees.
+ *	\param		world_ray		[in] stabbing ray in world space
+ *	\param		tree			[in] AABB tree
+ *	\param		box_indices		[out] indices of stabbed boxes
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices)
+{
+	// ### bad design here
+
+	// This is typically called for a scene tree, full of -AABBs-, not full of triangles.
+	// So we don't really have "primitives" to deal with. Hence it doesn't work with
+	// "FirstContact" + "TemporalCoherence".
+	ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
+
+	// Checkings
+	if(!tree)					return false;
+
+	// Init collision query
+	// Basically this is only called to initialize precomputed data
+	if(InitQuery(world_ray))	return true;
+
+	// Perform stabbing query
+	if(IR(mMaxDist)!=IEEE_MAX_FLOAT)	_SegmentStab(tree, box_indices);
+	else								_RayStab(tree, box_indices);
+
+	return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_SegmentStab(const AABBCollisionNode* node)
+{
+	// Perform Segment-AABB overlap test
+	if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	if(node->IsLeaf())
+	{
+		SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_SegmentStab(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_SegmentStab(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_SegmentStab(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Segment-AABB overlap test
+	if(!SegmentAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf())
+	{
+		SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_SegmentStab(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_SegmentStab(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_SegmentStab(const AABBNoLeafNode* node)
+{
+	// Perform Segment-AABB overlap test
+	if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	if(node->HasPosLeaf())
+	{
+		SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
+	}
+	else _SegmentStab(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())
+	{
+		SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
+	}
+	else _SegmentStab(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Segment-AABB overlap test
+	if(!SegmentAABBOverlap(Center, Extents))	return;
+
+	if(node->HasPosLeaf())
+	{
+		SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
+	}
+	else _SegmentStab(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())
+	{
+		SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
+	}
+	else _SegmentStab(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for vanilla AABB trees.
+ *	\param		node		[in] current collision node
+ *	\param		box_indices	[out] indices of stabbed boxes
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices)
+{
+	// Test the box against the segment
+	Point Center, Extents;
+	node->GetAABB()->GetCenter(Center);
+	node->GetAABB()->GetExtents(Extents);
+	if(!SegmentAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf())
+	{
+		box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives());
+	}
+	else
+	{
+		_SegmentStab(node->GetPos(), box_indices);
+		_SegmentStab(node->GetNeg(), box_indices);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_RayStab(const AABBCollisionNode* node)
+{
+	// Perform Ray-AABB overlap test
+	if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	if(node->IsLeaf())
+	{
+		RAY_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_RayStab(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_RayStab(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_RayStab(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Ray-AABB overlap test
+	if(!RayAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf())
+	{
+		RAY_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_RayStab(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_RayStab(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_RayStab(const AABBNoLeafNode* node)
+{
+	// Perform Ray-AABB overlap test
+	if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	if(node->HasPosLeaf())
+	{
+		RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
+	}
+	else _RayStab(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())
+	{
+		RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
+	}
+	else _RayStab(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Ray-AABB overlap test
+	if(!RayAABBOverlap(Center, Extents))	return;
+
+	if(node->HasPosLeaf())
+	{
+		RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT)
+	}
+	else _RayStab(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())
+	{
+		RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT)
+	}
+	else _RayStab(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive stabbing query for vanilla AABB trees.
+ *	\param		node		[in] current collision node
+ *	\param		box_indices	[out] indices of stabbed boxes
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices)
+{
+	// Test the box against the ray
+	Point Center, Extents;
+	node->GetAABB()->GetCenter(Center);
+	node->GetAABB()->GetExtents(Extents);
+	if(!RayAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf())
+	{
+		mFlags |= OPC_CONTACT;
+		box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives());
+	}
+	else
+	{
+		_RayStab(node->GetPos(), box_indices);
+		_RayStab(node->GetNeg(), box_indices);
+	}
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_RayCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_RayCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_RayCollider.h	(revision 216)
@@ -0,0 +1,225 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a ray collider.
+ *	\file		OPC_RayCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_RAYCOLLIDER_H__
+#define __OPC_RAYCOLLIDER_H__
+
+	class OPCODE_API CollisionFace
+	{
+		public:
+		//! Constructor
+		inline_				CollisionFace()			{}
+		//! Destructor
+		inline_				~CollisionFace()		{}
+
+				udword		mFaceID;				//!< Index of touched face
+				float		mDistance;				//!< Distance from collider to hitpoint
+				float		mU, mV;					//!< Impact barycentric coordinates
+	};
+
+	class OPCODE_API CollisionFaces : public Container
+	{
+		public:
+		//! Constructor
+										CollisionFaces()						{}
+		//! Destructor
+										~CollisionFaces()						{}
+
+		inline_	udword					GetNbFaces()					const	{ return GetNbEntries()>>2;						}
+		inline_	const CollisionFace*	GetFaces()						const	{ return (const CollisionFace*)GetEntries();	}
+
+		inline_	void					Reset()									{ Container::Reset();							}
+
+		inline_	void					AddFace(const CollisionFace& face)		{ Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV);	}
+	};
+
+#ifdef OPC_RAYHIT_CALLBACK
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	User-callback, called by OPCODE to record a hit.
+	 *	\param		hit			[in] current hit
+	 *	\param		user_data	[in] user-defined data from SetCallback()
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	typedef void	(*HitCallback)	(const CollisionFace& hit, void* user_data);
+#endif
+
+	class OPCODE_API RayCollider : public Collider
+	{
+		public:
+		// Constructor / Destructor
+											RayCollider();
+		virtual								~RayCollider();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic stabbing query for generic OPCODE models. After the call, access the results:
+		 *	- with GetContactStatus()
+		 *	- in the user-provided destination array
+		 *
+		 *	\param		world_ray		[in] stabbing ray in world space
+		 *	\param		model			[in] Opcode model to collide with
+		 *	\param		world			[in] model's world matrix, or null
+		 *	\param		cache			[in] a possibly cached face index, or null
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
+		//
+							bool			Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices);
+		// Settings
+
+#ifndef OPC_RAYHIT_CALLBACK
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: enable or disable "closest hit" mode.
+		 *	\param		flag		[in] true to report closest hit only
+		 *	\see		SetCulling(bool flag)
+		 *	\see		SetMaxDist(float max_dist)
+		 *	\see		SetDestination(StabbedFaces* sf)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetClosestHit(bool flag)				{ mClosestHit	= flag;		}
+#endif
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: enable or disable backface culling.
+		 *	\param		flag		[in] true to enable backface culling
+		 *	\see		SetClosestHit(bool flag)
+		 *	\see		SetMaxDist(float max_dist)
+		 *	\see		SetDestination(StabbedFaces* sf)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetCulling(bool flag)					{ mCulling		= flag;		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: sets the higher distance bound.
+		 *	\param		max_dist	[in] higher distance bound. Default = maximal value, for ray queries (else segment)
+		 *	\see		SetClosestHit(bool flag)
+		 *	\see		SetCulling(bool flag)
+		 *	\see		SetDestination(StabbedFaces* sf)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetMaxDist(float max_dist=MAX_FLOAT)	{ mMaxDist		= max_dist;	}
+
+#ifdef OPC_RAYHIT_CALLBACK
+		inline_				void			SetHitCallback(HitCallback cb)			{ mHitCallback	= cb;			}
+		inline_				void			SetUserData(void* user_data)			{ mUserData		= user_data;	}
+#else
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: sets the destination array for stabbed faces.
+		 *	\param		cf			[in] destination array, filled during queries
+		 *	\see		SetClosestHit(bool flag)
+		 *	\see		SetCulling(bool flag)
+		 *	\see		SetMaxDist(float max_dist)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetDestination(CollisionFaces* cf)		{ mStabbedFaces	= cf;		}
+#endif
+		// Stats
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of Ray-BV overlap tests after a collision query.
+		 *	\see		GetNbRayPrimTests()
+		 *	\see		GetNbIntersections()
+		 *	\return		the number of Ray-BV tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbRayBVTests()				const	{ return mNbRayBVTests;		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of Ray-Triangle overlap tests after a collision query.
+		 *	\see		GetNbRayBVTests()
+		 *	\see		GetNbIntersections()
+		 *	\return		the number of Ray-Triangle tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbRayPrimTests()				const	{ return mNbRayPrimTests;	}
+
+		// In-out test
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of intersection found after a collision query. Can be used for in/out tests.
+		 *	\see		GetNbRayBVTests()
+		 *	\see		GetNbRayPrimTests()
+		 *	\return		the number of valid intersections during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbIntersections()			const	{ return mNbIntersections;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
+		 *	\return		null if everything is ok, else a string describing the problem
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(Collider)	const char*		ValidateSettings();
+
+		protected:
+		// Ray in local space
+							Point			mOrigin;			//!< Ray origin
+							Point			mDir;				//!< Ray direction (normalized)
+							Point			mFDir;				//!< fabsf(mDir)
+							Point			mData, mData2;
+		// Stabbed faces
+							CollisionFace	mStabbedFace;		//!< Current stabbed face
+#ifdef OPC_RAYHIT_CALLBACK
+							HitCallback		mHitCallback;		//!< Callback used to record a hit
+							void*			mUserData;			//!< User-defined data
+#else
+							CollisionFaces*	mStabbedFaces;		//!< List of stabbed faces
+#endif
+		// Stats
+							udword			mNbRayBVTests;		//!< Number of Ray-BV tests
+							udword			mNbRayPrimTests;	//!< Number of Ray-Primitive tests
+		// In-out test
+							udword			mNbIntersections;	//!< Number of valid intersections
+		// Dequantization coeffs
+							Point			mCenterCoeff;
+							Point			mExtentsCoeff;
+		// Settings
+							float			mMaxDist;			//!< Valid segment on the ray
+#ifndef OPC_RAYHIT_CALLBACK
+							bool			mClosestHit;		//!< Report closest hit only
+#endif
+							bool			mCulling;			//!< Stab culled faces or not
+		// Internal methods
+							void			_SegmentStab(const AABBCollisionNode* node);
+							void			_SegmentStab(const AABBNoLeafNode* node);
+							void			_SegmentStab(const AABBQuantizedNode* node);
+							void			_SegmentStab(const AABBQuantizedNoLeafNode* node);
+							void			_SegmentStab(const AABBTreeNode* node, Container& box_indices);
+							void			_RayStab(const AABBCollisionNode* node);
+							void			_RayStab(const AABBNoLeafNode* node);
+							void			_RayStab(const AABBQuantizedNode* node);
+							void			_RayStab(const AABBQuantizedNoLeafNode* node);
+							void			_RayStab(const AABBTreeNode* node, Container& box_indices);
+			// Overlap tests
+		inline_				BOOL			RayAABBOverlap(const Point& center, const Point& extents);
+		inline_				BOOL			SegmentAABBOverlap(const Point& center, const Point& extents);
+		inline_				BOOL			RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
+			// Init methods
+							BOOL			InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
+	};
+
+#endif // __OPC_RAYCOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_RayTriOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_RayTriOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_RayTriOverlap.h	(revision 216)
@@ -0,0 +1,89 @@
+#define LOCAL_EPSILON 0.000001f
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes a ray-triangle intersection test.
+ *	Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection".
+ *	It's been optimized a bit with integer code, and modified to return a non-intersection if distance from
+ *	ray origin to triangle is negative.
+ *
+ *	\param		vert0	[in] triangle vertex
+ *	\param		vert1	[in] triangle vertex
+ *	\param		vert2	[in] triangle vertex
+ *	\return		true on overlap. mStabbedFace is filled with relevant info.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
+{
+	// Stats
+	mNbRayPrimTests++;
+
+	// Find vectors for two edges sharing vert0
+	Point edge1 = vert1 - vert0;
+	Point edge2 = vert2 - vert0;
+
+	// Begin calculating determinant - also used to calculate U parameter
+	Point pvec = mDir^edge2;
+
+	// If determinant is near zero, ray lies in plane of triangle
+	float det = edge1|pvec;
+
+	if(mCulling)
+	{
+		if(det<LOCAL_EPSILON)														return FALSE;
+		// From here, det is > 0. So we can use integer cmp.
+
+		// Calculate distance from vert0 to ray origin
+		Point tvec = mOrigin - vert0;
+
+		// Calculate U parameter and test bounds
+		mStabbedFace.mU = tvec|pvec;
+//		if(IR(u)&0x80000000 || u>det)					return FALSE;
+		if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det))		return FALSE;
+
+		// Prepare to test V parameter
+		Point qvec = tvec^edge1;
+
+		// Calculate V parameter and test bounds
+		mStabbedFace.mV = mDir|qvec;
+		if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det)	return FALSE;
+
+		// Calculate t, scale parameters, ray intersects triangle
+		mStabbedFace.mDistance = edge2|qvec;
+		// Det > 0 so we can early exit here
+		// Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
+		if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance))								return FALSE;
+		// Else go on
+		float OneOverDet = 1.0f / det;
+		mStabbedFace.mDistance *= OneOverDet;
+		mStabbedFace.mU *= OneOverDet;
+		mStabbedFace.mV *= OneOverDet;
+	}
+	else
+	{
+		// the non-culling branch
+		if(det>-LOCAL_EPSILON && det<LOCAL_EPSILON)									return FALSE;
+		float OneOverDet = 1.0f / det;
+
+		// Calculate distance from vert0 to ray origin
+		Point tvec = mOrigin - vert0;
+
+		// Calculate U parameter and test bounds
+		mStabbedFace.mU = (tvec|pvec) * OneOverDet;
+//		if(IR(u)&0x80000000 || u>1.0f)					return FALSE;
+		if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0)		return FALSE;
+
+		// prepare to test V parameter
+		Point qvec = tvec^edge1;
+
+		// Calculate V parameter and test bounds
+		mStabbedFace.mV = (mDir|qvec) * OneOverDet;
+		if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f)	return FALSE;
+
+		// Calculate t, ray intersects triangle
+		mStabbedFace.mDistance = (edge2|qvec) * OneOverDet;
+		// Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
+		if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance))								return FALSE;
+	}
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_Settings.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_Settings.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_Settings.h	(revision 216)
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains compilation flags.
+ *	\file		OPC_Settings.h
+ *	\author		Pierre Terdiman
+ *	\date		May, 12, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_SETTINGS_H__
+#define __OPC_SETTINGS_H__
+
+	//! Use CPU comparisons (comment that line to use standard FPU compares)
+	#define OPC_CPU_COMPARE
+
+	//! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++)
+	#define OPC_USE_FCOMI
+
+	//! Use epsilon value in tri-tri overlap test
+	#define OPC_TRITRI_EPSILON_TEST
+
+	//! Use tree-coherence or not [not implemented yet]
+//	#define OPC_USE_TREE_COHERENCE
+
+	//! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much)
+//	#define OPC_USE_CALLBACKS
+
+	//! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much)
+	#define OPC_USE_STRIDE
+
+	//! Discard negative pointer in vanilla trees
+	#define OPC_NO_NEG_VANILLA_TREE
+
+	//! Use a callback in the ray collider
+	//#define OPC_RAYHIT_CALLBACK
+
+	// NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test
+
+#endif //__OPC_SETTINGS_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_SphereAABBOverlap.h	(revision 216)
@@ -0,0 +1,128 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Sphere-AABB overlap test, based on Jim Arvo's code.
+ *	\param		center		[in] box center
+ *	\param		extents		[in] box extents
+ *	\return		TRUE on overlap
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL SphereCollider::SphereAABBOverlap(const Point& center, const Point& extents)
+{ 
+	// Stats
+	mNbVolumeBVTests++;
+
+	float d = 0.0f;
+
+	//find the square of the distance
+	//from the sphere to the box
+#ifdef OLDIES
+	for(udword i=0;i<3;i++)
+	{
+		float tmp = mCenter[i] - center[i];
+		float s = tmp + extents[i];
+
+		if(s<0.0f)	d += s*s;
+		else
+		{
+			s = tmp - extents[i];
+			if(s>0.0f)	d += s*s;
+		}
+	}
+#endif
+
+//#ifdef NEW_TEST
+
+//	float tmp = mCenter.x - center.x;
+//	float s = tmp + extents.x;
+
+	float tmp,s;
+
+	tmp = mCenter.x - center.x;
+	s = tmp + extents.x;
+
+	if(s<0.0f)
+	{
+		d += s*s;
+		if(d>mRadius2)	return FALSE;
+	}
+	else
+	{
+		s = tmp - extents.x;
+		if(s>0.0f)
+		{
+			d += s*s;
+			if(d>mRadius2)	return FALSE;
+		}
+	}
+
+	tmp = mCenter.y - center.y;
+	s = tmp + extents.y;
+
+	if(s<0.0f)
+	{
+		d += s*s;
+		if(d>mRadius2)	return FALSE;
+	}
+	else
+	{
+		s = tmp - extents.y;
+		if(s>0.0f)
+		{
+			d += s*s;
+			if(d>mRadius2)	return FALSE;
+		}
+	}
+
+	tmp = mCenter.z - center.z;
+	s = tmp + extents.z;
+
+	if(s<0.0f)
+	{
+		d += s*s;
+		if(d>mRadius2)	return FALSE;
+	}
+	else
+	{
+		s = tmp - extents.z;
+		if(s>0.0f)
+		{
+			d += s*s;
+			if(d>mRadius2)	return FALSE;
+		}
+	}
+//#endif
+
+#ifdef OLDIES
+//	Point Min = center - extents;
+//	Point Max = center + extents;
+
+	float d = 0.0f;
+
+	//find the square of the distance
+	//from the sphere to the box
+	for(udword i=0;i<3;i++)
+	{
+float Min = center[i] - extents[i];
+
+//		if(mCenter[i]<Min[i])
+		if(mCenter[i]<Min)
+		{
+//			float s = mCenter[i] - Min[i];
+			float s = mCenter[i] - Min;
+			d += s*s;
+		}
+		else
+		{
+float Max = center[i] + extents[i];
+
+//			if(mCenter[i]>Max[i])
+			if(mCenter[i]>Max)
+			{
+				float s = mCenter[i] - Max;
+				d += s*s;
+			}
+		}
+	}
+#endif
+	return d <= mRadius2;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_SphereCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_SphereCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_SphereCollider.cpp	(revision 216)
@@ -0,0 +1,739 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a sphere collider.
+ *	\file		OPC_SphereCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains a sphere-vs-tree collider.
+ *	This class performs a collision test between a sphere and an AABB tree. You can use this to do a standard player vs world collision,
+ *	in a Nettle/Telemachos way. It doesn't suffer from all reported bugs in those two classic codes - the "new" one by Paul Nettle is a
+ *	debuggued version I think. Collision response can be driven by reported collision data - it works extremely well for me. In sake of
+ *	efficiency, all meshes (that is, all AABB trees) should of course also be kept in an extra hierarchical structure (octree, whatever).
+ *
+ *	\class		SphereCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		June, 2, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_SphereAABBOverlap.h"
+#include "OPC_SphereTriOverlap.h"
+
+#define SET_CONTACT(prim_index, flag)									\
+	/* Set contact status */											\
+	mFlags |= flag;														\
+	mTouchedPrimitives->Add(udword(prim_index));
+
+//! Sphere-triangle overlap test
+#define SPHERE_PRIM(prim_index, flag)									\
+	/* Request vertices from the app */									\
+	VertexPointers VP;	mIMesh->GetTriangle(VP, prim_index);			\
+																		\
+	/* Perform sphere-tri overlap test */								\
+	if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))	\
+	{																	\
+		SET_CONTACT(prim_index, flag)									\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SphereCollider::SphereCollider()
+{
+	mCenter.Zero();
+	mRadius2 = 0.0f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SphereCollider::~SphereCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic collision query for generic OPCODE models. After the call, access the results:
+ *	- with GetContactStatus()
+ *	- with GetNbTouchedPrimitives()
+ *	- with GetTouchedPrimitives()
+ *
+ *	\param		cache		[in/out] a sphere cache
+ *	\param		sphere		[in] collision sphere in local space
+ *	\param		model		[in] Opcode model to collide with
+ *	\param		worlds		[in] sphere's world matrix, or null
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm)
+{
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, sphere, worlds, worldm))	return true;
+
+	// Special case for 1-leaf trees
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
+		udword Nb = mIMesh->GetNbTriangles();
+		// Loop through all triangles
+		for(udword i=0;i<Nb;i++)
+		{
+			SPHERE_PRIM(i, OPC_CONTACT)
+		}
+		return true;
+	}
+
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query
+			if(SkipPrimitiveTests())	_CollideNoPrimitiveTest(Tree->GetNodes());
+			else						_Collide(Tree->GetNodes());
+		}
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a collision query :
+ *	- reset stats & contact status
+ *	- setup matrices
+ *	- check temporal coherence
+ *
+ *	\param		cache		[in/out] a sphere cache
+ *	\param		sphere		[in] sphere in local space
+ *	\param		worlds		[in] sphere's world matrix, or null
+ *	\param		worldm		[in] model's world matrix, or null
+ *	\return		TRUE if we can return immediately
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm)
+{
+	// 1) Call the base method
+	VolumeCollider::InitQuery();
+
+	// 2) Compute sphere in model space:
+	// - Precompute R^2
+	mRadius2 = sphere.mRadius * sphere.mRadius;
+	// - Compute center position
+	mCenter = sphere.mCenter;
+	// -> to world space
+	if(worlds)	mCenter *= *worlds;
+	// -> to model space
+	if(worldm)
+	{
+		// Invert model matrix
+		Matrix4x4 InvWorldM;
+		InvertPRMatrix(InvWorldM, *worldm);
+
+		mCenter *= InvWorldM;
+	}
+
+	// 3) Setup destination pointer
+	mTouchedPrimitives = &cache.TouchedPrimitives;
+
+	// 4) Special case: 1-triangle meshes [Opcode 1.3]
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		if(!SkipPrimitiveTests())
+		{
+			// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
+			mTouchedPrimitives->Reset();
+
+			// Perform overlap test between the unique triangle and the sphere (and set contact status if needed)
+			SPHERE_PRIM(udword(0), OPC_CONTACT)
+
+			// Return immediately regardless of status
+			return TRUE;
+		}
+	}
+
+	// 5) Check temporal coherence :
+	if(TemporalCoherenceEnabled())
+	{
+		// Here we use temporal coherence
+		// => check results from previous frame before performing the collision query
+		if(FirstContactEnabled())
+		{
+			// We're only interested in the first contact found => test the unique previously touched face
+			if(mTouchedPrimitives->GetNbEntries())
+			{
+				// Get index of previously touched face = the first entry in the array
+				udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
+
+				// Then reset the array:
+				// - if the overlap test below is successful, the index we'll get added back anyway
+				// - if it isn't, then the array should be reset anyway for the normal query
+				mTouchedPrimitives->Reset();
+
+				// Perform overlap test between the cached triangle and the sphere (and set contact status if needed)
+				SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
+
+				// Return immediately if possible
+				if(GetContactStatus())	return TRUE;
+			}
+			// else no face has been touched during previous query
+			// => we'll have to perform a normal query
+		}
+		else
+		{
+			// We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious):
+			float r = sqrtf(cache.FatRadius2) - sphere.mRadius;
+			if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r)
+			{
+				// - if N is included in P, return previous list
+				// => we simply leave the list (mTouchedFaces) unchanged
+
+				// Set contact status if needed
+				if(mTouchedPrimitives->GetNbEntries())	mFlags |= OPC_TEMPORAL_CONTACT;
+
+				// In any case we don't need to do a query
+				return TRUE;
+			}
+			else
+			{
+				// - else do the query using a fat N
+
+				// Reset cache since we'll about to perform a real query
+				mTouchedPrimitives->Reset();
+
+				// Make a fat sphere so that coherence will work for subsequent frames
+				mRadius2 *= cache.FatCoeff;
+//				mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff);
+
+				// Update cache with query data (signature for cached faces)
+				cache.Center = mCenter;
+				cache.FatRadius2 = mRadius2;
+			}
+		}
+	}
+	else
+	{
+		// Here we don't use temporal coherence => do a normal query
+		mTouchedPrimitives->Reset();
+	}
+
+	return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for vanilla AABB trees.
+ *	\param		cache		[in/out] a sphere cache
+ *	\param		sphere		[in] collision sphere in world space
+ *	\param		tree		[in] AABB tree
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree)
+{
+	// This is typically called for a scene tree, full of -AABBs-, not full of triangles.
+	// So we don't really have "primitives" to deal with. Hence it doesn't work with
+	// "FirstContact" + "TemporalCoherence".
+	ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
+
+	// Checkings
+	if(!tree)	return false;
+
+	// Init collision query
+	if(InitQuery(cache, sphere))	return true;
+
+	// Perform collision query
+	_Collide(tree);
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Checks the sphere completely contains the box. In which case we can end the query sooner.
+ *	\param		bc	[in] box center
+ *	\param		be	[in] box extents
+ *	\return		true if the sphere contains the whole box
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL SphereCollider::SphereContainsBox(const Point& bc, const Point& be)
+{
+	// I assume if all 8 box vertices are inside the sphere, so does the whole box.
+	// Sounds ok but maybe there's a better way?
+	Point p;
+	p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z;	if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x-be.x;									if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x+be.x; p.y=bc.y-be.y;					if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x-be.x;									if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z;	if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x-be.x;									if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x+be.x; p.y=bc.y-be.y;					if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+	p.x=bc.x-be.x;									if(mCenter.SquareDistance(p)>=mRadius2)	return FALSE;
+
+	return TRUE;
+}
+
+#define TEST_BOX_IN_SPHERE(center, extents)	\
+	if(SphereContainsBox(center, extents))	\
+	{										\
+		/* Set contact status */			\
+		mFlags |= OPC_CONTACT;				\
+		_Dump(node);						\
+		return;								\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_Collide(const AABBCollisionNode* node)
+{
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
+{
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_Collide(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_SPHERE(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_Collide(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_Collide(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_SPHERE(Center, Extents)
+
+	if(node->IsLeaf())
+	{
+		SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
+	}
+	else
+	{
+		_CollideNoPrimitiveTest(node->GetPos());
+
+		if(ContactFound()) return;
+
+		_CollideNoPrimitiveTest(node->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_Collide(const AABBNoLeafNode* node)
+{
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
+{
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))	return;
+
+	TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_SPHERE(Center, Extents)
+
+	if(node->HasPosLeaf())	{ SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_Collide(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
+{
+	// Dequantize box
+	const QuantizedAABB& Box = node->mAABB;
+	const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
+	const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
+
+	// Perform Sphere-AABB overlap test
+	if(!SphereAABBOverlap(Center, Extents))	return;
+
+	TEST_BOX_IN_SPHERE(Center, Extents)
+
+	if(node->HasPosLeaf())	{ SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetPos());
+
+	if(ContactFound()) return;
+
+	if(node->HasNegLeaf())	{ SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
+	else					_CollideNoPrimitiveTest(node->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for vanilla AABB trees.
+ *	\param		node	[in] current collision node
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SphereCollider::_Collide(const AABBTreeNode* node)
+{
+	// Perform Sphere-AABB overlap test
+	Point Center, Extents;
+	node->GetAABB()->GetCenter(Center);
+	node->GetAABB()->GetExtents(Extents);
+	if(!SphereAABBOverlap(Center, Extents))	return;
+
+	if(node->IsLeaf() || SphereContainsBox(Center, Extents))
+	{
+		mFlags |= OPC_CONTACT;
+		mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
+	}
+	else
+	{
+		_Collide(node->GetPos());
+		_Collide(node->GetNeg());
+	}
+}
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridSphereCollider::HybridSphereCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+HybridSphereCollider::~HybridSphereCollider()
+{
+}
+
+bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm)
+{
+	// We don't want primitive tests here!
+	mFlags |= OPC_NO_PRIMITIVE_TESTS;
+
+	// Checkings
+	if(!Setup(&model))	return false;
+
+	// Init collision query
+	if(InitQuery(cache, sphere, worlds, worldm))	return true;
+
+	// Special case for 1-leaf trees
+	if(mCurrentModel && mCurrentModel->HasSingleNode())
+	{
+		// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
+		udword Nb = mIMesh->GetNbTriangles();
+
+		// Loop through all triangles
+		for(udword i=0;i<Nb;i++)
+		{
+			SPHERE_PRIM(i, OPC_CONTACT)
+		}
+		return true;
+	}
+
+	// Override destination array since we're only going to get leaf boxes here
+	mTouchedBoxes.Reset();
+	mTouchedPrimitives = &mTouchedBoxes;
+
+	// Now, do the actual query against leaf boxes
+	if(!model.HasLeafNodes())
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+	else
+	{
+		if(model.IsQuantized())
+		{
+			const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
+
+			// Setup dequantization coeffs
+			mCenterCoeff	= Tree->mCenterCoeff;
+			mExtentsCoeff	= Tree->mExtentsCoeff;
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+		else
+		{
+			const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
+
+			// Perform collision query - we don't want primitive tests here!
+			_CollideNoPrimitiveTest(Tree->GetNodes());
+		}
+	}
+
+	// We only have a list of boxes so far
+	if(GetContactStatus())
+	{
+		// Reset contact status, since it currently only reflects collisions with leaf boxes
+		Collider::InitQuery();
+
+		// Change dest container so that we can use built-in overlap tests and get collided primitives
+		cache.TouchedPrimitives.Reset();
+		mTouchedPrimitives = &cache.TouchedPrimitives;
+
+		// Read touched leaf boxes
+		udword Nb = mTouchedBoxes.GetNbEntries();
+		const udword* Touched = mTouchedBoxes.GetEntries();
+
+		const LeafTriangles* LT = model.GetLeafTriangles();
+		const udword* Indices = model.GetIndices();
+
+		// Loop through touched leaves
+		while(Nb--)
+		{
+			const LeafTriangles& CurrentLeaf = LT[*Touched++];
+
+			// Each leaf box has a set of triangles
+			udword NbTris = CurrentLeaf.GetNbTriangles();
+			if(Indices)
+			{
+				const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = *T++;
+					SPHERE_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+			else
+			{
+				udword BaseIndex = CurrentLeaf.GetTriangleIndex();
+
+				// Loop through triangles and test each of them
+				while(NbTris--)
+				{
+					udword TriangleIndex = BaseIndex++;
+					SPHERE_PRIM(TriangleIndex, OPC_CONTACT)
+				}
+			}
+		}
+	}
+
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_SphereCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_SphereCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_SphereCollider.h	(revision 216)
@@ -0,0 +1,96 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a sphere collider.
+ *	\file		OPC_SphereCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_SPHERECOLLIDER_H__
+#define __OPC_SPHERECOLLIDER_H__
+
+	struct OPCODE_API SphereCache : VolumeCache
+	{
+					SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f)	{}
+					~SphereCache()																{}
+
+		// Cached faces signature
+		Point		Center;		//!< Sphere used when performing the query resulting in cached faces
+		float		FatRadius2;	//!< Sphere used when performing the query resulting in cached faces
+		// User settings
+		float		FatCoeff;	//!< mRadius2 multiplier used to create a fat sphere
+	};
+
+	class OPCODE_API SphereCollider : public VolumeCollider
+	{
+		public:
+		// Constructor / Destructor
+											SphereCollider();
+		virtual								~SphereCollider();
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic collision query for generic OPCODE models. After the call, access the results:
+		 *	- with GetContactStatus()
+		 *	- with GetNbTouchedPrimitives()
+		 *	- with GetTouchedPrimitives()
+		 *
+		 *	\param		cache			[in/out] a sphere cache
+		 *	\param		sphere			[in] collision sphere in local space
+		 *	\param		model			[in] Opcode model to collide with
+		 *	\param		worlds			[in] sphere's world matrix, or null
+		 *	\param		worldm			[in] model's world matrix, or null
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null);
+
+		// 
+							bool			Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree);
+		protected:
+		// Sphere in model space
+							Point			mCenter;			//!< Sphere center
+							float			mRadius2;			//!< Sphere radius squared
+		// Internal methods
+							void			_Collide(const AABBCollisionNode* node);
+							void			_Collide(const AABBNoLeafNode* node);
+							void			_Collide(const AABBQuantizedNode* node);
+							void			_Collide(const AABBQuantizedNoLeafNode* node);
+							void			_Collide(const AABBTreeNode* node);
+							void			_CollideNoPrimitiveTest(const AABBCollisionNode* node);
+							void			_CollideNoPrimitiveTest(const AABBNoLeafNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNode* node);
+							void			_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node);
+			// Overlap tests
+		inline_				BOOL			SphereContainsBox(const Point& bc, const Point& be);
+		inline_				BOOL			SphereAABBOverlap(const Point& center, const Point& extents);
+							BOOL			SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
+			// Init methods
+							BOOL			InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null);
+	};
+
+	class OPCODE_API HybridSphereCollider : public SphereCollider
+	{
+		public:
+		// Constructor / Destructor
+											HybridSphereCollider();
+		virtual								~HybridSphereCollider();
+
+							bool			Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null);
+		protected:
+							Container		mTouchedBoxes;
+	};
+
+#endif // __OPC_SPHERECOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_SphereTriOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_SphereTriOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_SphereTriOverlap.h	(revision 216)
@@ -0,0 +1,187 @@
+
+// This is collision detection. If you do another distance test for collision *response*,
+// if might be useful to simply *skip* the test below completely, and report a collision.
+// - if sphere-triangle overlap, result is ok
+// - if they don't, we'll discard them during collision response with a similar test anyway
+// Overall this approach should run faster.
+
+// Original code by David Eberly in Magic.
+BOOL SphereCollider::SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
+{
+	// Stats
+	mNbVolumePrimTests++;
+
+	// Early exit if one of the vertices is inside the sphere
+	Point kDiff = vert2 - mCenter;
+	float fC = kDiff.SquareMagnitude();
+	if(fC <= mRadius2)	return TRUE;
+
+	kDiff = vert1 - mCenter;
+	fC = kDiff.SquareMagnitude();
+	if(fC <= mRadius2)	return TRUE;
+
+	kDiff = vert0 - mCenter;
+	fC = kDiff.SquareMagnitude();
+	if(fC <= mRadius2)	return TRUE;
+
+	// Else do the full distance test
+	Point TriEdge0	= vert1 - vert0;
+	Point TriEdge1	= vert2 - vert0;
+
+//Point kDiff	= vert0 - mCenter;
+	float fA00	= TriEdge0.SquareMagnitude();
+	float fA01	= TriEdge0 | TriEdge1;
+	float fA11	= TriEdge1.SquareMagnitude();
+	float fB0	= kDiff | TriEdge0;
+	float fB1	= kDiff | TriEdge1;
+//float fC	= kDiff.SquareMagnitude();
+	float fDet	= fabsf(fA00*fA11 - fA01*fA01);
+	float u		= fA01*fB1-fA11*fB0;
+	float v		= fA01*fB0-fA00*fB1;
+	float SqrDist;
+
+	if(u + v <= fDet)
+	{
+		if(u < 0.0f)
+		{
+			if(v < 0.0f)  // region 4
+			{
+				if(fB0 < 0.0f)
+				{
+//					v = 0.0f;
+					if(-fB0>=fA00)			{ /*u = 1.0f;*/		SqrDist = fA00+2.0f*fB0+fC;	}
+					else					{ u = -fB0/fA00;	SqrDist = fB0*u+fC;			}
+				}
+				else
+				{
+//					u = 0.0f;
+					if(fB1>=0.0f)			{ /*v = 0.0f;*/		SqrDist = fC;				}
+					else if(-fB1>=fA11)		{ /*v = 1.0f;*/		SqrDist = fA11+2.0f*fB1+fC;	}
+					else					{ v = -fB1/fA11;	SqrDist = fB1*v+fC;			}
+				}
+			}
+			else  // region 3
+			{
+//				u = 0.0f;
+				if(fB1>=0.0f)				{ /*v = 0.0f;*/		SqrDist = fC;				}
+				else if(-fB1>=fA11)			{ /*v = 1.0f;*/		SqrDist = fA11+2.0f*fB1+fC;	}
+				else						{ v = -fB1/fA11;	SqrDist = fB1*v+fC;			}
+			}
+		}
+		else if(v < 0.0f)  // region 5
+		{
+//			v = 0.0f;
+			if(fB0>=0.0f)					{ /*u = 0.0f;*/		SqrDist = fC;				}
+			else if(-fB0>=fA00)				{ /*u = 1.0f;*/		SqrDist = fA00+2.0f*fB0+fC;	}
+			else							{ u = -fB0/fA00;	SqrDist = fB0*u+fC;			}
+		}
+		else  // region 0
+		{
+			// minimum at interior point
+			if(fDet==0.0f)
+			{
+//				u = 0.0f;
+//				v = 0.0f;
+				SqrDist = MAX_FLOAT;
+			}
+			else
+			{
+				float fInvDet = 1.0f/fDet;
+				u *= fInvDet;
+				v *= fInvDet;
+				SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
+			}
+		}
+	}
+	else
+	{
+		float fTmp0, fTmp1, fNumer, fDenom;
+
+		if(u < 0.0f)  // region 2
+		{
+			fTmp0 = fA01 + fB0;
+			fTmp1 = fA11 + fB1;
+			if(fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-2.0f*fA01+fA11;
+				if(fNumer >= fDenom)
+				{
+//					u = 1.0f;
+//					v = 0.0f;
+					SqrDist = fA00+2.0f*fB0+fC;
+				}
+				else
+				{
+					u = fNumer/fDenom;
+					v = 1.0f - u;
+					SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
+				}
+			}
+			else
+			{
+//				u = 0.0f;
+				if(fTmp1 <= 0.0f)		{ /*v = 1.0f;*/		SqrDist = fA11+2.0f*fB1+fC;	}
+				else if(fB1 >= 0.0f)	{ /*v = 0.0f;*/		SqrDist = fC;				}
+				else					{ v = -fB1/fA11;	SqrDist = fB1*v+fC;			}
+			}
+		}
+		else if(v < 0.0f)  // region 6
+		{
+			fTmp0 = fA01 + fB1;
+			fTmp1 = fA00 + fB0;
+			if(fTmp1 > fTmp0)
+			{
+				fNumer = fTmp1 - fTmp0;
+				fDenom = fA00-2.0f*fA01+fA11;
+				if(fNumer >= fDenom)
+				{
+//					v = 1.0f;
+//					u = 0.0f;
+					SqrDist = fA11+2.0f*fB1+fC;
+				}
+				else
+				{
+					v = fNumer/fDenom;
+					u = 1.0f - v;
+					SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
+				}
+			}
+			else
+			{
+//				v = 0.0f;
+				if(fTmp1 <= 0.0f)		{ /*u = 1.0f;*/		SqrDist = fA00+2.0f*fB0+fC;	}
+				else if(fB0 >= 0.0f)	{ /*u = 0.0f;*/		SqrDist = fC;				}
+				else					{ u = -fB0/fA00;	SqrDist = fB0*u+fC;			}
+			}
+		}
+		else  // region 1
+		{
+			fNumer = fA11 + fB1 - fA01 - fB0;
+			if(fNumer <= 0.0f)
+			{
+//				u = 0.0f;
+//				v = 1.0f;
+				SqrDist = fA11+2.0f*fB1+fC;
+			}
+			else
+			{
+				fDenom = fA00-2.0f*fA01+fA11;
+				if(fNumer >= fDenom)
+				{
+//					u = 1.0f;
+//					v = 0.0f;
+					SqrDist = fA00+2.0f*fB0+fC;
+				}
+				else
+				{
+					u = fNumer/fDenom;
+					v = 1.0f - u;
+					SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC;
+				}
+			}
+		}
+	}
+
+	return fabsf(SqrDist) < mRadius2;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_SweepAndPrune.cpp	(revision 216)
@@ -0,0 +1,664 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide)
+ *	\file		OPC_SweepAndPrune.cpp
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+inline_ void Sort(udword& id0, udword& id1)
+{
+	if(id0>id1)	Swap(id0, id1);
+}
+
+	class Opcode::SAP_Element
+	{
+		public:
+		inline_					SAP_Element()														{}
+		inline_					SAP_Element(udword id, SAP_Element* next) : mID(id), mNext(next)	{}
+		inline_					~SAP_Element()														{}
+
+				udword			mID;
+				SAP_Element*	mNext;
+	};
+
+	class Opcode::SAP_Box
+	{
+		public:
+				SAP_EndPoint*	Min[3];
+				SAP_EndPoint*	Max[3];
+	};
+
+	class Opcode::SAP_EndPoint
+	{
+		public:
+				float			Value;		// Min or Max value
+				SAP_EndPoint*	Previous;	// Previous EndPoint whose Value is smaller than ours (or null)
+				SAP_EndPoint*	Next;		// Next EndPoint whose Value is greater than ours (or null)
+				udword			Data;		// Parent box ID *2 | MinMax flag
+
+		inline_	void			SetData(udword box_id, BOOL is_max)			{ Data = (box_id<<1)|is_max;	}
+		inline_	BOOL			IsMax()								const	{ return Data & 1;				}
+		inline_	udword			GetBoxID()							const	{ return Data>>1;				}
+
+		inline_	void InsertAfter(SAP_EndPoint* element)
+		{
+			if(this!=element && this!=element->Next)
+			{
+				// Remove
+				if(Previous)	Previous->Next = Next;
+				if(Next)		Next->Previous = Previous;
+
+				// Insert
+				Next = element->Next;
+				if(Next)	Next->Previous = this;
+
+				element->Next = this;
+				Previous = element;
+			}
+		}
+
+		inline_	void InsertBefore(SAP_EndPoint* element)
+		{
+			if(this!=element && this!=element->Previous)
+			{
+				// Remove
+				if(Previous)	Previous->Next = Next;
+				if(Next)		Next->Previous = Previous;
+
+				// Insert
+				Previous = element->Previous;
+				element->Previous = this;
+
+				Next = element;
+				if(Previous)	Previous->Next = this;
+			}
+		}
+	};
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SAP_PairData::SAP_PairData() :
+	mNbElements		(0),
+	mNbUsedElements	(0),
+	mElementPool	(null),
+	mFirstFree		(null),
+	mNbObjects		(0),
+	mArray			(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SAP_PairData::~SAP_PairData()
+{
+	Release();
+}
+
+void SAP_PairData::Release()
+{
+	mNbElements		= 0;
+	mNbUsedElements	= 0;
+	mNbObjects		= 0;
+	DELETEARRAY(mElementPool);
+	DELETEARRAY(mArray);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes.
+ *	\param		nb_objects	[in] 
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool SAP_PairData::Init(udword nb_objects)
+{
+	// Make sure everything has been released
+	Release();
+	if(!nb_objects)	return false;
+
+	mArray = new SAP_Element*[nb_objects];
+	CHECKALLOC(mArray);
+	ZeroMemory(mArray, nb_objects*sizeof(SAP_Element*));
+	mNbObjects = nb_objects;
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Remaps a pointer when pool gets resized.
+ *	\param		element	[in/out] remapped element
+ *	\param		delta	[in] offset in bytes
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ void Remap(SAP_Element*& element, size_t delta)
+{
+	if(element)	element = (SAP_Element*)(size_t(element) + delta);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Gets a free element in the pool.
+ *	\param		id		[in] element id
+ *	\param		next	[in] next element
+ *	\param		remap	[out] possible remapping offset
+ *	\return		the new element
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SAP_Element* SAP_PairData::GetFreeElem(udword id, SAP_Element* next, udword* remap)
+{
+	if(remap)	*remap = 0;
+
+	SAP_Element* FreeElem;
+	if(mFirstFree)
+	{
+		// Recycle
+		FreeElem = mFirstFree;
+		mFirstFree = mFirstFree->mNext;	// First free = next free (or null)
+	}
+	else
+	{
+		if(mNbUsedElements==mNbElements)
+		{
+			// Resize
+			mNbElements = mNbElements ? (mNbElements<<1) : 2;
+
+			SAP_Element* NewElems = new SAP_Element[mNbElements];
+
+			if(mNbUsedElements)	CopyMemory(NewElems, mElementPool, mNbUsedElements*sizeof(SAP_Element));
+
+			// Remap everything
+			{
+				size_t Delta = size_t(NewElems) - size_t(mElementPool);
+
+				for(udword i=0;i<mNbUsedElements;i++)	Remap(NewElems[i].mNext, Delta);
+				for(udword i=0;i<mNbObjects;i++)		Remap(mArray[i], Delta);
+
+				Remap(mFirstFree, Delta);
+				Remap(next, Delta);
+
+				if(remap)	*remap = Delta;
+			}
+
+			DELETEARRAY(mElementPool);
+			mElementPool = NewElems;
+		}
+
+		FreeElem = &mElementPool[mNbUsedElements++];
+	}
+
+	FreeElem->mID = id;
+	FreeElem->mNext = next;
+
+	return FreeElem;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Frees an element of the pool.
+ *	\param		elem	[in] element to free/recycle
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ void SAP_PairData::FreeElem(SAP_Element* elem)
+{
+	elem->mNext = mFirstFree;	// Next free
+	mFirstFree = elem;
+}
+
+// Add a pair to the set.
+void SAP_PairData::AddPair(udword id1, udword id2)
+{
+	// Order the ids
+	Sort(id1, id2);
+
+	ASSERT(id1<mNbObjects);
+	if(id1>=mNbObjects)	return;
+
+	// Select the right list from "mArray".
+	SAP_Element* Current = mArray[id1];
+
+	if(!Current)
+	{
+		// Empty slot => create new element
+		mArray[id1] = GetFreeElem(id2, null);
+	}
+	else if(Current->mID>id2)
+	{
+		// The list is not empty but all elements are greater than id2 => insert id2 in the front.
+		mArray[id1]	= GetFreeElem(id2, mArray[id1]);
+	}
+	else
+	{
+		// Else find the correct location in the sorted list (ascending order) and insert id2 there.
+		while(Current->mNext)
+		{
+			if(Current->mNext->mID > id2)	break;
+
+			Current = Current->mNext;
+		}
+
+		if(Current->mID==id2)	return;	// The pair already exists
+		
+//		Current->mNext = GetFreeElem(id2, Current->mNext);
+		udword Delta;
+		SAP_Element* E = GetFreeElem(id2, Current->mNext, &Delta);
+		if(Delta)	Remap(Current, Delta);
+		Current->mNext = E;
+	}
+}
+
+// Delete a pair from the set.
+void SAP_PairData::RemovePair(udword id1, udword id2)
+{
+	// Order the ids.
+	Sort(id1, id2);
+
+	// Exit if the pair doesn't exist in the set
+	if(id1>=mNbObjects)	return;
+
+	// Otherwise, select the correct list.
+	SAP_Element* Current = mArray[id1];
+
+	// If this list is empty, the pair doesn't exist.
+	if(!Current) return;
+
+	// Otherwise, if id2 is the first element, delete it.
+	if(Current->mID==id2)
+	{
+		mArray[id1] = Current->mNext;
+		FreeElem(Current);
+	}
+	else
+	{
+		// If id2 is not the first element, start traversing the sorted list.
+		while(Current->mNext)
+		{
+			// If we have moved too far away without hitting id2, then the pair doesn't exist
+			if(Current->mNext->mID > id2)	return;
+
+			// Otherwise, delete id2.
+			if(Current->mNext->mID == id2)
+			{
+				SAP_Element* Temp = Current->mNext;
+				Current->mNext = Temp->mNext;
+				FreeElem(Temp);
+				return;
+			}
+			Current = Current->mNext;
+		}
+	}
+}
+
+void SAP_PairData::DumpPairs(Pairs& pairs) const
+{
+	// ### Ugly and slow
+	for(udword i=0;i<mNbObjects;i++)
+	{
+		SAP_Element* Current = mArray[i];
+		while(Current)
+		{
+			ASSERT(Current->mID<mNbObjects);
+
+			pairs.AddPair(i, Current->mID);
+			Current = Current->mNext;
+		}
+	}
+}
+
+void SAP_PairData::DumpPairs(PairCallback callback, void* user_data) const
+{
+	if(!callback)	return;
+
+	// ### Ugly and slow
+	for(udword i=0;i<mNbObjects;i++)
+	{
+		SAP_Element* Current = mArray[i];
+		while(Current)
+		{
+			ASSERT(Current->mID<mNbObjects);
+
+			if(!(callback)(i, Current->mID, user_data))	return;
+			Current = Current->mNext;
+		}
+	}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SweepAndPrune::SweepAndPrune()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+SweepAndPrune::~SweepAndPrune()
+{
+}
+
+void SweepAndPrune::GetPairs(Pairs& pairs) const
+{
+	mPairs.DumpPairs(pairs);
+}
+
+void SweepAndPrune::GetPairs(PairCallback callback, void* user_data) const
+{
+	mPairs.DumpPairs(callback, user_data);
+}
+
+bool SweepAndPrune::Init(udword nb_objects, const AABB** boxes)
+{
+	// 1) Create sorted lists
+	mNbObjects = nb_objects;
+
+	mBoxes = new SAP_Box[nb_objects];
+//	for(udword i=0;i<nb_objects;i++)	mBoxes[i].Box = *boxes[i];
+
+	float* Data = new float[nb_objects*2];
+
+	for(udword Axis=0;Axis<3;Axis++)
+	{
+		mList[Axis] = new SAP_EndPoint[nb_objects*2];
+
+		for(udword i=0;i<nb_objects;i++)
+		{
+			Data[i*2+0] = boxes[i]->GetMin(Axis);
+			Data[i*2+1] = boxes[i]->GetMax(Axis);
+		}
+		RadixSort RS;
+		const udword* Sorted = RS.Sort(Data, nb_objects*2).GetRanks();
+
+		SAP_EndPoint* PreviousEndPoint = null;
+
+		for(udword i=0;i<nb_objects*2;i++)
+		{
+			udword SortedIndex	= *Sorted++;
+			float SortedCoord	= Data[SortedIndex];
+			udword BoxIndex		= SortedIndex>>1;
+
+			ASSERT(BoxIndex<nb_objects);
+
+			SAP_EndPoint* CurrentEndPoint = &mList[Axis][SortedIndex];
+			CurrentEndPoint->Value		= SortedCoord;
+//			CurrentEndPoint->IsMax		= SortedIndex&1;		// ### could be implicit ?
+//			CurrentEndPoint->ID			= BoxIndex;				// ### could be implicit ?
+			CurrentEndPoint->SetData(BoxIndex, SortedIndex&1);	// ### could be implicit ?
+			CurrentEndPoint->Previous	= PreviousEndPoint;
+			CurrentEndPoint->Next		= null;
+			if(PreviousEndPoint)	PreviousEndPoint->Next = CurrentEndPoint;
+
+			if(CurrentEndPoint->IsMax())	mBoxes[BoxIndex].Max[Axis] = CurrentEndPoint;
+			else							mBoxes[BoxIndex].Min[Axis] = CurrentEndPoint;
+
+			PreviousEndPoint = CurrentEndPoint;
+		}
+	}
+
+	DELETEARRAY(Data);
+
+	CheckListsIntegrity();
+
+	// 2) Quickly find starting pairs
+
+	mPairs.Init(nb_objects);
+
+	{
+		Pairs P;
+		CompleteBoxPruning(nb_objects, boxes, P, Axes(AXES_XZY));
+		for(udword i=0;i<P.GetNbPairs();i++)
+		{
+			const Pair* PP = P.GetPair(i);
+
+			udword id0 = PP->id0;
+			udword id1 = PP->id1;
+
+			if(id0!=id1 && boxes[id0]->Intersect(*boxes[id1]))
+			{
+				mPairs.AddPair(id0, id1);
+			}
+			else ASSERT(0);
+		}
+	}
+
+	return true;
+}
+
+bool SweepAndPrune::CheckListsIntegrity()
+{
+	for(udword Axis=0;Axis<3;Axis++)
+	{
+		// Find list head
+		SAP_EndPoint* Current = mList[Axis];
+		while(Current->Previous)	Current = Current->Previous;
+
+		udword Nb = 0;
+
+		SAP_EndPoint* Previous = null;
+		while(Current)
+		{
+			Nb++;
+
+			if(Previous)
+			{
+				ASSERT(Previous->Value <= Current->Value);
+				if(Previous->Value > Current->Value)	return false;
+			}
+
+			ASSERT(Current->Previous==Previous);
+			if(Current->Previous!=Previous)	return false;
+
+			Previous = Current;
+			Current = Current->Next;
+		}
+
+		ASSERT(Nb==mNbObjects*2);
+	}
+	return true;
+}
+
+inline_ BOOL Intersect(const AABB& a, const SAP_Box& b)
+{
+	if(b.Max[0]->Value < a.GetMin(0) || a.GetMax(0) < b.Min[0]->Value
+	|| b.Max[1]->Value < a.GetMin(1) || a.GetMax(1) < b.Min[1]->Value
+	|| b.Max[2]->Value < a.GetMin(2) || a.GetMax(2) < b.Min[2]->Value)	return FALSE;
+
+	return TRUE;
+}
+
+
+
+bool SweepAndPrune::UpdateObject(udword i, const AABB& box)
+{
+	for(udword Axis=0;Axis<3;Axis++)
+	{
+//		udword Base = (udword)&mList[Axis][0];
+
+		// Update min
+		{
+			SAP_EndPoint* const CurrentMin = mBoxes[i].Min[Axis];
+			ASSERT(!CurrentMin->IsMax());
+
+			const float Limit = box.GetMin(Axis);
+			if(Limit == CurrentMin->Value)
+			{
+			}
+			else if(Limit < CurrentMin->Value)
+			{
+				CurrentMin->Value = Limit;
+
+				// Min is moving left:
+				SAP_EndPoint* NewPos = CurrentMin;
+				ASSERT(NewPos);
+
+				SAP_EndPoint* tmp;
+				while((tmp = NewPos->Previous) && tmp->Value > Limit)
+				{
+					NewPos = tmp;
+
+					if(NewPos->IsMax())
+					{
+						// Our min passed a max => start overlap
+						//udword SortedIndex = (udword(CurrentMin) - Base)/sizeof(NS_EndPoint);
+						const udword id0 = CurrentMin->GetBoxID();
+						const udword id1 = NewPos->GetBoxID();
+
+						if(id0!=id1 && Intersect(box, mBoxes[id1]))	mPairs.AddPair(id0, id1);
+					}
+				}
+
+				CurrentMin->InsertBefore(NewPos);
+			}
+			else// if(Limit > CurrentMin->Value)
+			{
+				CurrentMin->Value = Limit;
+
+				// Min is moving right:
+				SAP_EndPoint* NewPos = CurrentMin;
+				ASSERT(NewPos);
+
+				SAP_EndPoint* tmp;
+				while((tmp = NewPos->Next) && tmp->Value < Limit)
+				{
+					NewPos = tmp;
+
+					if(NewPos->IsMax())
+					{
+						// Our min passed a max => stop overlap
+						const udword id0 = CurrentMin->GetBoxID();
+						const udword id1 = NewPos->GetBoxID();
+
+						if(id0!=id1)	mPairs.RemovePair(id0, id1);
+					}
+				}
+
+				CurrentMin->InsertAfter(NewPos);
+			}
+		}
+
+		// Update max
+		{
+			SAP_EndPoint* const CurrentMax = mBoxes[i].Max[Axis];
+			ASSERT(CurrentMax->IsMax());
+
+			const float Limit = box.GetMax(Axis);
+			if(Limit == CurrentMax->Value)
+			{
+			}
+			else if(Limit > CurrentMax->Value)
+			{
+				CurrentMax->Value = Limit;
+
+				// Max is moving right:
+				SAP_EndPoint* NewPos = CurrentMax;
+				ASSERT(NewPos);
+
+				SAP_EndPoint* tmp;
+				while((tmp = NewPos->Next) && tmp->Value < Limit)
+				{
+					NewPos = tmp;
+
+					if(!NewPos->IsMax())
+					{
+						// Our max passed a min => start overlap
+						const udword id0 = CurrentMax->GetBoxID();
+						const udword id1 = NewPos->GetBoxID();
+
+						if(id0!=id1 && Intersect(box, mBoxes[id1]))	mPairs.AddPair(id0, id1);
+					}
+				}
+
+				CurrentMax->InsertAfter(NewPos);
+			}
+			else// if(Limit < CurrentMax->Value)
+			{
+				CurrentMax->Value = Limit;
+
+				// Max is moving left:
+				SAP_EndPoint* NewPos = CurrentMax;
+				ASSERT(NewPos);
+
+				SAP_EndPoint* tmp;
+				while((tmp = NewPos->Previous) && tmp->Value > Limit)
+				{
+					NewPos = tmp;
+
+					if(!NewPos->IsMax())
+					{
+						// Our max passed a min => stop overlap
+						const udword id0 = CurrentMax->GetBoxID();
+						const udword id1 = NewPos->GetBoxID();
+
+						if(id0!=id1)	mPairs.RemovePair(id0, id1);
+					}
+				}
+
+				CurrentMax->InsertBefore(NewPos);
+			}
+		}
+	}
+
+	return true;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_SweepAndPrune.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_SweepAndPrune.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_SweepAndPrune.h	(revision 216)
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide)
+ *	\file		OPC_SweepAndPrune.h
+ *	\author		Pierre Terdiman
+ *	\date		January, 29, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_SWEEPANDPRUNE_H__
+#define __OPC_SWEEPANDPRUNE_H__
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/**
+	 *	User-callback, called by OPCODE for each colliding pairs.
+	 *	\param		id0			[in] id of colliding object
+	 *	\param		id1			[in] id of colliding object
+	 *	\param		user_data	[in] user-defined data
+	 *	\return		TRUE to continue enumeration
+	 */
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	typedef BOOL	(*PairCallback)	(udword id0, udword id1, void* user_data);
+
+	class SAP_Element;
+	class SAP_EndPoint;
+	class SAP_Box;
+
+	class OPCODE_API SAP_PairData
+	{
+		public:
+								SAP_PairData();
+								~SAP_PairData();
+
+				bool			Init(udword nb_objects);
+
+				void			AddPair(udword id1, udword id2);
+				void			RemovePair(udword id1, udword id2);
+
+				void			DumpPairs(Pairs& pairs)								const;
+				void			DumpPairs(PairCallback callback, void* user_data)	const;
+		private:
+				udword			mNbElements;		//!< Total number of elements in the pool
+				udword			mNbUsedElements;	//!< Number of used elements
+				SAP_Element*	mElementPool;		//!< Array of mNbElements elements
+				SAP_Element*	mFirstFree;			//!< First free element in the pool
+
+				udword			mNbObjects;			//!< Max number of objects we can handle
+				SAP_Element**	mArray;				//!< Pointers to pool
+		// Internal methods
+				SAP_Element*	GetFreeElem(udword id, SAP_Element* next, udword* remap=null);
+		inline_	void			FreeElem(SAP_Element* elem);
+				void			Release();
+	};
+
+	class OPCODE_API SweepAndPrune
+	{
+		public:
+								SweepAndPrune();
+								~SweepAndPrune();
+
+				bool			Init(udword nb_objects, const AABB** boxes);
+				bool			UpdateObject(udword i, const AABB& box);
+
+				void			GetPairs(Pairs& pairs)								const;
+				void			GetPairs(PairCallback callback, void* user_data)	const;
+		private:
+				SAP_PairData	mPairs;
+
+				udword			mNbObjects;
+				SAP_Box*		mBoxes;
+				SAP_EndPoint*	mList[3];
+		// Internal methods
+				bool			CheckListsIntegrity();
+	};
+
+#endif //__OPC_SWEEPANDPRUNE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_TreeBuilders.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_TreeBuilders.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_TreeBuilders.cpp	(revision 216)
@@ -0,0 +1,255 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for tree builders.
+ *	\file		OPC_TreeBuilders.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A builder for AABB-trees of vertices.
+ *
+ *	\class		AABBTreeOfVerticesBuilder
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A builder for AABB-trees of AABBs.
+ *
+ *	\class		AABBTreeOfAABBsBuilder
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A builder for AABB-trees of triangles.
+ *
+ *	\class		AABBTreeOfTrianglesBuilder
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the AABB of a set of primitives.
+ *	\param		primitives		[in] list of indices of primitives
+ *	\param		nb_prims		[in] number of indices
+ *	\param		global_box		[out] global AABB enclosing the set of input primitives
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const
+{
+	// Checkings
+	if(!primitives || !nb_prims)	return false;
+
+	// Initialize global box
+	global_box = mAABBArray[primitives[0]];
+
+	// Loop through boxes
+	for(udword i=1;i<nb_prims;i++)
+	{
+		// Update global box
+		global_box.Add(mAABBArray[primitives[i]]);
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the splitting value along a given axis for a given primitive.
+ *	\param		index		[in] index of the primitive to split
+ *	\param		axis		[in] axis index (0,1,2)
+ *	\return		splitting value
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float AABBTreeOfAABBsBuilder::GetSplittingValue(udword index, udword axis) const
+{
+	// For an AABB, the splitting value is the middle of the given axis,
+	// i.e. the corresponding component of the center point
+	return mAABBArray[index].GetCenter(axis);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the AABB of a set of primitives.
+ *	\param		primitives		[in] list of indices of primitives
+ *	\param		nb_prims		[in] number of indices
+ *	\param		global_box		[out] global AABB enclosing the set of input primitives
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeOfTrianglesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const
+{
+	// Checkings
+	if(!primitives || !nb_prims)	return false;
+
+	// Initialize global box
+	Point Min(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
+	Point Max(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);
+
+	// Loop through triangles
+	VertexPointers VP;
+	while(nb_prims--)
+	{
+		// Get current triangle-vertices
+		mIMesh->GetTriangle(VP, *primitives++);
+		// Update global box
+		Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]);
+		Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]);
+	}
+	global_box.SetMinMax(Min, Max);
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the splitting value along a given axis for a given primitive.
+ *	\param		index		[in] index of the primitive to split
+ *	\param		axis		[in] axis index (0,1,2)
+ *	\return		splitting value
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const
+{
+/*	// Compute center of triangle
+	Point Center;
+	mTriList[index].Center(mVerts, Center);
+	// Return value
+	return Center[axis];*/
+
+	// Compute correct component from center of triangle
+//	return	(mVerts[mTriList[index].mVRef[0]][axis]
+//			+mVerts[mTriList[index].mVRef[1]][axis]
+//			+mVerts[mTriList[index].mVRef[2]][axis])*INV3;
+
+	VertexPointers VP;
+	mIMesh->GetTriangle(VP, index);
+
+	// Compute correct component from center of triangle
+	return	((*VP.Vertex[0])[axis]
+			+(*VP.Vertex[1])[axis]
+			+(*VP.Vertex[2])[axis])*INV3;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the splitting value along a given axis for a given node.
+ *	\param		primitives		[in] list of indices of primitives
+ *	\param		nb_prims		[in] number of indices
+ *	\param		global_box		[in] global AABB enclosing the set of input primitives
+ *	\param		axis			[in] axis index (0,1,2)
+ *	\return		splitting value
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float AABBTreeOfTrianglesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis)	const
+{
+	if(mSettings.mRules&SPLIT_GEOM_CENTER)
+	{
+		// Loop through triangles
+		float SplitValue = 0.0f;
+		VertexPointers VP;
+		for(udword i=0;i<nb_prims;i++)
+		{
+			// Get current triangle-vertices
+			mIMesh->GetTriangle(VP, primitives[i]);
+			// Update split value
+			SplitValue += (*VP.Vertex[0])[axis];
+			SplitValue += (*VP.Vertex[1])[axis];
+			SplitValue += (*VP.Vertex[2])[axis];
+		}
+		return SplitValue / float(nb_prims*3);
+	}
+	else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the AABB of a set of primitives.
+ *	\param		primitives		[in] list of indices of primitives
+ *	\param		nb_prims		[in] number of indices
+ *	\param		global_box		[out] global AABB enclosing the set of input primitives
+ *	\return		true if success
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const
+{
+	// Checkings
+	if(!primitives || !nb_prims)	return false;
+
+	// Initialize global box
+	global_box.SetEmpty();
+
+	// Loop through vertices
+	for(udword i=0;i<nb_prims;i++)
+	{
+		// Update global box
+		global_box.Extend(mVertexArray[primitives[i]]);
+	}
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the splitting value along a given axis for a given primitive.
+ *	\param		index		[in] index of the primitive to split
+ *	\param		axis		[in] axis index (0,1,2)
+ *	\return		splitting value
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float AABBTreeOfVerticesBuilder::GetSplittingValue(udword index, udword axis) const
+{
+	// For a vertex, the splitting value is simply the vertex coordinate.
+	return mVertexArray[index][axis];
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Computes the splitting value along a given axis for a given node.
+ *	\param		primitives		[in] list of indices of primitives
+ *	\param		nb_prims		[in] number of indices
+ *	\param		global_box		[in] global AABB enclosing the set of input primitives
+ *	\param		axis			[in] axis index (0,1,2)
+ *	\return		splitting value
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float AABBTreeOfVerticesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis)	const
+{
+	if(mSettings.mRules&SPLIT_GEOM_CENTER)
+	{
+		// Loop through vertices
+		float SplitValue = 0.0f;
+		for(udword i=0;i<nb_prims;i++)
+		{
+			// Update split value
+			SplitValue += mVertexArray[primitives[i]][axis];
+		}
+		return SplitValue / float(nb_prims);
+	}
+	else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis);
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_TreeBuilders.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_TreeBuilders.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_TreeBuilders.h	(revision 216)
@@ -0,0 +1,173 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for tree builders.
+ *	\file		OPC_TreeBuilders.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_TREEBUILDERS_H__
+#define __OPC_TREEBUILDERS_H__
+
+	//! Tree splitting rules
+	enum SplittingRules
+	{
+		// Primitive split
+		SPLIT_LARGEST_AXIS		= (1<<0),		//!< Split along the largest axis
+		SPLIT_SPLATTER_POINTS	= (1<<1),		//!< Splatter primitive centers (QuickCD-style)
+		SPLIT_BEST_AXIS			= (1<<2),		//!< Try largest axis, then second, then last
+		SPLIT_BALANCED			= (1<<3),		//!< Try to keep a well-balanced tree
+		SPLIT_FIFTY				= (1<<4),		//!< Arbitrary 50-50 split
+		// Node split
+		SPLIT_GEOM_CENTER		= (1<<5),		//!< Split at geometric center (else split in the middle)
+		//
+		SPLIT_FORCE_DWORD		= 0x7fffffff
+	};
+
+	//! Simple wrapper around build-related settings [Opcode 1.3]
+	struct OPCODE_API BuildSettings
+	{
+		inline_	BuildSettings() : mLimit(1), mRules(SPLIT_FORCE_DWORD)	{}
+
+		udword	mLimit;		//!< Limit number of primitives / node. If limit is 1, build a complete tree (2*N-1 nodes)
+		udword	mRules;		//!< Building/Splitting rules (a combination of SplittingRules flags)
+	};
+
+	class OPCODE_API AABBTreeBuilder
+	{
+		public:
+		//! Constructor
+													AABBTreeBuilder() :
+														mNbPrimitives(0),
+														mNodeBase(null),
+														mCount(0),
+														mNbInvalidSplits(0)		{}
+		//! Destructor
+		virtual										~AABBTreeBuilder()			{}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the AABB of a set of primitives.
+		 *	\param		primitives		[in] list of indices of primitives
+		 *	\param		nb_prims		[in] number of indices
+		 *	\param		global_box		[out] global AABB enclosing the set of input primitives
+		 *	\return		true if success
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual						bool			ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box)	const	= 0;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the splitting value along a given axis for a given primitive.
+		 *	\param		index			[in] index of the primitive to split
+		 *	\param		axis			[in] axis index (0,1,2)
+		 *	\return		splitting value
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual						float			GetSplittingValue(udword index, udword axis)	const	= 0;
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Computes the splitting value along a given axis for a given node.
+		 *	\param		primitives		[in] list of indices of primitives
+		 *	\param		nb_prims		[in] number of indices
+		 *	\param		global_box		[in] global AABB enclosing the set of input primitives
+		 *	\param		axis			[in] axis index (0,1,2)
+		 *	\return		splitting value
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual						float			GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis)	const
+													{
+														// Default split value = middle of the axis (using only the box)
+														return global_box.GetCenter(axis);
+													}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates node subdivision. This is called each time a node is considered for subdivision, during tree building.
+		 *	\param		primitives		[in] list of indices of primitives
+		 *	\param		nb_prims		[in] number of indices
+		 *	\param		global_box		[in] global AABB enclosing the set of input primitives
+		 *	\return		TRUE if the node should be subdivised
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		virtual						BOOL			ValidateSubdivision(const udword* primitives, udword nb_prims, const AABB& global_box)
+													{
+														// Check the user-defined limit
+														if(nb_prims<=mSettings.mLimit)	return FALSE;
+
+														return TRUE;
+													}
+
+									BuildSettings	mSettings;			//!< Splitting rules & split limit [Opcode 1.3]
+									udword			mNbPrimitives;		//!< Total number of primitives.
+									void*			mNodeBase;			//!< Address of node pool [Opcode 1.3]
+		// Stats
+		inline_						void			SetCount(udword nb)				{ mCount=nb;				}
+		inline_						void			IncreaseCount(udword nb)		{ mCount+=nb;				}
+		inline_						udword			GetCount()				const	{ return mCount;			}
+		inline_						void			SetNbInvalidSplits(udword nb)	{ mNbInvalidSplits=nb;		}
+		inline_						void			IncreaseNbInvalidSplits()		{ mNbInvalidSplits++;		}
+		inline_						udword			GetNbInvalidSplits()	const	{ return mNbInvalidSplits;	}
+
+		private:
+									udword			mCount;				//!< Stats: number of nodes created
+									udword			mNbInvalidSplits;	//!< Stats: number of invalid splits
+	};
+
+	class OPCODE_API AABBTreeOfVerticesBuilder : public AABBTreeBuilder
+	{
+		public:
+		//! Constructor
+													AABBTreeOfVerticesBuilder() : mVertexArray(null)	{}
+		//! Destructor
+		virtual										~AABBTreeOfVerticesBuilder()						{}
+
+		override(AABBTreeBuilder)	bool			ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box)	const;
+		override(AABBTreeBuilder)	float			GetSplittingValue(udword index, udword axis)									const;
+		override(AABBTreeBuilder)	float			GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis)	const;
+
+		const						Point*			mVertexArray;		//!< Shortcut to an app-controlled array of vertices.
+	};
+
+	class OPCODE_API AABBTreeOfAABBsBuilder : public AABBTreeBuilder
+	{
+		public:
+		//! Constructor
+													AABBTreeOfAABBsBuilder() : mAABBArray(null)	{}
+		//! Destructor
+		virtual										~AABBTreeOfAABBsBuilder()					{}
+
+		override(AABBTreeBuilder)	bool			ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box)	const;
+		override(AABBTreeBuilder)	float			GetSplittingValue(udword index, udword axis)									const;
+
+		const						AABB*			mAABBArray;			//!< Shortcut to an app-controlled array of AABBs.
+	};
+
+	class OPCODE_API AABBTreeOfTrianglesBuilder : public AABBTreeBuilder
+	{
+		public:
+		//! Constructor
+													AABBTreeOfTrianglesBuilder() : mIMesh(null)										{}
+		//! Destructor
+		virtual										~AABBTreeOfTrianglesBuilder()													{}
+
+		override(AABBTreeBuilder)	bool			ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box)	const;
+		override(AABBTreeBuilder)	float			GetSplittingValue(udword index, udword axis)									const;
+		override(AABBTreeBuilder)	float			GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis)	const;
+
+		const				MeshInterface*			mIMesh;			//!< Shortcut to an app-controlled mesh interface
+	};
+
+#endif // __OPC_TREEBUILDERS_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_TreeCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_TreeCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_TreeCollider.cpp	(revision 216)
@@ -0,0 +1,943 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a tree collider.
+ *	\file		OPC_TreeCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains an AABB tree collider.
+ *	This class performs a collision test between two AABB trees.
+ *
+ *	\class		AABBTreeCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		March, 20, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+#include "OPC_BoxBoxOverlap.h"
+#include "OPC_TriBoxOverlap.h"
+#include "OPC_TriTriOverlap.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBTreeCollider::AABBTreeCollider() :
+	mNbBVBVTests		(0),
+	mNbPrimPrimTests	(0),
+	mNbBVPrimTests		(0),
+	mFullBoxBoxTest		(true),
+	mFullPrimBoxTest	(true),
+	mIMesh0				(null),
+	mIMesh1				(null)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+AABBTreeCollider::~AABBTreeCollider()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Validates current settings. You should call this method after all the settings and callbacks have been defined.
+ *	\return		null if everything is ok, else a string describing the problem
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const char* AABBTreeCollider::ValidateSettings()
+{
+	if(TemporalCoherenceEnabled() && !FirstContactEnabled())	return "Temporal coherence only works with ""First contact"" mode!";
+	return null;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Generic collision query for generic OPCODE models. After the call, access the results with:
+ *	- GetContactStatus()
+ *	- GetNbPairs()
+ *	- GetPairs()
+ *
+ *	\param		cache			[in] collision cache for model pointers and a colliding pair of primitives
+ *	\param		world0			[in] world matrix for first object
+ *	\param		world1			[in] world matrix for second object
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeCollider::Collide(BVTCache& cache, const Matrix4x4* world0, const Matrix4x4* world1)
+{
+	// Checkings
+	if(!cache.Model0 || !cache.Model1)								return false;
+	if(cache.Model0->HasLeafNodes()!=cache.Model1->HasLeafNodes())	return false;
+	if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized())	return false;
+
+	/*
+	
+	  Rules:
+		- perform hull test
+		- when hulls collide, disable hull test
+		- if meshes overlap, reset countdown
+		- if countdown reaches 0, enable hull test
+
+	*/
+
+#ifdef __MESHMERIZER_H__
+	// Handle hulls
+	if(cache.HullTest)
+	{
+		if(cache.Model0->GetHull() && cache.Model1->GetHull())
+		{
+			struct Local
+			{
+				static Point* SVCallback(const Point& sv, udword& previndex, udword user_data)
+				{
+					CollisionHull* Hull = (CollisionHull*)user_data;
+					previndex = Hull->ComputeSupportingVertex(sv, previndex);
+					return (Point*)&Hull->GetVerts()[previndex];
+				}
+			};
+
+			bool Collide;
+
+			if(0)
+			{
+				static GJKEngine GJK;
+				static bool GJKInitDone=false;
+				if(!GJKInitDone)
+				{
+					GJK.Enable(GJK_BACKUP_PROCEDURE);
+					GJK.Enable(GJK_DEGENERATE);
+					GJK.Enable(GJK_HILLCLIMBING);
+					GJKInitDone = true;
+				}
+				GJK.SetCallbackObj0(Local::SVCallback);
+				GJK.SetCallbackObj1(Local::SVCallback);
+				GJK.SetUserData0(udword(cache.Model0->GetHull()));
+				GJK.SetUserData1(udword(cache.Model1->GetHull()));
+				Collide = GJK.Collide(*world0, *world1, &cache.SepVector);
+			}
+			else
+			{
+				static SVEngine SVE;
+				SVE.SetCallbackObj0(Local::SVCallback);
+				SVE.SetCallbackObj1(Local::SVCallback);
+				SVE.SetUserData0(udword(cache.Model0->GetHull()));
+				SVE.SetUserData1(udword(cache.Model1->GetHull()));
+				Collide = SVE.Collide(*world0, *world1, &cache.SepVector);
+			}
+
+			if(!Collide)
+			{
+		// Reset stats & contact status
+		mFlags &= ~OPC_CONTACT;
+		mNbBVBVTests		= 0;
+		mNbPrimPrimTests	= 0;
+		mNbBVPrimTests		= 0;
+		mPairs.Reset();
+		return true;
+			}
+		}
+	}
+
+	// Here, hulls collide
+	cache.HullTest = false;
+#endif // __MESHMERIZER_H__
+
+	// Checkings
+	if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface()))	return false;
+
+	// Simple double-dispatch
+	bool Status;
+	if(!cache.Model0->HasLeafNodes())
+	{
+		if(cache.Model0->IsQuantized())
+		{
+			const AABBQuantizedNoLeafTree* T0 = (const AABBQuantizedNoLeafTree*)cache.Model0->GetTree();
+			const AABBQuantizedNoLeafTree* T1 = (const AABBQuantizedNoLeafTree*)cache.Model1->GetTree();
+			Status = Collide(T0, T1, world0, world1, &cache);
+		}
+		else
+		{
+			const AABBNoLeafTree* T0 = (const AABBNoLeafTree*)cache.Model0->GetTree();
+			const AABBNoLeafTree* T1 = (const AABBNoLeafTree*)cache.Model1->GetTree();
+			Status = Collide(T0, T1, world0, world1, &cache);
+		}
+	}
+	else
+	{
+		if(cache.Model0->IsQuantized())
+		{
+			const AABBQuantizedTree* T0 = (const AABBQuantizedTree*)cache.Model0->GetTree();
+			const AABBQuantizedTree* T1 = (const AABBQuantizedTree*)cache.Model1->GetTree();
+			Status = Collide(T0, T1, world0, world1, &cache);
+		}
+		else
+		{
+			const AABBCollisionTree* T0 = (const AABBCollisionTree*)cache.Model0->GetTree();
+			const AABBCollisionTree* T1 = (const AABBCollisionTree*)cache.Model1->GetTree();
+			Status = Collide(T0, T1, world0, world1, &cache);
+		}
+	}
+
+#ifdef __MESHMERIZER_H__
+	if(Status)
+	{
+		// Reset counter as long as overlap occurs
+		if(GetContactStatus())	cache.ResetCountDown();
+
+		// Enable hull test again when counter reaches zero
+		cache.CountDown--;
+		if(!cache.CountDown)
+		{
+			cache.ResetCountDown();
+			cache.HullTest = true;
+		}
+	}
+#endif
+	return Status;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Initializes a collision query :
+ *	- reset stats & contact status
+ *	- setup matrices
+ *
+ *	\param		world0			[in] world matrix for first object
+ *	\param		world1			[in] world matrix for second object
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1)
+{
+	// Reset stats & contact status
+	Collider::InitQuery();
+	mNbBVBVTests		= 0;
+	mNbPrimPrimTests	= 0;
+	mNbBVPrimTests		= 0;
+	mPairs.Reset();
+
+	// Setup matrices
+	Matrix4x4 InvWorld0, InvWorld1;
+	if(world0)	InvertPRMatrix(InvWorld0, *world0);
+	else		InvWorld0.Identity();
+
+	if(world1)	InvertPRMatrix(InvWorld1, *world1);
+	else		InvWorld1.Identity();
+
+	Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1;
+	Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0;
+
+	mR0to1 = World0to1;		World0to1.GetTrans(mT0to1);
+	mR1to0 = World1to0;		World1to0.GetTrans(mT1to0);
+
+	// Precompute absolute 1-to-0 rotation matrix
+	for(udword i=0;i<3;i++)
+	{
+		for(udword j=0;j<3;j++)
+		{
+			// Epsilon value prevents floating-point inaccuracies (strategy borrowed from RAPID)
+			mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]);
+		}
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Takes advantage of temporal coherence.
+ *	\param		cache	[in] cache for a pair of previously colliding primitives
+ *	\return		true if we can return immediately
+ *	\warning	only works for "First Contact" mode
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache)
+{
+	// Checkings
+	if(!cache)	return false;
+
+	// Test previously colliding primitives first
+	if(TemporalCoherenceEnabled() && FirstContactEnabled())
+	{
+		PrimTest(cache->id0, cache->id1);
+		if(GetContactStatus())	return true;
+	}
+	return false;
+}
+
+#define UPDATE_CACHE						\
+	if(cache && GetContactStatus())			\
+	{										\
+		cache->id0 = mPairs.GetEntry(0);	\
+		cache->id1 = mPairs.GetEntry(1);	\
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for normal AABB trees.
+ *	\param		tree0			[in] AABB tree from first object
+ *	\param		tree1			[in] AABB tree from second object
+ *	\param		world0			[in] world matrix for first object
+ *	\param		world1			[in] world matrix for second object
+ *	\param		cache			[in/out] cache for a pair of previously colliding primitives
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
+{
+	// Init collision query
+	InitQuery(world0, world1);
+
+	// Check previous state
+	if(CheckTemporalCoherence(cache))		return true;
+
+	// Perform collision query
+	_Collide(tree0->GetNodes(), tree1->GetNodes());
+
+	UPDATE_CACHE
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for no-leaf AABB trees.
+ *	\param		tree0			[in] AABB tree from first object
+ *	\param		tree1			[in] AABB tree from second object
+ *	\param		world0			[in] world matrix for first object
+ *	\param		world1			[in] world matrix for second object
+ *	\param		cache			[in/out] cache for a pair of previously colliding primitives
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
+{
+	// Init collision query
+	InitQuery(world0, world1);
+
+	// Check previous state
+	if(CheckTemporalCoherence(cache))		return true;
+
+	// Perform collision query
+	_Collide(tree0->GetNodes(), tree1->GetNodes());
+
+	UPDATE_CACHE
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for quantized AABB trees.
+ *	\param		tree0			[in] AABB tree from first object
+ *	\param		tree1			[in] AABB tree from second object
+ *	\param		world0			[in] world matrix for first object
+ *	\param		world1			[in] world matrix for second object
+ *	\param		cache			[in/out] cache for a pair of previously colliding primitives
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
+{
+	// Init collision query
+	InitQuery(world0, world1);
+
+	// Check previous state
+	if(CheckTemporalCoherence(cache))		return true;
+
+	// Setup dequantization coeffs
+	mCenterCoeff0	= tree0->mCenterCoeff;
+	mExtentsCoeff0	= tree0->mExtentsCoeff;
+	mCenterCoeff1	= tree1->mCenterCoeff;
+	mExtentsCoeff1	= tree1->mExtentsCoeff;
+
+	// Dequantize box A
+	const AABBQuantizedNode* N0 = tree0->GetNodes();
+	const Point a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z);
+	const Point Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z);
+	// Dequantize box B
+	const AABBQuantizedNode* N1 = tree1->GetNodes();
+	const Point b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z);
+	const Point Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z);
+
+	// Perform collision query
+	_Collide(N0, N1, a, Pa, b, Pb);
+
+	UPDATE_CACHE
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Collision query for quantized no-leaf AABB trees.
+ *	\param		tree0			[in] AABB tree from first object
+ *	\param		tree1			[in] AABB tree from second object
+ *	\param		world0			[in] world matrix for first object
+ *	\param		world1			[in] world matrix for second object
+ *	\param		cache			[in/out] cache for a pair of previously colliding primitives
+ *	\return		true if success
+ *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache)
+{
+	// Init collision query
+	InitQuery(world0, world1);
+
+	// Check previous state
+	if(CheckTemporalCoherence(cache))		return true;
+
+	// Setup dequantization coeffs
+	mCenterCoeff0	= tree0->mCenterCoeff;
+	mExtentsCoeff0	= tree0->mExtentsCoeff;
+	mCenterCoeff1	= tree1->mCenterCoeff;
+	mExtentsCoeff1	= tree1->mExtentsCoeff;
+
+	// Perform collision query
+	_Collide(tree0->GetNodes(), tree1->GetNodes());
+
+	UPDATE_CACHE
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Standard trees
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// The normal AABB tree can use 2 different descent rules (with different performances)
+//#define ORIGINAL_CODE			//!< UNC-like descent rules
+#define ALTERNATIVE_CODE		//!< Alternative descent rules
+
+#ifdef ORIGINAL_CODE
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		b0		[in] collision node from first tree
+ *	\param		b1		[in] collision node from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1)
+{
+	// Perform BV-BV overlap test
+	if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter))	return;
+
+	if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; }
+
+	if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize())))
+	{
+		_Collide(b0->GetNeg(), b1);
+		if(ContactFound()) return;
+		_Collide(b0->GetPos(), b1);
+	}
+	else
+	{
+		_Collide(b0, b1->GetNeg());
+		if(ContactFound()) return;
+		_Collide(b0, b1->GetPos());
+	}
+}
+#endif
+
+#ifdef ALTERNATIVE_CODE
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for normal AABB trees.
+ *	\param		b0		[in] collision node from first tree
+ *	\param		b1		[in] collision node from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1)
+{
+	// Perform BV-BV overlap test
+	if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter))
+	{
+		return;
+	}
+
+	if(b0->IsLeaf())
+	{
+		if(b1->IsLeaf())
+		{
+			PrimTest(b0->GetPrimitive(), b1->GetPrimitive());
+		}
+		else
+		{
+			_Collide(b0, b1->GetNeg());
+			if(ContactFound()) return;
+			_Collide(b0, b1->GetPos());
+		}
+	}
+	else if(b1->IsLeaf())
+	{
+		_Collide(b0->GetNeg(), b1);
+		if(ContactFound()) return;
+		_Collide(b0->GetPos(), b1);
+	}
+	else
+	{
+		_Collide(b0->GetNeg(), b1->GetNeg());
+		if(ContactFound()) return;
+		_Collide(b0->GetNeg(), b1->GetPos());
+		if(ContactFound()) return;
+		_Collide(b0->GetPos(), b1->GetNeg());
+		if(ContactFound()) return;
+		_Collide(b0->GetPos(), b1->GetPos());
+	}
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// No-leaf trees
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Leaf-leaf test for two primitive indices.
+ *	\param		id0		[in] index from first leaf-triangle
+ *	\param		id1		[in] index from second leaf-triangle
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::PrimTest(udword id0, udword id1)
+{
+	// Request vertices from the app
+	VertexPointers VP0;
+	VertexPointers VP1;
+	mIMesh0->GetTriangle(VP0, id0);
+	mIMesh1->GetTriangle(VP1, id1);
+
+	// Transform from space 1 to space 0
+	Point u0,u1,u2;
+	TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0);
+	TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0);
+	TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0);
+
+	// Perform triangle-triangle overlap test
+	if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2))
+	{
+		// Keep track of colliding pairs
+		mPairs.Add(id0).Add(id1);
+		// Set contact status
+		mFlags |= OPC_CONTACT;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B.
+ *	\param		id1		[in] leaf-triangle index from tree B
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1)
+{
+	// Request vertices from the app
+	VertexPointers VP;
+	mIMesh1->GetTriangle(VP, id1);
+
+	// Perform triangle-triangle overlap test
+	if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
+	{
+		// Keep track of colliding pairs
+		mPairs.Add(mLeafIndex).Add(id1);
+		// Set contact status
+		mFlags |= OPC_CONTACT;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A.
+ *	\param		id0		[in] leaf-triangle index from tree A
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0)
+{
+	// Request vertices from the app
+	VertexPointers VP;
+	mIMesh0->GetTriangle(VP, id0);
+
+	// Perform triangle-triangle overlap test
+	if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))
+	{
+		// Keep track of colliding pairs
+		mPairs.Add(id0).Add(mLeafIndex);
+		// Set contact status
+		mFlags |= OPC_CONTACT;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision of a leaf node from A and a branch from B.
+ *	\param		b		[in] collision node from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b)
+{
+	// Perform triangle-box overlap test
+	if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents))	return;
+
+	// Keep same triangle, deal with first child
+	if(b->HasPosLeaf())	PrimTestTriIndex(b->GetPosPrimitive());
+	else				_CollideTriBox(b->GetPos());
+
+	if(ContactFound()) return;
+
+	// Keep same triangle, deal with second child
+	if(b->HasNegLeaf())	PrimTestTriIndex(b->GetNegPrimitive());
+	else				_CollideTriBox(b->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision of a leaf node from B and a branch from A.
+ *	\param		b		[in] collision node from first tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b)
+{
+	// Perform triangle-box overlap test
+	if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents))	return;
+
+	// Keep same triangle, deal with first child
+	if(b->HasPosLeaf())	PrimTestIndexTri(b->GetPosPrimitive());
+	else				_CollideBoxTri(b->GetPos());
+
+	if(ContactFound()) return;
+
+	// Keep same triangle, deal with second child
+	if(b->HasNegLeaf())	PrimTestIndexTri(b->GetNegPrimitive());
+	else				_CollideBoxTri(b->GetNeg());
+}
+
+//! Request triangle vertices from the app and transform them
+#define FETCH_LEAF(prim_index, imesh, rot, trans)				\
+	mLeafIndex = prim_index;									\
+	/* Request vertices from the app */							\
+	VertexPointers VP;	imesh->GetTriangle(VP, prim_index);		\
+	/* Transform them in a common space */						\
+	TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans);	\
+	TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans);	\
+	TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans);
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for no-leaf AABB trees.
+ *	\param		a	[in] collision node from first tree
+ *	\param		b	[in] collision node from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b)
+{
+	// Perform BV-BV overlap test
+	if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter))	return;
+
+	// Catch leaf status
+	BOOL BHasPosLeaf = b->HasPosLeaf();
+	BOOL BHasNegLeaf = b->HasNegLeaf();
+
+	if(a->HasPosLeaf())
+	{
+		FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1)
+
+		if(BHasPosLeaf)	PrimTestTriIndex(b->GetPosPrimitive());
+		else			_CollideTriBox(b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)	PrimTestTriIndex(b->GetNegPrimitive());
+		else			_CollideTriBox(b->GetNeg());
+	}
+	else
+	{
+		if(BHasPosLeaf)
+		{
+			FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetPos());
+		}
+		else _Collide(a->GetPos(), b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)
+		{
+			FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetPos());
+		}
+		else _Collide(a->GetPos(), b->GetNeg());
+	}
+
+	if(ContactFound()) return;
+
+	if(a->HasNegLeaf())
+	{
+		FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1)
+
+		if(BHasPosLeaf)	PrimTestTriIndex(b->GetPosPrimitive());
+		else			_CollideTriBox(b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)	PrimTestTriIndex(b->GetNegPrimitive());
+		else			_CollideTriBox(b->GetNeg());
+	}
+	else
+	{
+		if(BHasPosLeaf)
+		{
+			// ### That leaf has possibly already been fetched
+			FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetNeg());
+		}
+		else _Collide(a->GetNeg(), b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)
+		{
+			// ### That leaf has possibly already been fetched
+			FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetNeg());
+		}
+		else _Collide(a->GetNeg(), b->GetNeg());
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantized trees
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized AABB trees.
+ *	\param		b0		[in] collision node from first tree
+ *	\param		b1		[in] collision node from second tree
+ *	\param		a		[in] extent from box A
+ *	\param		Pa		[in] center from box A
+ *	\param		b		[in] extent from box B
+ *	\param		Pb		[in] center from box B
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb)
+{
+	// Perform BV-BV overlap test
+	if(!BoxBoxOverlap(a, Pa, b, Pb))	return;
+
+	if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; }
+
+	if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize())))
+	{
+		// Dequantize box
+		const QuantizedAABB* Box = &b0->GetNeg()->mAABB;
+		const Point negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z);
+		const Point nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z);
+		_Collide(b0->GetNeg(), b1, nega, negPa, b, Pb);
+
+		if(ContactFound()) return;
+
+		// Dequantize box
+		Box = &b0->GetPos()->mAABB;
+		const Point posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z);
+		const Point posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z);
+		_Collide(b0->GetPos(), b1, posa, posPa, b, Pb);
+	}
+	else
+	{
+		// Dequantize box
+		const QuantizedAABB* Box = &b1->GetNeg()->mAABB;
+		const Point negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z);
+		const Point negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z);
+		_Collide(b0, b1->GetNeg(), a, Pa, negb, negPb);
+
+		if(ContactFound()) return;
+
+		// Dequantize box
+		Box = &b1->GetPos()->mAABB;
+		const Point posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z);
+		const Point posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z);
+		_Collide(b0, b1->GetPos(), a, Pa, posb, posPb);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Quantized no-leaf trees
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision of a leaf node from A and a quantized branch from B.
+ *	\param		leaf	[in] leaf triangle from first tree
+ *	\param		b		[in] collision node from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b)
+{
+	// Dequantize box
+	const QuantizedAABB* bb = &b->mAABB;
+	const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z);
+	const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z);
+
+	// Perform triangle-box overlap test
+	if(!TriBoxOverlap(Pb, eb))	return;
+
+	if(b->HasPosLeaf())	PrimTestTriIndex(b->GetPosPrimitive());
+	else				_CollideTriBox(b->GetPos());
+
+	if(ContactFound()) return;
+
+	if(b->HasNegLeaf())	PrimTestTriIndex(b->GetNegPrimitive());
+	else				_CollideTriBox(b->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision of a leaf node from B and a quantized branch from A.
+ *	\param		b		[in] collision node from first tree
+ *	\param		leaf	[in] leaf triangle from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b)
+{
+	// Dequantize box
+	const QuantizedAABB* bb = &b->mAABB;
+	const Point Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z);
+	const Point ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z);
+
+	// Perform triangle-box overlap test
+	if(!TriBoxOverlap(Pa, ea))	return;
+
+	if(b->HasPosLeaf())	PrimTestIndexTri(b->GetPosPrimitive());
+	else				_CollideBoxTri(b->GetPos());
+
+	if(ContactFound()) return;
+
+	if(b->HasNegLeaf())	PrimTestIndexTri(b->GetNegPrimitive());
+	else				_CollideBoxTri(b->GetNeg());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Recursive collision query for quantized no-leaf AABB trees.
+ *	\param		a	[in] collision node from first tree
+ *	\param		b	[in] collision node from second tree
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b)
+{
+	// Dequantize box A
+	const QuantizedAABB* ab = &a->mAABB;
+	const Point Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z);
+	const Point ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z);
+	// Dequantize box B
+	const QuantizedAABB* bb = &b->mAABB;
+	const Point Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z);
+	const Point eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z);
+
+	// Perform BV-BV overlap test
+	if(!BoxBoxOverlap(ea, Pa, eb, Pb))	return;
+
+	// Catch leaf status
+	BOOL BHasPosLeaf = b->HasPosLeaf();
+	BOOL BHasNegLeaf = b->HasNegLeaf();
+
+	if(a->HasPosLeaf())
+	{
+		FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1)
+
+		if(BHasPosLeaf)	PrimTestTriIndex(b->GetPosPrimitive());
+		else			_CollideTriBox(b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)	PrimTestTriIndex(b->GetNegPrimitive());
+		else			_CollideTriBox(b->GetNeg());
+	}
+	else
+	{
+		if(BHasPosLeaf)
+		{
+			FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetPos());
+		}
+		else _Collide(a->GetPos(), b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)
+		{
+			FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetPos());
+		}
+		else _Collide(a->GetPos(), b->GetNeg());
+	}
+
+	if(ContactFound()) return;
+
+	if(a->HasNegLeaf())
+	{
+		FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1)
+
+		if(BHasPosLeaf)	PrimTestTriIndex(b->GetPosPrimitive());
+		else			_CollideTriBox(b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)	PrimTestTriIndex(b->GetNegPrimitive());
+		else			_CollideTriBox(b->GetNeg());
+	}
+	else
+	{
+		if(BHasPosLeaf)
+		{
+			// ### That leaf has possibly already been fetched
+			FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetNeg());
+		}
+		else _Collide(a->GetNeg(), b->GetPos());
+
+		if(ContactFound()) return;
+
+		if(BHasNegLeaf)
+		{
+			// ### That leaf has possibly already been fetched
+			FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0)
+
+			_CollideBoxTri(a->GetNeg());
+		}
+		else _Collide(a->GetNeg(), b->GetNeg());
+	}
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_TreeCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_TreeCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_TreeCollider.h	(revision 216)
@@ -0,0 +1,246 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains code for a tree collider.
+ *	\file		OPC_TreeCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_TREECOLLIDER_H__
+#define __OPC_TREECOLLIDER_H__
+
+	//! This structure holds cached information used by the algorithm.
+	//! Two model pointers and two colliding primitives are cached. Model pointers are assigned
+	//! to their respective meshes, and the pair of colliding primitives is used for temporal
+	//! coherence. That is, in case temporal coherence is enabled, those two primitives are
+	//! tested for overlap before everything else. If they still collide, we're done before
+	//! even entering the recursive collision code.
+	struct OPCODE_API BVTCache : Pair
+	{
+		//! Constructor
+		inline_				BVTCache()
+							{
+								ResetCache();
+								ResetCountDown();
+							}
+
+					void	ResetCache()
+							{
+								Model0			= null;
+								Model1			= null;
+								id0				= 0;
+								id1				= 1;
+#ifdef __MESHMERIZER_H__		// Collision hulls only supported within ICE !
+								HullTest		= true;
+								SepVector.pid	= 0;
+								SepVector.qid	= 0;
+								SepVector.SV	= Point(1.0f, 0.0f, 0.0f);
+#endif // __MESHMERIZER_H__
+							}
+
+#ifdef __MESHMERIZER_H__		// Collision hulls only supported within ICE !
+	  inline_ void ResetCountDown()
+	  {
+	    CountDown		= 50;
+	  }
+#else
+	  void	ResetCountDown(){};
+#endif // __MESHMERIZER_H__
+
+		const Model*		Model0;	//!< Model for first object
+		const Model*		Model1;	//!< Model for second object
+
+#ifdef __MESHMERIZER_H__	// Collision hulls only supported within ICE !
+		SVCache				SepVector;
+		udword				CountDown;
+		bool				HullTest;
+#endif // __MESHMERIZER_H__
+	};
+
+	class OPCODE_API AABBTreeCollider : public Collider
+	{
+		public:
+		// Constructor / Destructor
+											AABBTreeCollider();
+		virtual								~AABBTreeCollider();
+		// Generic collision query
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Generic collision query for generic OPCODE models. After the call, access the results with:
+		 *	- GetContactStatus()
+		 *	- GetNbPairs()
+		 *	- GetPairs()
+		 *
+		 *	\param		cache			[in] collision cache for model pointers and a colliding pair of primitives
+		 *	\param		world0			[in] world matrix for first object, or null
+		 *	\param		world1			[in] world matrix for second object, or null
+		 *	\return		true if success
+		 *	\warning	SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+							bool			Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null);
+
+		// Collision queries
+							bool			Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1,				const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
+							bool			Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1,					const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
+							bool			Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1,				const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
+							bool			Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1,	const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null);
+		// Settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded)
+		 *	\param		flag		[in] true for full tests, false for coarse tests
+		 *	\see		SetFullPrimBoxTest(bool flag)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetFullBoxBoxTest(bool flag)			{ mFullBoxBoxTest		= flag;					}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded)
+		 *	\param		flag		[in] true for full tests, false for coarse tests
+		 *	\see		SetFullBoxBoxTest(bool flag)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				void			SetFullPrimBoxTest(bool flag)			{ mFullPrimBoxTest		= flag;					}
+
+		// Stats
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of BV-BV overlap tests after a collision query.
+		 *	\see		GetNbPrimPrimTests()
+		 *	\see		GetNbBVPrimTests()
+		 *	\return		the number of BV-BV tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbBVBVTests()				const	{ return mNbBVBVTests;							}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of Triangle-Triangle overlap tests after a collision query.
+		 *	\see		GetNbBVBVTests()
+		 *	\see		GetNbBVPrimTests()
+		 *	\return		the number of Triangle-Triangle tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbPrimPrimTests()			const	{ return mNbPrimPrimTests;						}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of BV-Triangle overlap tests after a collision query.
+		 *	\see		GetNbBVBVTests()
+		 *	\see		GetNbPrimPrimTests()
+		 *	\return		the number of BV-Triangle tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbBVPrimTests()				const	{ return mNbBVPrimTests;						}
+
+		// Data access
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the number of contacts after a collision query.
+		 *	\see		GetContactStatus()
+		 *	\see		GetPairs()
+		 *	\return		the number of contacts / colliding pairs.
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbPairs()					const	{ return mPairs.GetNbEntries()>>1;				}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the pairs of colliding triangles after a collision query.
+		 *	\see		GetContactStatus()
+		 *	\see		GetNbPairs()
+		 *	\return		the list of colliding pairs (triangle indices)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				const Pair*		GetPairs()						const	{ return (const Pair*)mPairs.GetEntries();		}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
+		 *	\return		null if everything is ok, else a string describing the problem
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(Collider)	const char*		ValidateSettings();
+
+		protected:
+		// Colliding pairs
+							Container		mPairs;				//!< Pairs of colliding primitives
+		// User mesh interfaces
+					const	MeshInterface*	mIMesh0;			//!< User-defined mesh interface for object0
+					const	MeshInterface*	mIMesh1;			//!< User-defined mesh interface for object1
+		// Stats
+							udword			mNbBVBVTests;		//!< Number of BV-BV tests
+							udword			mNbPrimPrimTests;	//!< Number of Primitive-Primitive tests
+							udword			mNbBVPrimTests;		//!< Number of BV-Primitive tests
+		// Precomputed data
+							Matrix3x3		mAR;				//!< Absolute rotation matrix
+							Matrix3x3		mR0to1;				//!< Rotation from object0 to object1
+							Matrix3x3		mR1to0;				//!< Rotation from object1 to object0
+							Point			mT0to1;				//!< Translation from object0 to object1
+							Point			mT1to0;				//!< Translation from object1 to object0
+		// Dequantization coeffs
+							Point			mCenterCoeff0;
+							Point			mExtentsCoeff0;
+							Point			mCenterCoeff1;
+							Point			mExtentsCoeff1;
+		// Leaf description
+							Point			mLeafVerts[3];		//!< Triangle vertices
+							udword			mLeafIndex;			//!< Triangle index
+		// Settings
+							bool			mFullBoxBoxTest;	//!< Perform full BV-BV tests (true) or SAT-lite tests (false)
+							bool			mFullPrimBoxTest;	//!< Perform full Primitive-BV tests (true) or SAT-lite tests (false)
+		// Internal methods
+
+			// Standard AABB trees
+							void			_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1);
+			// Quantized AABB trees
+							void			_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const Point& a, const Point& Pa, const Point& b, const Point& Pb);
+			// No-leaf AABB trees
+							void			_CollideTriBox(const AABBNoLeafNode* b);
+							void			_CollideBoxTri(const AABBNoLeafNode* b);
+							void			_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b);
+			// Quantized no-leaf AABB trees
+							void			_CollideTriBox(const AABBQuantizedNoLeafNode* b);
+							void			_CollideBoxTri(const AABBQuantizedNoLeafNode* b);
+							void			_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b);
+			// Overlap tests
+							void			PrimTest(udword id0, udword id1);
+			inline_			void			PrimTestTriIndex(udword id1);
+			inline_			void			PrimTestIndexTri(udword id0);
+
+			inline_			BOOL			BoxBoxOverlap(const Point& ea, const Point& ca, const Point& eb, const Point& cb);
+			inline_			BOOL			TriBoxOverlap(const Point& center, const Point& extents);
+			inline_			BOOL			TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2);
+			// Init methods
+							void			InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null);
+							bool			CheckTemporalCoherence(Pair* cache);
+
+		inline_				BOOL			Setup(const MeshInterface* mi0, const MeshInterface* mi1)
+											{
+												mIMesh0	= mi0;
+												mIMesh1	= mi1;
+
+												if(!mIMesh0 || !mIMesh1)	return FALSE;
+
+												return TRUE;
+											}
+	};
+
+#endif // __OPC_TREECOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_TriBoxOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_TriBoxOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_TriBoxOverlap.h	(revision 216)
@@ -0,0 +1,339 @@
+
+//! This macro quickly finds the min & max values among 3 variables
+#define FINDMINMAX(x0, x1, x2, min, max)	\
+	min = max = x0;							\
+	if(x1<min) min=x1;						\
+	if(x1>max) max=x1;						\
+	if(x2<min) min=x2;						\
+	if(x2>max) max=x2;
+
+//! TO BE DOCUMENTED
+inline_ BOOL planeBoxOverlap(const Point& normal, const float d, const Point& maxbox)
+{
+	Point vmin, vmax;
+	for(udword q=0;q<=2;q++)
+	{
+		if(normal[q]>0.0f)	{ vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; }
+		else				{ vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; }
+	}
+	if((normal|vmin)+d>0.0f) return FALSE;
+	if((normal|vmax)+d>=0.0f) return TRUE;
+
+	return FALSE;
+}
+
+//! TO BE DOCUMENTED
+#define AXISTEST_X01(a, b, fa, fb)							\
+	min = a*v0.y - b*v0.z;									\
+	max = a*v2.y - b*v2.z;									\
+	if(min>max) {const float tmp=max; max=min; min=tmp;	}	\
+	rad = fa * extents.y + fb * extents.z;					\
+	if(min>rad || max<-rad) return FALSE;
+
+//! TO BE DOCUMENTED
+#define AXISTEST_X2(a, b, fa, fb)							\
+	min = a*v0.y - b*v0.z;									\
+	max = a*v1.y - b*v1.z;									\
+	if(min>max) {const float tmp=max; max=min; min=tmp;	}	\
+	rad = fa * extents.y + fb * extents.z;					\
+	if(min>rad || max<-rad) return FALSE;
+
+//! TO BE DOCUMENTED
+#define AXISTEST_Y02(a, b, fa, fb)							\
+	min = b*v0.z - a*v0.x;									\
+	max = b*v2.z - a*v2.x;									\
+	if(min>max) {const float tmp=max; max=min; min=tmp;	}	\
+	rad = fa * extents.x + fb * extents.z;					\
+	if(min>rad || max<-rad) return FALSE;
+
+//! TO BE DOCUMENTED
+#define AXISTEST_Y1(a, b, fa, fb)							\
+	min = b*v0.z - a*v0.x;									\
+	max = b*v1.z - a*v1.x;									\
+	if(min>max) {const float tmp=max; max=min; min=tmp;	}	\
+	rad = fa * extents.x + fb * extents.z;					\
+	if(min>rad || max<-rad) return FALSE;
+
+//! TO BE DOCUMENTED
+#define AXISTEST_Z12(a, b, fa, fb)							\
+	min = a*v1.x - b*v1.y;									\
+	max = a*v2.x - b*v2.y;									\
+	if(min>max) {const float tmp=max; max=min; min=tmp;	}	\
+	rad = fa * extents.x + fb * extents.y;					\
+	if(min>rad || max<-rad) return FALSE;
+
+//! TO BE DOCUMENTED
+#define AXISTEST_Z0(a, b, fa, fb)							\
+	min = a*v0.x - b*v0.y;									\
+	max = a*v1.x - b*v1.y;									\
+	if(min>max) {const float tmp=max; max=min; min=tmp;	}	\
+	rad = fa * extents.x + fb * extents.y;					\
+	if(min>rad || max<-rad) return FALSE;
+
+// compute triangle edges
+// - edges lazy evaluated to take advantage of early exits
+// - fabs precomputed (half less work, possible since extents are always >0)
+// - customized macros to take advantage of the null component
+// - axis vector discarded, possibly saves useless movs
+#define IMPLEMENT_CLASS3_TESTS						\
+	float rad;										\
+	float min, max;									\
+													\
+	const float fey0 = fabsf(e0.y);					\
+	const float fez0 = fabsf(e0.z);					\
+	AXISTEST_X01(e0.z, e0.y, fez0, fey0);			\
+	const float fex0 = fabsf(e0.x);					\
+	AXISTEST_Y02(e0.z, e0.x, fez0, fex0);			\
+	AXISTEST_Z12(e0.y, e0.x, fey0, fex0);			\
+													\
+	const float fey1 = fabsf(e1.y);					\
+	const float fez1 = fabsf(e1.z);					\
+	AXISTEST_X01(e1.z, e1.y, fez1, fey1);			\
+	const float fex1 = fabsf(e1.x);					\
+	AXISTEST_Y02(e1.z, e1.x, fez1, fex1);			\
+	AXISTEST_Z0(e1.y, e1.x, fey1, fex1);			\
+													\
+	const Point e2 = mLeafVerts[0] - mLeafVerts[2];	\
+	const float fey2 = fabsf(e2.y);					\
+	const float fez2 = fabsf(e2.z);					\
+	AXISTEST_X2(e2.z, e2.y, fez2, fey2);			\
+	const float fex2 = fabsf(e2.x);					\
+	AXISTEST_Y1(e2.z, e2.x, fez2, fex2);			\
+	AXISTEST_Z12(e2.y, e2.x, fey2, fex2);
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Triangle-Box overlap test using the separating axis theorem.
+ *	This is the code from Tomas Möller, a bit optimized:
+ *	- with some more lazy evaluation (faster path on PC)
+ *	- with a tiny bit of assembly
+ *	- with "SAT-lite" applied if needed
+ *	- and perhaps with some more minor modifs...
+ *
+ *	\param		center		[in] box center
+ *	\param		extents		[in] box extents
+ *	\return		true if triangle & box overlap
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL AABBTreeCollider::TriBoxOverlap(const Point& center, const Point& extents)
+{
+	// Stats
+	mNbBVPrimTests++;
+
+	// use separating axis theorem to test overlap between triangle and box 
+	// need to test for overlap in these directions: 
+	// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle 
+	//    we do not even need to test these) 
+	// 2) normal of the triangle 
+	// 3) crossproduct(edge from tri, {x,y,z}-directin) 
+	//    this gives 3x3=9 more tests 
+
+	// move everything so that the boxcenter is in (0,0,0) 
+	Point v0, v1, v2;
+	v0.x = mLeafVerts[0].x - center.x;
+	v1.x = mLeafVerts[1].x - center.x;
+	v2.x = mLeafVerts[2].x - center.x;
+
+	// First, test overlap in the {x,y,z}-directions
+#ifdef OPC_USE_FCOMI
+	// find min, max of the triangle in x-direction, and test for overlap in X
+	if(FCMin3(v0.x, v1.x, v2.x)>extents.x)	return FALSE;
+	if(FCMax3(v0.x, v1.x, v2.x)<-extents.x)	return FALSE;
+
+	// same for Y
+	v0.y = mLeafVerts[0].y - center.y;
+	v1.y = mLeafVerts[1].y - center.y;
+	v2.y = mLeafVerts[2].y - center.y;
+
+	if(FCMin3(v0.y, v1.y, v2.y)>extents.y)	return FALSE;
+	if(FCMax3(v0.y, v1.y, v2.y)<-extents.y)	return FALSE;
+
+	// same for Z
+	v0.z = mLeafVerts[0].z - center.z;
+	v1.z = mLeafVerts[1].z - center.z;
+	v2.z = mLeafVerts[2].z - center.z;
+
+	if(FCMin3(v0.z, v1.z, v2.z)>extents.z)	return FALSE;
+	if(FCMax3(v0.z, v1.z, v2.z)<-extents.z)	return FALSE;
+#else
+	float min,max;
+	// Find min, max of the triangle in x-direction, and test for overlap in X
+	FINDMINMAX(v0.x, v1.x, v2.x, min, max);
+	if(min>extents.x || max<-extents.x) return FALSE;
+
+	// Same for Y
+	v0.y = mLeafVerts[0].y - center.y;
+	v1.y = mLeafVerts[1].y - center.y;
+	v2.y = mLeafVerts[2].y - center.y;
+
+	FINDMINMAX(v0.y, v1.y, v2.y, min, max);
+	if(min>extents.y || max<-extents.y) return FALSE;
+
+	// Same for Z
+	v0.z = mLeafVerts[0].z - center.z;
+	v1.z = mLeafVerts[1].z - center.z;
+	v2.z = mLeafVerts[2].z - center.z;
+
+	FINDMINMAX(v0.z, v1.z, v2.z, min, max);
+	if(min>extents.z || max<-extents.z) return FALSE;
+#endif
+	// 2) Test if the box intersects the plane of the triangle
+	// compute plane equation of triangle: normal*x+d=0
+	// ### could be precomputed since we use the same leaf triangle several times
+	const Point e0 = v1 - v0;
+	const Point e1 = v2 - v1;
+	const Point normal = e0 ^ e1;
+	const float d = -normal|v0;
+	if(!planeBoxOverlap(normal, d, extents)) return FALSE;
+
+	// 3) "Class III" tests
+	if(mFullPrimBoxTest)
+	{
+		IMPLEMENT_CLASS3_TESTS
+	}
+	return TRUE;
+}
+
+//! A dedicated version where the box is constant
+inline_ BOOL OBBCollider::TriBoxOverlap()
+{
+	// Stats
+	mNbVolumePrimTests++;
+
+	// Hook
+	const Point& extents = mBoxExtents;
+	const Point& v0 = mLeafVerts[0];
+	const Point& v1 = mLeafVerts[1];
+	const Point& v2 = mLeafVerts[2];
+
+	// use separating axis theorem to test overlap between triangle and box 
+	// need to test for overlap in these directions: 
+	// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle 
+	//    we do not even need to test these) 
+	// 2) normal of the triangle 
+	// 3) crossproduct(edge from tri, {x,y,z}-directin) 
+	//    this gives 3x3=9 more tests 
+
+	// Box center is already in (0,0,0)
+
+	// First, test overlap in the {x,y,z}-directions
+#ifdef OPC_USE_FCOMI
+	// find min, max of the triangle in x-direction, and test for overlap in X
+	if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x)	return FALSE;
+	if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x)	return FALSE;
+
+	if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y)	return FALSE;
+	if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y)	return FALSE;
+
+	if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z)	return FALSE;
+	if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z)	return FALSE;
+#else
+	float min,max;
+	// Find min, max of the triangle in x-direction, and test for overlap in X
+	FINDMINMAX(v0.x, v1.x, v2.x, min, max);
+	if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE;
+
+	FINDMINMAX(v0.y, v1.y, v2.y, min, max);
+	if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE;
+
+	FINDMINMAX(v0.z, v1.z, v2.z, min, max);
+	if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE;
+#endif
+	// 2) Test if the box intersects the plane of the triangle
+	// compute plane equation of triangle: normal*x+d=0
+	// ### could be precomputed since we use the same leaf triangle several times
+	const Point e0 = v1 - v0;
+	const Point e1 = v2 - v1;
+	const Point normal = e0 ^ e1;
+	const float d = -normal|v0;
+	if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE;
+
+	// 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV)
+	{
+		IMPLEMENT_CLASS3_TESTS
+	}
+	return TRUE;
+}
+
+//! ...and another one, jeez
+inline_ BOOL AABBCollider::TriBoxOverlap()
+{
+	// Stats
+	mNbVolumePrimTests++;
+
+	// Hook
+	const Point& center		= mBox.mCenter;
+	const Point& extents	= mBox.mExtents;
+
+	// use separating axis theorem to test overlap between triangle and box 
+	// need to test for overlap in these directions: 
+	// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle 
+	//    we do not even need to test these) 
+	// 2) normal of the triangle 
+	// 3) crossproduct(edge from tri, {x,y,z}-directin) 
+	//    this gives 3x3=9 more tests 
+
+	// move everything so that the boxcenter is in (0,0,0) 
+	Point v0, v1, v2;
+	v0.x = mLeafVerts[0].x - center.x;
+	v1.x = mLeafVerts[1].x - center.x;
+	v2.x = mLeafVerts[2].x - center.x;
+
+	// First, test overlap in the {x,y,z}-directions
+#ifdef OPC_USE_FCOMI
+	// find min, max of the triangle in x-direction, and test for overlap in X
+	if(FCMin3(v0.x, v1.x, v2.x)>extents.x)	return FALSE;
+	if(FCMax3(v0.x, v1.x, v2.x)<-extents.x)	return FALSE;
+
+	// same for Y
+	v0.y = mLeafVerts[0].y - center.y;
+	v1.y = mLeafVerts[1].y - center.y;
+	v2.y = mLeafVerts[2].y - center.y;
+
+	if(FCMin3(v0.y, v1.y, v2.y)>extents.y)	return FALSE;
+	if(FCMax3(v0.y, v1.y, v2.y)<-extents.y)	return FALSE;
+
+	// same for Z
+	v0.z = mLeafVerts[0].z - center.z;
+	v1.z = mLeafVerts[1].z - center.z;
+	v2.z = mLeafVerts[2].z - center.z;
+
+	if(FCMin3(v0.z, v1.z, v2.z)>extents.z)	return FALSE;
+	if(FCMax3(v0.z, v1.z, v2.z)<-extents.z)	return FALSE;
+#else
+	float min,max;
+	// Find min, max of the triangle in x-direction, and test for overlap in X
+	FINDMINMAX(v0.x, v1.x, v2.x, min, max);
+	if(min>extents.x || max<-extents.x) return FALSE;
+
+	// Same for Y
+	v0.y = mLeafVerts[0].y - center.y;
+	v1.y = mLeafVerts[1].y - center.y;
+	v2.y = mLeafVerts[2].y - center.y;
+
+	FINDMINMAX(v0.y, v1.y, v2.y, min, max);
+	if(min>extents.y || max<-extents.y) return FALSE;
+
+	// Same for Z
+	v0.z = mLeafVerts[0].z - center.z;
+	v1.z = mLeafVerts[1].z - center.z;
+	v2.z = mLeafVerts[2].z - center.z;
+
+	FINDMINMAX(v0.z, v1.z, v2.z, min, max);
+	if(min>extents.z || max<-extents.z) return FALSE;
+#endif
+	// 2) Test if the box intersects the plane of the triangle
+	// compute plane equation of triangle: normal*x+d=0
+	// ### could be precomputed since we use the same leaf triangle several times
+	const Point e0 = v1 - v0;
+	const Point e1 = v2 - v1;
+	const Point normal = e0 ^ e1;
+	const float d = -normal|v0;
+	if(!planeBoxOverlap(normal, d, extents)) return FALSE;
+
+	// 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV)
+	{
+		IMPLEMENT_CLASS3_TESTS
+	}
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_TriTriOverlap.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_TriTriOverlap.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_TriTriOverlap.h	(revision 216)
@@ -0,0 +1,279 @@
+
+//! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|<EPSILON then dv=0.0;) else no check is done (which is less robust, but faster)
+#define LOCAL_EPSILON 0.000001f
+
+//! sort so that a<=b
+#define SORT(a,b)			\
+	if(a>b)					\
+	{						\
+		const float c=a;	\
+		a=b;				\
+		b=c;				\
+	}
+
+//! Edge to edge test based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202
+#define EDGE_EDGE_TEST(V0, U0, U1)						\
+	Bx = U0[i0] - U1[i0];								\
+	By = U0[i1] - U1[i1];								\
+	Cx = V0[i0] - U0[i0];								\
+	Cy = V0[i1] - U0[i1];								\
+	f  = Ay*Bx - Ax*By;									\
+	d  = By*Cx - Bx*Cy;									\
+	if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f))	\
+	{													\
+		const float e=Ax*Cy - Ay*Cx;					\
+		if(f>0.0f)										\
+		{												\
+			if(e>=0.0f && e<=f) return TRUE;			\
+		}												\
+		else											\
+		{												\
+			if(e<=0.0f && e>=f) return TRUE;			\
+		}												\
+	}
+
+//! TO BE DOCUMENTED
+#define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2)		\
+{														\
+	float Bx,By,Cx,Cy,d,f;								\
+	const float Ax = V1[i0] - V0[i0];					\
+	const float Ay = V1[i1] - V0[i1];					\
+	/* test edge U0,U1 against V0,V1 */					\
+	EDGE_EDGE_TEST(V0, U0, U1);							\
+	/* test edge U1,U2 against V0,V1 */					\
+	EDGE_EDGE_TEST(V0, U1, U2);							\
+	/* test edge U2,U1 against V0,V1 */					\
+	EDGE_EDGE_TEST(V0, U2, U0);							\
+}
+
+//! TO BE DOCUMENTED
+#define POINT_IN_TRI(V0, U0, U1, U2)					\
+{														\
+	/* is T1 completly inside T2? */					\
+	/* check if V0 is inside tri(U0,U1,U2) */			\
+	float a  = U1[i1] - U0[i1];							\
+	float b  = -(U1[i0] - U0[i0]);						\
+	float c  = -a*U0[i0] - b*U0[i1];					\
+	float d0 = a*V0[i0] + b*V0[i1] + c;					\
+														\
+	a  = U2[i1] - U1[i1];								\
+	b  = -(U2[i0] - U1[i0]);							\
+	c  = -a*U1[i0] - b*U1[i1];							\
+	const float d1 = a*V0[i0] + b*V0[i1] + c;			\
+														\
+	a  = U0[i1] - U2[i1];								\
+	b  = -(U0[i0] - U2[i0]);							\
+	c  = -a*U2[i0] - b*U2[i1];							\
+	const float d2 = a*V0[i0] + b*V0[i1] + c;			\
+	if(d0*d1>0.0f)										\
+	{													\
+		if(d0*d2>0.0f) return TRUE;						\
+	}													\
+}
+
+//! TO BE DOCUMENTED
+BOOL CoplanarTriTri(const Point& n, const Point& v0, const Point& v1, const Point& v2, const Point& u0, const Point& u1, const Point& u2)
+{
+	float A[3];
+	short i0,i1;
+	/* first project onto an axis-aligned plane, that maximizes the area */
+	/* of the triangles, compute indices: i0,i1. */
+	A[0] = fabsf(n[0]);
+	A[1] = fabsf(n[1]);
+	A[2] = fabsf(n[2]);
+	if(A[0]>A[1])
+	{
+		if(A[0]>A[2])
+		{
+			i0=1;      /* A[0] is greatest */
+			i1=2;
+		}
+		else
+		{
+			i0=0;      /* A[2] is greatest */
+			i1=1;
+		}
+	}
+	else   /* A[0]<=A[1] */
+	{
+		if(A[2]>A[1])
+		{
+			i0=0;      /* A[2] is greatest */
+			i1=1;
+		}
+		else
+		{
+			i0=0;      /* A[1] is greatest */
+			i1=2;
+		}
+	}
+
+	/* test all edges of triangle 1 against the edges of triangle 2 */
+	EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2);
+	EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2);
+	EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2);
+
+	/* finally, test if tri1 is totally contained in tri2 or vice versa */
+	POINT_IN_TRI(v0, u0, u1, u2);
+	POINT_IN_TRI(u0, v0, v1, v2);
+
+	return FALSE;
+}
+
+//! TO BE DOCUMENTED
+#define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1)	\
+{																						\
+	if(D0D1>0.0f)																		\
+	{																					\
+		/* here we know that D0D2<=0.0 */												\
+		/* that is D0, D1 are on the same side, D2 on the other or on the plane */		\
+		A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1;				\
+	}																					\
+	else if(D0D2>0.0f)																	\
+	{																					\
+		/* here we know that d0d1<=0.0 */												\
+		A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2;				\
+	}																					\
+	else if(D1*D2>0.0f || D0!=0.0f)														\
+	{																					\
+		/* here we know that d0d1<=0.0 or that D0!=0.0 */								\
+		A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2;				\
+	}																					\
+	else if(D1!=0.0f)																	\
+	{																					\
+		A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2;				\
+	}																					\
+	else if(D2!=0.0f)																	\
+	{																					\
+		A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1;				\
+	}																					\
+	else																				\
+	{																					\
+		/* triangles are coplanar */													\
+		return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2);								\
+	}																					\
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Triangle/triangle intersection test routine,
+ *	by Tomas Moller, 1997.
+ *	See article "A Fast Triangle-Triangle Intersection Test",
+ *	Journal of Graphics Tools, 2(2), 1997
+ *
+ *	Updated June 1999: removed the divisions -- a little faster now!
+ *	Updated October 1999: added {} to CROSS and SUB macros 
+ *
+ *	int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3],
+ *                      float U0[3],float U1[3],float U2[3])
+ *
+ *	\param		V0		[in] triangle 0, vertex 0
+ *	\param		V1		[in] triangle 0, vertex 1
+ *	\param		V2		[in] triangle 0, vertex 2
+ *	\param		U0		[in] triangle 1, vertex 0
+ *	\param		U1		[in] triangle 1, vertex 1
+ *	\param		U2		[in] triangle 1, vertex 2
+ *	\return		true if triangles overlap
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+inline_ BOOL AABBTreeCollider::TriTriOverlap(const Point& V0, const Point& V1, const Point& V2, const Point& U0, const Point& U1, const Point& U2)
+{
+	// Stats
+	mNbPrimPrimTests++;
+
+	// Compute plane equation of triangle(V0,V1,V2)
+	Point E1 = V1 - V0;
+	Point E2 = V2 - V0;
+	const Point N1 = E1 ^ E2;
+	const float d1 =-N1 | V0;
+	// Plane equation 1: N1.X+d1=0
+
+	// Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane
+	float du0 = (N1|U0) + d1;
+	float du1 = (N1|U1) + d1;
+	float du2 = (N1|U2) + d1;
+
+	// Coplanarity robustness check
+#ifdef OPC_TRITRI_EPSILON_TEST
+	if(fabsf(du0)<LOCAL_EPSILON) du0 = 0.0f;
+	if(fabsf(du1)<LOCAL_EPSILON) du1 = 0.0f;
+	if(fabsf(du2)<LOCAL_EPSILON) du2 = 0.0f;
+#endif
+	const float du0du1 = du0 * du1;
+	const float du0du2 = du0 * du2;
+
+	if(du0du1>0.0f && du0du2>0.0f)	// same sign on all of them + not equal 0 ?
+		return FALSE;				// no intersection occurs
+
+	// Compute plane of triangle (U0,U1,U2)
+	E1 = U1 - U0;
+	E2 = U2 - U0;
+	const Point N2 = E1 ^ E2;
+	const float d2=-N2 | U0;
+	// plane equation 2: N2.X+d2=0
+
+	// put V0,V1,V2 into plane equation 2
+	float dv0 = (N2|V0) + d2;
+	float dv1 = (N2|V1) + d2;
+	float dv2 = (N2|V2) + d2;
+
+#ifdef OPC_TRITRI_EPSILON_TEST
+	if(fabsf(dv0)<LOCAL_EPSILON) dv0 = 0.0f;
+	if(fabsf(dv1)<LOCAL_EPSILON) dv1 = 0.0f;
+	if(fabsf(dv2)<LOCAL_EPSILON) dv2 = 0.0f;
+#endif
+
+	const float dv0dv1 = dv0 * dv1;
+	const float dv0dv2 = dv0 * dv2;
+
+	if(dv0dv1>0.0f && dv0dv2>0.0f)	// same sign on all of them + not equal 0 ?
+		return FALSE;				// no intersection occurs
+
+	// Compute direction of intersection line
+	const Point D = N1^N2;
+
+	// Compute and index to the largest component of D
+	float max=fabsf(D[0]);
+	short index=0;
+	float bb=fabsf(D[1]);
+	float cc=fabsf(D[2]);
+	if(bb>max) max=bb,index=1;
+	if(cc>max) max=cc,index=2;
+
+	// This is the simplified projection onto L
+	const float vp0 = V0[index];
+	const float vp1 = V1[index];
+	const float vp2 = V2[index];
+
+	const float up0 = U0[index];
+	const float up1 = U1[index];
+	const float up2 = U2[index];
+
+	// Compute interval for triangle 1
+	float a,b,c,x0,x1;
+	NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);
+
+	// Compute interval for triangle 2
+	float d,e,f,y0,y1;
+	NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);
+
+	const float xx=x0*x1;
+	const float yy=y0*y1;
+	const float xxyy=xx*yy;
+
+	float isect1[2], isect2[2];
+
+	float tmp=a*xxyy;
+	isect1[0]=tmp+b*x1*yy;
+	isect1[1]=tmp+c*x0*yy;
+
+	tmp=d*xxyy;
+	isect2[0]=tmp+e*xx*y1;
+	isect2[1]=tmp+f*xx*y0;
+
+	SORT(isect1[0],isect1[1]);
+	SORT(isect2[0],isect2[1]);
+
+	if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return FALSE;
+	return TRUE;
+}
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_VolumeCollider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_VolumeCollider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_VolumeCollider.cpp	(revision 216)
@@ -0,0 +1,103 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains base volume collider class.
+ *	\file		OPC_VolumeCollider.cpp
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains the abstract class for volume colliders.
+ *
+ *	\class		VolumeCollider
+ *	\author		Pierre Terdiman
+ *	\version	1.3
+ *	\date		June, 2, 2001
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+using namespace Opcode;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Constructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+VolumeCollider::VolumeCollider() :
+	mTouchedPrimitives	(null),
+	mNbVolumeBVTests	(0),
+	mNbVolumePrimTests	(0)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Destructor.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+VolumeCollider::~VolumeCollider()
+{
+	mTouchedPrimitives = null;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
+ *	\return		null if everything is ok, else a string describing the problem
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const char* VolumeCollider::ValidateSettings()
+{
+	return null;
+}
+
+// Pretty dumb way to dump - to do better - one day...
+
+#define IMPLEMENT_NOLEAFDUMP(type)												\
+void VolumeCollider::_Dump(const type* node)									\
+{																				\
+	if(node->HasPosLeaf())	mTouchedPrimitives->Add(udword(node->GetPosPrimitive()));	\
+	else					_Dump(node->GetPos());								\
+																				\
+	if(ContactFound()) return;													\
+																				\
+	if(node->HasNegLeaf())	mTouchedPrimitives->Add(udword(node->GetNegPrimitive()));	\
+	else					_Dump(node->GetNeg());								\
+}
+
+#define IMPLEMENT_LEAFDUMP(type)						\
+void VolumeCollider::_Dump(const type* node)			\
+{														\
+	if(node->IsLeaf())									\
+	{													\
+		mTouchedPrimitives->Add(udword(node->GetPrimitive()));	\
+	}													\
+	else												\
+	{													\
+		_Dump(node->GetPos());							\
+														\
+		if(ContactFound()) return;						\
+														\
+		_Dump(node->GetNeg());							\
+	}													\
+}
+
+IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode)
+IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode)
+
+IMPLEMENT_LEAFDUMP(AABBCollisionNode)
+IMPLEMENT_LEAFDUMP(AABBQuantizedNode)
Index: /code/branches/ode/ode-0.9/OPCODE/OPC_VolumeCollider.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/OPC_VolumeCollider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/OPC_VolumeCollider.h	(revision 216)
@@ -0,0 +1,138 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Contains base volume collider class.
+ *	\file		OPC_VolumeCollider.h
+ *	\author		Pierre Terdiman
+ *	\date		June, 2, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPC_VOLUMECOLLIDER_H__
+#define __OPC_VOLUMECOLLIDER_H__
+
+	struct OPCODE_API VolumeCache
+	{
+							VolumeCache() : Model(null)		{}
+							~VolumeCache()					{}
+
+		Container			TouchedPrimitives;	//!< Indices of touched primitives
+		const BaseModel*	Model;				//!< Owner
+	};
+
+	class OPCODE_API VolumeCollider : public Collider
+	{
+		public:
+		// Constructor / Destructor
+											VolumeCollider();
+		virtual								~VolumeCollider() = 0;
+
+		// Collision report
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the number of touched primitives after a collision query.
+		 *	\see		GetContactStatus()
+		 *	\see		GetTouchedPrimitives()
+		 *	\return		the number of touched primitives
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbTouchedPrimitives()	const	{ return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0;	}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Gets the list of touched primitives after a collision query.
+		 *	\see		GetContactStatus()
+		 *	\see		GetNbTouchedPrimitives()
+		 *	\return		the list of touched primitives (primitive indices)
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_		const	udword*			GetTouchedPrimitives()		const	{ return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null;	}
+
+		// Stats
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of Volume-BV overlap tests after a collision query.
+		 *	\see		GetNbVolumePrimTests()
+		 *	\return		the number of Volume-BV tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbVolumeBVTests()		const	{ return mNbVolumeBVTests;												}
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Stats: gets the number of Volume-Triangle overlap tests after a collision query.
+		 *	\see		GetNbVolumeBVTests()
+		 *	\return		the number of Volume-Triangle tests performed during last query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		inline_				udword			GetNbVolumePrimTests()		const	{ return mNbVolumePrimTests;											}
+
+		// Settings
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
+		 *	\return		null if everything is ok, else a string describing the problem
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(Collider)	const char*		ValidateSettings();
+
+		protected:
+		// Touched primitives
+							Container*		mTouchedPrimitives;	//!< List of touched primitives
+
+		// Dequantization coeffs
+							Point			mCenterCoeff;
+							Point			mExtentsCoeff;
+		// Stats
+							udword			mNbVolumeBVTests;	//!< Number of Volume-BV tests
+							udword			mNbVolumePrimTests;	//!< Number of Volume-Primitive tests
+		// Internal methods
+							void			_Dump(const AABBCollisionNode* node);
+							void			_Dump(const AABBNoLeafNode* node);
+							void			_Dump(const AABBQuantizedNode* node);
+							void			_Dump(const AABBQuantizedNoLeafNode* node);
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		/**
+		 *	Initializes a query
+		 */
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		override(Collider) inline_	void	InitQuery()
+											{
+												// Reset stats & contact status
+												mNbVolumeBVTests	= 0;
+												mNbVolumePrimTests	= 0;
+												Collider::InitQuery();
+											}
+
+		inline_				BOOL			IsCacheValid(VolumeCache& cache)
+											{
+												// We're going to do a volume-vs-model query.
+												if(cache.Model!=mCurrentModel)
+												{
+													// Cached list was for another model so we can't keep it
+													// Keep track of new owner and reset cache
+													cache.Model = mCurrentModel;
+													return FALSE;
+												}
+												else
+												{
+													// Same models, no problem
+													return TRUE;
+												}
+											}
+	};
+
+#endif // __OPC_VOLUMECOLLIDER_H__
Index: /code/branches/ode/ode-0.9/OPCODE/Opcode.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Opcode.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Opcode.cpp	(revision 216)
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Main file for Opcode.dll.
+ *	\file		Opcode.cpp
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+	Finding a good name is difficult!
+	Here's the draft for this lib.... Spooky, uh?
+
+	VOID?			Very Optimized Interference Detection
+	ZOID?			Zappy's Optimized Interference Detection
+	CID?			Custom/Clever Interference Detection
+	AID / ACID!		Accurate Interference Detection
+	QUID?			Quick Interference Detection
+	RIDE?			Realtime Interference DEtection
+	WIDE?			Wicked Interference DEtection (....)
+	GUID!
+	KID !			k-dop interference detection :)
+	OPCODE!			OPtimized COllision DEtection
+*/
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "Stdafx.h"
+
+bool Opcode::InitOpcode()
+{
+	Log("// Initializing OPCODE\n\n");
+//	LogAPIInfo();
+	return true;
+}
+
+void ReleasePruningSorters();
+bool Opcode::CloseOpcode()
+{
+	Log("// Closing OPCODE\n\n");
+
+	ReleasePruningSorters();
+
+	return true;
+}
+
+#ifdef ICE_MAIN
+
+void ModuleAttach(HINSTANCE hinstance)
+{
+}
+
+void ModuleDetach()
+{
+}
+
+#endif
Index: /code/branches/ode/ode-0.9/OPCODE/Opcode.dsp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Opcode.dsp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Opcode.dsp	(revision 216)
@@ -0,0 +1,470 @@
+# Microsoft Developer Studio Project File - Name="OPCODE" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=OPCODE - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "Opcode.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Opcode.mak" CFG="OPCODE - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "OPCODE - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "OPCODE - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/TR4/ODE/VC6", WNKAAAAA"
+# PROP Scc_LocalPath "..\vc6"
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "OPCODE - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /Zp4 /MD /O2 /Ob0 /I ".\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "ICE_NO_DLL" /FD /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\OPCODE.lib"
+
+!ELSEIF  "$(CFG)" == "OPCODE - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /G6 /Zp4 /MDd /Gm /ZI /Od /I ".\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "ICE_NO_DLL" /FR /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\OPCODE_D.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "OPCODE - Win32 Release"
+# Name "OPCODE - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\Ice\IceAABB.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceAABB.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceAxes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceBoundingSphere.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceContainer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceContainer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceFPU.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceHPoint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceHPoint.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceIndexedTriangle.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceIndexedTriangle.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceLSS.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceMatrix3x3.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceMatrix3x3.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceMatrix4x4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceMatrix4x4.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceMemoryMacros.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceOBB.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceOBB.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IcePairs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IcePlane.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IcePlane.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IcePoint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IcePoint.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IcePreprocessor.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceRandom.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceRandom.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceRay.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceRay.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceRevisitedRadix.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceRevisitedRadix.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceSegment.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceSegment.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceTriangle.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceTriangle.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceTrilist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Ice\IceUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_AABBCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_AABBCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_AABBTree.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_AABBTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_BaseModel.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_BaseModel.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_BoxBoxOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_BoxPruning.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_BoxPruning.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Collider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Collider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Common.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Common.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_HybridModel.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_HybridModel.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_IceHook.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_LSSAABBOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_LSSCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_LSSCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_LSSTriOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_MeshInterface.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_MeshInterface.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Model.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Model.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_OBBCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_OBBCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_OptimizedTree.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_OptimizedTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Picking.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Picking.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_PlanesAABBOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_PlanesCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_PlanesCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_PlanesTriOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_RayAABBOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_RayCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_RayCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_RayTriOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_Settings.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_SphereAABBOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_SphereCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_SphereCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_SphereTriOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_SweepAndPrune.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_SweepAndPrune.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_TreeBuilders.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_TreeBuilders.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_TreeCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_TreeCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_TriBoxOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_TriTriOverlap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_VolumeCollider.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OPC_VolumeCollider.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Opcode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Opcode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Target
+# End Project
Index: /code/branches/ode/ode-0.9/OPCODE/Opcode.dsw
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Opcode.dsw	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Opcode.dsw	(revision 216)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "OPCODE"=.\Opcode.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
Index: /code/branches/ode/ode-0.9/OPCODE/Opcode.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Opcode.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Opcode.h	(revision 216)
@@ -0,0 +1,113 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	Main file for Opcode.dll.
+ *	\file		Opcode.h
+ *	\author		Pierre Terdiman
+ *	\date		March, 20, 2001
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Include Guard
+#ifndef __OPCODE_H__
+#define __OPCODE_H__
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Things to help us compile on non-windows platforms
+
+#if defined(__APPLE__) || defined(__MACOSX__)
+#if __APPLE_CC__ < 1495
+#define sqrtf sqrt
+#define sinf sin
+#define cosf cos
+#define acosf acos
+#define asinf asin
+#endif
+#endif
+
+#ifndef _MSC_VER
+#ifndef __int64
+#define __int64 long long int
+#endif
+#ifndef __stdcall /* this is defined in MinGW and CygWin, so avoid the warning */
+#define __stdcall /* */
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Compilation messages
+#ifdef _MSC_VER
+	#if defined(OPCODE_EXPORTS)
+		// #pragma message("Compiling OPCODE")
+	#elif !defined(OPCODE_EXPORTS)
+		// #pragma message("Using OPCODE")
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		// Automatic linking
+		#ifndef BAN_OPCODE_AUTOLINK
+			#ifdef _DEBUG
+				//#pragma comment(lib, "Opcode_D.lib")
+			#else
+				//#pragma comment(lib, "Opcode.lib")
+			#endif
+		#endif
+	#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Preprocessor
+#ifndef ICE_NO_DLL
+	#ifdef OPCODE_EXPORTS
+		#define OPCODE_API// __declspec(dllexport)
+	#else
+		#define OPCODE_API// __declspec(dllimport)
+	#endif
+#else
+		#define OPCODE_API
+#endif
+
+	#include "OPC_IceHook.h"
+
+	namespace Opcode
+	{
+		// Bulk-of-the-work
+		#include "OPC_Settings.h"
+		#include "OPC_Common.h"
+		#include "OPC_MeshInterface.h"
+		// Builders
+		#include "OPC_TreeBuilders.h"
+		// Trees
+		#include "OPC_AABBTree.h"
+		#include "OPC_OptimizedTree.h"
+		// Models
+		#include "OPC_BaseModel.h"
+		#include "OPC_Model.h"
+		#include "OPC_HybridModel.h"
+		// Colliders
+		#include "OPC_Collider.h"
+		#include "OPC_VolumeCollider.h"
+		#include "OPC_TreeCollider.h"
+		#include "OPC_RayCollider.h"
+		#include "OPC_SphereCollider.h"
+		#include "OPC_OBBCollider.h"
+		#include "OPC_AABBCollider.h"
+		#include "OPC_LSSCollider.h"
+		#include "OPC_PlanesCollider.h"
+		// Usages
+		#include "OPC_Picking.h"
+		// Sweep-and-prune
+		#include "OPC_BoxPruning.h"
+		#include "OPC_SweepAndPrune.h"
+
+		FUNCTION OPCODE_API bool InitOpcode();
+		FUNCTION OPCODE_API bool CloseOpcode();
+	}
+
+#endif // __OPCODE_H__
Index: /code/branches/ode/ode-0.9/OPCODE/README-ODE.txt
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/README-ODE.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/README-ODE.txt	(revision 216)
@@ -0,0 +1,13 @@
+
+This is a copy of the OPCODE collision detection library by Pierre Terdiman.
+See http://www.codercorner.com/Opcode.htm for more information, and read
+the ReadMe.txt in this directory.
+
+If you want to use the TriList (triangle mesh) geometry class in ODE, the
+OPCODE library must be compiled. If you are using the autotools support to 
+compile ODE, you just have to specify --with-trimesh=opcode when calling ./configure.
+
+This code was originally written for and compiled on windows, but it has been
+ported so that it should compile under unix/gcc too. Your mileage may vary.
+
+Russ Smith, April 12 2005.
Index: /code/branches/ode/ode-0.9/OPCODE/ReadMe.txt
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/ReadMe.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/ReadMe.txt	(revision 216)
@@ -0,0 +1,171 @@
+
+ OPCODE distribution 1.3 (june 2003)
+ -----------------------
+
+    New in Opcode 1.3:
+    - fixed the divide by 0 bug that was happening when all centers where located on a coordinate axis (thanks to Jorrit T)
+    - linearized "complete" vanilla AABB trees
+    - ANSI-compliant "for" loops (for the ones porting it to Linux...)
+    - callbacks & pointers moved to mesh interface
+    - support for triangle & vertex strides
+    - optimized the sphere-triangle overlap code a bit
+    - dynamic trees (refit)
+    - more builders
+    - ValidateSubdivision in builders
+    - LSS collider
+    - primitive-bv tests can now be skipped in most volume queries
+    - temporal coherence now also works for airborne objects
+    - temporal coherence completed for boxes / all contacts, LSS, etc
+    - ray-collider now uses a callback
+    - some common "usages" have been introduced (only picking for now)
+    - SPLIT_COMPLETE removed (now implicitely using mLimit = 1)
+    - hybrid collision models
+    - sweep-and-prune code added, moved from my old Z-Collide lib
+    - it now works with meshes made of only 1 triangle (except in mesh-mesh case!)
+
+    Disclaimer:
+
+    - I forced myself to actually *do* the release today no matter what. Else it would never have been done. That's
+      why the code may not be very polished. I also removed a *lot* of things (more usages, distance queries, etc...)
+      that weren't ready for prime-time (or that were linked to too many of my supporting libs)
+
+    - Some comments may also be obsolete here and there. The old User Manual for Opcode 1.2 may not fit version 1.3
+      either, since there's a new "mesh interface" to support strides, etc.
+
+    - Everything in the "Ice" directory has been hacked out of my engine and edited until everything compiled. Don't
+      expect anything out there to be cute or something. In particular, some CPP files are not even included when not
+      needed, so you can expect some linker errors if you try messing around with them...
+
+    Otherwise, it should be just like previous version, only better. In particular, hybrid models can be very
+    memory-friendly (sometimes using like 10 times less ram than the best trees from version 1.2). The possible
+    speed hit is often invisible (if it even exists), especially using temporal coherence in "all contacts" mode.
+    (Admittedly, this depends on your particular usage pattern / what you do on collided triangles).
+
+    The sweep-and-prune code is similar to the "vanilla" version found in V-Collide (but that one's better IMHO...)
+    The simple "radix" version is often just as good, see for yourself.
+
+ OPCODE distribution 1.2 (august 2002)
+ -----------------------
+
+    New in Opcode 1.2:
+    - new VolumeCollider base class
+    - simplified callback setup
+    - you can now use callbacks or pointers (setup at compile time)
+    - destination array not needed anymore in the RayCollider (faster in-out tests)
+    - renamed classes: AABBRayCollider => RayCollider, AABBSphereCollider => SphereCollider
+    - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster.
+    - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries.
+    - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen
+    - some inlining problems fixed
+    - faster ray-mesh tests using the separating axis theorem
+    - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time.
+    - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode)
+
+    Notes:
+
+    - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot
+      of code removed until there was no link error anymore. Don't expect those files to be cute or anything,
+      they've never been meant to be released and they're often updated/modified/messy.
+    - Some experimental features have been removed as well. Else I would never have released the 1.2...
+    - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it
+      before october 2002 (one YEAR later ?!).... That's the only reason why it's there.
+    - Some people reported ColDet was faster. Uh, come on. They were using Opcode in
+      "All contacts" mode whereas ColDet was doing "first contact"...
+
+ OPCODE distribution 1.1 (october 2001)
+ -----------------------
+
+    New in Opcode 1.1:
+    - stabbing queries
+    - sphere queries
+    - abtract base class for colliders
+    - settings validation methods
+    - compilation flags now grouped in OPC_Settings.h
+    - smaller files, new VC++ virtual dirs (cleaner)
+
+    Notes:
+
+    - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info.
+    - I code in 1600*1200, so some lines may look a bit long..
+    - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries
+      can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB
+      code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp
+    - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!)
+    - I removed various tests before releasing this one:
+        - a separation line, a.k.a. "front" in QuickCD, because gains were unclear
+        - distance queries in a PQP style, because it was way too slow
+        - support for deformable models, too slow as well
+    - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way.
+      If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current
+      demo uses copyrighted art I'm not allowed to spread)
+    - Sorry for the lack of real docs and/or solid examples. I just don't have enough time.
+
+ OPCODE distribution 1.0 (march 2001)
+ -----------------------
+
+    - First release
+
+ ===============================================================================
+
+ WHAT ?
+
+    OPCODE means OPtimized COllision DEtection.
+    So this is a collision detection package similar to RAPID. Here's a
+    quick list of features:
+
+    - C++ interface, developed for Windows systems using VC++ 6.0
+    - Works on arbitrary meshes (convex or non-convex), even polygon soups
+    - Current implementation uses AABB-trees
+    - Introduces Primitive-BV overlap tests during recursive collision queries (whereas
+      standard libraries only rely on Primitive-Primitive and BV-BV tests)
+    - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed
+    - Supports collision queries on quantized trees (decompressed on-the-fly)
+    - Supports "first contact" or "all contacts" modes (à la RAPID)
+    - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful
+      in rigid body simulation during bisection)
+    - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console
+      games with limited ram (actually, if you use the unmodified RAPID code using double
+      precision, it's more like 13 times smaller...)
+    - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5
+      times faster when objects are deeply overlapping)
+    - Performance is usually close to RAPID's one in close-proximity situations
+    - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS)
+    - Sweep-and-prune
+    - Now works with deformable meshes
+    - Hybrid trees
+
+
+    What it can be used for:
+    - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...)
+    - N-body collisions (similar to V-Collide)
+    - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles)
+    - shadow feelers to speed up lightmap computations
+    - in-out tests to speed up voxelization processes
+    - picking
+    - rigid body simulation
+    - view frustum culling
+    - etc
+
+ WHY ?
+
+    - Because RAPID uses too many bytes.
+    - Because the idea was nice...
+
+ WHEN ?
+
+    It's been coded in march 2001 following a thread on the GD-Algorithms list.
+
+      GDAlgorithms-list mailing list
+      GDAlgorithms-list@lists.sourceforge.net
+      http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list
+
+ WHO ?
+
+    Pierre Terdiman
+    June, 1, 2003
+
+    p.terdiman@wanadoo.fr
+    p.terdiman@codercorner.com
+ 
+    http://www.codercorner.com
+    http://www.codercorner.com/Opcode.htm
Index: /code/branches/ode/ode-0.9/OPCODE/StdAfx.cpp
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/StdAfx.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/StdAfx.cpp	(revision 216)
@@ -0,0 +1,10 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//#define ICE_MAIN
+#include "Stdafx.h"
Index: /code/branches/ode/ode-0.9/OPCODE/Stdafx.h
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/Stdafx.h	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/Stdafx.h	(revision 216)
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ *	OPCODE - Optimized Collision Detection
+ *	Copyright (C) 2001 Pierre Terdiman
+ *	Homepage: http://www.codercorner.com/Opcode.htm
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_)
+#define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+// Insert your headers here
+#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
+
+#include "Opcode.h"
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_)
Index: /code/branches/ode/ode-0.9/OPCODE/TemporalCoherence.txt
===================================================================
--- /code/branches/ode/ode-0.9/OPCODE/TemporalCoherence.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/OPCODE/TemporalCoherence.txt	(revision 216)
@@ -0,0 +1,32 @@
+
+> Hi John,
+>
+> I know I'll forget to tell you this if I don't write it right now....
+>
+> >(2) How is the receiving geometry for the shadow decided?
+>
+> I wrote about an LSS-test but actually performing a new VFC test (from the
+> light's view) is the same. In both cases, here's a trick to take advantage
+> of temporal coherence : test the world against a slightly larger than
+> necessary LSS or frustum. Keep the list of touched surfaces. Then next
+> frame, if the new volume is still contained within the previous one used
+for
+> the query, you can reuse the same list immediately. Actually it's a bit
+> similar to what you did in your sphere-tree, I think. Anyway, now the
+O(log
+> N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but
+> when you have N virtual frustum to test to drop N shadows, that's another
+> story.
+>
+> Two downsides:
+> - You need more ram to keep track of one list of meshes / shadow, but
+> usually it's not a lot.
+> - By using a larger volume for the query you possibly touch more
+> faces/surfaces, which will be rendered in the shadow pass. Usually it's
+not
+> a problem either since rendering is simply faster than geometric queries
+> those days. But of course, "your mileage may vary".
+>
+> Happy new year !
+>
+> Pierre
Index: /code/branches/ode/ode-0.9/README.txt
===================================================================
--- /code/branches/ode/ode-0.9/README.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/README.txt	(revision 216)
@@ -0,0 +1,41 @@
+The Open Dynamics Engine (ODE), Copyright (C) 2001-2007 Russell L. Smith.
+-------------------------------------------------------------------------
+
+ODE is a free, industrial quality library for simulating articulated
+rigid body dynamics - for example ground vehicles, legged creatures,
+and moving objects in VR environments. It is fast, flexible, robust
+and platform independent, with advanced joints, contact with friction,
+and built-in collision detection.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of EITHER:
+  (1) The GNU Lesser General Public License as published by the Free
+      Software Foundation; either version 2.1 of the License, or (at
+      your option) any later version. The text of the GNU Lesser
+      General Public License is included with this library in the
+      file LICENSE.TXT.
+  (2) The BSD-style license that is included with this library in
+      the file LICENSE-BSD.TXT.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+LICENSE.TXT and LICENSE-BSD.TXT for more details.
+
+ * Installation instructions are in the INSTALL file
+
+ * The ODE web pages are at http://ode.org/
+
+ * An online manual is at http://opende.sf.net/wiki/index.php/Manual
+
+ * API documentation is in the file ode/docs/index.html, or you
+   can view it on the web at http://opende.sf.net/docs/index.html
+
+All contributions are copyright by their owners, but the owners
+automatically transfer unrestricted rights in those changes to the ODE
+project, which is released under the dual licenses as indicated. The
+owners can also use the contributions in other projects under other
+licenses if they want (including sell them), but they can't prevent
+anyone from releasing the contributions under the dual ODE licenses as
+part of an ODE release.
+
Index: /code/branches/ode/ode-0.9/aclocal.m4
===================================================================
--- /code/branches/ode/ode-0.9/aclocal.m4	(revision 216)
+++ /code/branches/ode/ode-0.9/aclocal.m4	(revision 216)
@@ -0,0 +1,874 @@
+# generated automatically by aclocal 1.10 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_if(m4_PACKAGE_VERSION, [2.61],,
+[m4_fatal([this file was generated for autoconf 2.61.
+You have another version of autoconf.  If you want to use that,
+you should regenerate the build system entirely.], [63])])
+
+# Copyright (C) 2002, 2003, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.10], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10])dnl
+_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+	[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
+    dirpart=`AS_DIRNAME("$mf")`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`AS_DIRNAME(["$file"])`
+    AS_MKDIR_P([$dirpart/$fdir])
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+	      		     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                  [_AM_DEPENDENCIES(OBJC)],
+                  [define([AC_PROG_OBJC],
+                          defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $1 | $1:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
Index: /code/branches/ode/ode-0.9/autogen.sh
===================================================================
--- /code/branches/ode/ode-0.9/autogen.sh	(revision 216)
+++ /code/branches/ode/ode-0.9/autogen.sh	(revision 216)
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# The version nr detection is not working.
+# It fails if there is a '-' char in the version nr e.g.
+# We should not use it until fixed. - Bram
+
+## The reason this uses sed instead of "grep --only-matches"
+## is because MinGW's grep is an old version and does not contain that flag.
+#automake_version=`automake --version | grep --regexp='[+0-9].[+0-9].[+0-9]' | sed -n 's/[* ()A-Za-z]//g;p'`
+#automake_mayor=${automake_version%.*.*}
+#automake_minor=${automake_version%.*}
+#automake_minor=${automake_minor##*.}
+#automake_revision=${automake_version##*.}
+#echo "AutoMake Version: $automake_mayor.$automake_minor.$automake_revision"
+#
+#if [ $automake_mayor -eq 1 ]; then
+#    if [ $automake_minor -lt 8 ]; then
+#	echo "Automake must be 1.8.2 or higher, please upgrade"
+#	exit
+#    else
+#	if [ $automake_minor -eq 8 ] && [ $automake_revision -lt 2 ]; then
+#	    echo "Automake must be 1.8.2 or higher, please upgrade"
+#	    exit
+#	fi
+#    fi
+#fi
+
+echo "Please make sure that you use automake 1.8.2 or later"
+echo "Warnings about underquoted definitions are harmless"
+ 
+echo "Running aclocal"
+aclocal -I . || exit 1
+echo "Running autoheader"
+autoheader || exit 1
+echo "Running automake"
+automake --foreign --include-deps --add-missing --copy || exit 1
+echo "Running autoconf"
+autoconf || exit 1
+
+#./configure $*
+
+echo "Now you are ready to run ./configure"
Index: /code/branches/ode/ode-0.9/build/README.txt
===================================================================
--- /code/branches/ode/ode-0.9/build/README.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/build/README.txt	(revision 216)
@@ -0,0 +1,44 @@
+Premake-based Windows Build System
+Contributed by Jason Perkins (jason379@users.sourceforge.net)
+-------------------------------------------------------------------
+
+ SVN USERS: Before using these project files you must copy
+ config-default.h to ode/include/ode/config.h (or run Premake to
+ generate a new set of project files, see below). 
+
+
+ABOUT THESE FILES
+
+ These project files are automatically generated using a tool called
+ Premake, available from http://premake.sourceforge.net/. The scripts
+ used to build them have the ".lua" file extension. To regenerate the
+ stock project files for inclusion in a new release, type:
+
+   premake --makeall
+
+
+CREATING CUSTOM PROJECT FILES
+
+ To create a set of custom project files, first type `premake --help`
+ to see the options that you have available. Then generate the new
+ project files using the form:
+
+   premake [options] --target [toolset]
+
+ For instance:
+
+   premake --no-trimesh --target vs2005
+
+ To build the test applications and Drawstuff library, use the form:
+ 
+   premake --with-tests --target [toolset]
+   
+ If you ever decide that you want to remove your custom project, you
+ can just type:
+
+   premake --with-tests --clean
+
+ Feel free to direct any questions or comments to myself or the ODE
+ mailing list.
+
+
Index: /code/branches/ode/ode-0.9/build/config-default.h
===================================================================
--- /code/branches/ode/ode-0.9/build/config-default.h	(revision 216)
+++ /code/branches/ode/ode-0.9/build/config-default.h	(revision 216)
@@ -0,0 +1,176 @@
+/* This file was autogenerated by Premake */
+#ifndef _ODE_CONFIG_H_
+#define _ODE_CONFIG_H_
+
+
+/******************************************************************
+ * CONFIGURATON SETTINGS - you can change these, and then rebuild
+ *   ODE to modify the behavior of the library.
+ *
+ *   dSINGLE/dDOUBLE   - force ODE to use single-precision (float)
+ *                       or double-precision (double) for numbers.
+ *                       Only one should be defined.
+ *
+ *   dTRIMESH_ENABLED  - enable/disable trimesh support
+ *   dTRIMESH_OPCODE   - use the OPCODE trimesh engine
+ *   dTRIMESH_GIMPACT  - use the GIMPACT trimesh engine
+ *                       Only one trimesh engine should be enabled.
+ *
+ *   dUSE_MALLOC_FOR_ALLOCA (experimental)-
+ *                       Use malloc() instead of alloca(). Slower,
+ *                       but allows for larger systems and more
+ *                       graceful out-of-memory handling.
+ *
+ *   dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER (experimental)-
+ *                       Use an alternative trimesh-trimesh collider
+ *                       which should yield better results.
+ *
+ ******************************************************************/
+
+#define dSINGLE
+/* #define dDOUBLE */
+
+#define dTRIMESH_ENABLED 1
+#define dTRIMESH_OPCODE 1
+
+#define dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER 0
+
+/* #define dUSE_MALLOC_FOR_ALLOCA */
+
+
+/******************************************************************
+ * SYSTEM SETTINGS - you shouldn't need to change these. If you
+ *   run into an issue with these settings, please report it to
+ *   the ODE bug tracker at:
+ *      http://sf.net/tracker/?group_id=24884&atid=382799
+ ******************************************************************/
+
+/* Try to identify the platform */
+#if defined(_XENON)
+  #define ODE_PLATFORM_XBOX360
+#elif defined(SN_TARGET_PSP_HW)
+  #define ODE_PLATFORM_PSP
+#elif defined(SN_TARGET_PS3)
+  #define ODE_PLATFORM_PS3
+#elif defined(_MSC_VER) || defined(__CYGWIN32__) || defined(__MINGW32__)
+  #define ODE_PLATFORM_WINDOWS
+#elif defined(__linux__)
+  #define ODE_PLATFORM_LINUX
+#elif defined(__APPLE__) && defined(__MACH__)
+  #define ODE_PLATFORM_OSX
+#else
+  #error "Need some help identifying the platform!"
+#endif
+
+/* Additional platform defines used in the code */
+#if defined(ODE_PLATFORM_WINDOWS) && !defined(WIN32)
+  #define WIN32
+#endif
+
+#if defined(__CYGWIN32__) || defined(__MINGW32__)
+  #define CYGWIN
+#endif
+
+#if defined(ODE_PLATFORM_OSX)
+  #define macintosh
+#endif
+
+
+/* Define a DLL export symbol for those platforms that need it */
+#if defined(ODE_PLATFORM_WINDOWS)
+  #if defined(ODE_DLL)
+    #define ODE_API __declspec(dllexport)
+  #elif !defined(ODE_LIB)
+    #define ODE_DLL_API __declspec(dllimport)
+  #endif
+#endif
+
+#if !defined(ODE_API)
+  #define ODE_API
+#endif
+
+
+/* Pull in the standard headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <math.h>
+#include <string.h>
+#include <float.h>
+
+#if !defined(ODE_PLATFORM_PS3)
+  #include <malloc.h>
+#endif
+
+#if !defined(ODE_PLATFORM_WINDOWS)
+  #include <alloca.h>
+#endif
+
+
+/* Visual C does not define these functions */
+#if defined(_MSC_VER)
+  #define copysignf _copysign
+  #define copysign _copysign
+#endif
+
+
+/* Define a value for infinity */
+#if defined(HUGE_VALF)
+	#define ODE_INFINITY4 HUGE_VALF
+	#define ODE_INFINITY8 HUGE_VAL
+#elif defined(FLT_MAX)
+	#define ODE_INFINITY4 FLT_MAX
+	#define ODE_INFINITY8 DBL_MAX
+#else
+	static union { unsigned char __c[4]; float  __f; }  __ode_huge_valf = {{0,0,0x80,0x7f}};
+	static union { unsigned char __c[8]; double __d; }  __ode_huge_val  = {{0,0,0,0,0,0,0xf0,0x7f}};
+	#define ODE_INFINITY4 (__ode_huge_valf.__f)
+	#define ODE_INFINITY8 (__ode_huge_val.__d)
+#endif
+
+#ifdef dSINGLE
+	#define dInfinity ODE_INFINITY4
+	#define dEpsilon  FLT_EPSILON
+#else
+	#define dInfinity ODE_INFINITY8
+	#define dEpsilon  DBL_EPSILON
+#endif
+
+
+/* Well-defined common data types...need to define for 64 bit systems */
+#if defined(_M_IA64) || defined(__ia64__) || defined(_M_AMD64) || defined(__x86_64__)
+  #define X86_64_SYSTEM   1
+  typedef int             int32;
+  typedef unsigned int    uint32;
+  typedef short           int16;
+  typedef unsigned short  uint16;
+  typedef char            int8;
+  typedef unsigned char   uint8;
+#else
+  typedef int             int32;
+  typedef unsigned int    uint32;
+  typedef short           int16;
+  typedef unsigned short  uint16;
+  typedef char            int8;
+  typedef unsigned char   uint8;
+#endif
+
+/* An integer type that can be safely cast to a pointer. This definition
+ * should be safe even on 64-bit systems */
+typedef size_t intP;
+
+
+/* The efficient alignment. most platforms align data structures to some
+ * number of bytes, but this is not always the most efficient alignment.
+ * for example, many x86 compilers align to 4 bytes, but on a pentium it is
+ * important to align doubles to 8 byte boundaries (for speed), and the 4
+ * floats in a SIMD register to 16 byte boundaries. many other platforms have
+ * similar behavior. setting a larger alignment can waste a (very) small
+ * amount of memory. NOTE: this number must be a power of two. */
+#define EFFICIENT_ALIGNMENT 16
+
+
+/* Define this if your system supports anonymous memory maps (linux does) */
+#define MMAP_ANONYMOUS
+
+#endif
Index: /code/branches/ode/ode-0.9/build/demos.lua
===================================================================
--- /code/branches/ode/ode-0.9/build/demos.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/build/demos.lua	(revision 216)
@@ -0,0 +1,88 @@
+-- Here are the lists of demos to build. Add/remove new
+-- demos here and everything else should just work
+
+  local demos =
+  {
+    "boxstack",
+    "buggy",
+    "chain1",
+    "chain2",
+    "collision",
+    "crash",
+    "feedback",
+    "friction",
+    "heightfield",
+    "hinge",
+    "I",
+    "jointsPR",
+    "joints",
+    "motor",
+    "ode",
+    "plane2d",
+    "slider",
+    "space",
+    "space_stress",
+    "step"
+  }
+
+  if (not options["no-trimesh"]) then
+    table.insert(demos, "basket")
+    if (not options["no-cylinder"]) then
+      table.insert(demos, "cyl")
+    end
+    table.insert(demos, "moving_trimesh")
+    table.insert(demos, "trimesh")
+  end
+
+  if (not options["no-cylinder"]) then
+    table.insert(demos, "cylvssphere")
+  end
+
+
+-- Separate distribution files into toolset subdirectories
+
+  if (options["usetargetpath"]) then
+    packagepath = options["target"]
+  else
+    packagepath = "custom"
+  end
+
+
+-- Factory function for demo packages
+
+  function makedemo(index, name)
+    package = newpackage()
+    package.name = "demo_" .. name
+    package.kind = "exe"
+    package.language = "c++"
+    package.path = packagepath
+    package.objdir = "obj/"..name
+
+    package.includepaths = { "../../include" }
+    package.defines = { "_CRT_SECURE_NO_DEPRECATE" }
+
+    if (options.target == "vs6" or options.target == "vs2002" or options.target == "vs2003") then
+      package.config.DebugLib.buildflags   = { "static-runtime" }
+      package.config.ReleaseLib.buildflags = { "static-runtime" }
+    end
+
+    package.links = { "ode", "drawstuff" }
+    if (windows) then
+      table.insert(package.links, { "user32", "winmm", "gdi32", "opengl32", "glu32" })
+    else
+      table.insert(package.links, { "GL", "GLU" })
+    end
+
+    if (name == "chain1") then
+      package.files = { "../../ode/demo/demo_" .. name .. ".c" }
+    else
+      package.files = { "../../ode/demo/demo_" .. name .. ".cpp" }
+    end
+
+    if (windows) then
+      table.insert(package.defines, "WIN32")
+      table.insert(package.files, "../../drawstuff/src/resources.rc")
+    end
+  end
+
+  table.foreach(demos, makedemo)
Index: /code/branches/ode/ode-0.9/build/drawstuff.lua
===================================================================
--- /code/branches/ode/ode-0.9/build/drawstuff.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/build/drawstuff.lua	(revision 216)
@@ -0,0 +1,112 @@
+package.name = "drawstuff"
+package.language = "c++"
+package.objdir = "obj/drawstuff"
+
+
+-- Separate distribution files into toolset subdirectories
+
+  if (options["usetargetpath"]) then
+    package.path = options["target"]
+  else
+    package.path = "custom"
+  end
+
+
+-- Package Build Settings
+
+  local dll_defines =
+  {
+    "DS_DLL",
+    "USRDLL"
+  }
+  
+  local lib_defines = 
+  {
+    "DS_LIB"
+  }
+      
+  if (options["enable-shared-only"]) then
+    package.kind = "dll"
+    table.insert(package.defines, dll_defines)
+  elseif (options["enable-static-only"]) then
+    package.kind = "lib"
+    table.insert(package.defines, lib_defines)
+  else
+    package.config["DebugDLL"].kind = "dll"
+    package.config["DebugLib"].kind = "lib"
+    package.config["ReleaseDLL"].kind = "dll"
+    package.config["ReleaseLib"].kind = "lib"
+
+    table.insert(package.config["DebugDLL"].defines, dll_defines)
+    table.insert(package.config["ReleaseDLL"].defines, dll_defines)
+    table.insert(package.config["DebugLib"].defines, lib_defines)
+    table.insert(package.config["ReleaseLib"].defines, lib_defines)
+  end
+
+  package.includepaths =
+  {
+    "../../include"
+  }
+
+  -- disable VS2005 CRT security warnings
+  if (options["target"] == "vs2005") then
+    table.insert(package.defines, "_CRT_SECURE_NO_DEPRECATE")
+  end
+
+
+-- Build Flags
+
+	package.config["DebugLib"].buildflags   = { }
+	package.config["DebugDLL"].buildflags   = { }
+
+	package.config["ReleaseDLL"].buildflags = { "optimize-speed", "no-symbols", "no-frame-pointer" }
+	package.config["ReleaseLib"].buildflags = { "optimize-speed", "no-symbols", "no-frame-pointer" }
+
+	if (options.target == "vs6" or options.target == "vs2002" or options.target == "vs2003") then
+		table.insert(package.config.DebugLib.buildflags, "static-runtime")
+		table.insert(package.config.ReleaseLib.buildflags, "static-runtime")
+	end
+
+
+-- Libraries
+
+  local windows_libs =
+  {
+    "user32",
+    "opengl32",
+    "glu32",
+    "winmm",
+    "gdi32"
+  }
+
+  local x11_libs =
+  {
+    "X11",
+    "GL",
+    "GLU"
+  }
+  
+  if (windows) then
+    table.insert(package.links, windows_libs)
+  else
+    table.insert(package.links, x11_libs)
+  end
+
+
+-- Files
+
+  package.files =
+  {
+    matchfiles("../../include/drawstuff/*.h"),
+    "../../drawstuff/src/internal.h",
+    "../../drawstuff/src/drawstuff.cpp"
+  }
+
+  if (windows) then
+    table.insert(package.defines, "WIN32")
+    table.insert(package.files, "../../drawstuff/src/resource.h")
+    table.insert(package.files, "../../drawstuff/src/resources.rc")
+    table.insert(package.files, "../../drawstuff/src/windows.cpp")
+  else
+    table.insert(package.files, "../../drawstuff/src/x11.cpp")
+  end
Index: /code/branches/ode/ode-0.9/build/gnu/Makefile
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/Makefile	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/Makefile	(revision 216)
@@ -0,0 +1,155 @@
+# Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+# Options:
+#   CONFIG=[DebugDLL|ReleaseDLL|DebugLib|ReleaseLib]
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+export CONFIG
+
+.PHONY: all clean ode drawstuff demo_boxstack demo_buggy demo_chain1 demo_chain2 demo_collision demo_crash demo_feedback demo_friction demo_heightfield demo_hinge demo_I demo_joints demo_motor demo_ode demo_plane2d demo_slider demo_space demo_space_stress demo_step demo_basket demo_cyl demo_moving_trimesh demo_trimesh demo_cylvssphere tests
+
+all: ode drawstuff demo_boxstack demo_buggy demo_chain1 demo_chain2 demo_collision demo_crash demo_feedback demo_friction demo_heightfield demo_hinge demo_I demo_joints demo_motor demo_ode demo_plane2d demo_slider demo_space demo_space_stress demo_step demo_basket demo_cyl demo_moving_trimesh demo_trimesh demo_cylvssphere tests
+
+Makefile: ../premake.lua ../ode.lua ../drawstuff.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../demos.lua ../tests.lua
+	@echo ==== Regenerating Makefiles ====
+	@premake --file $^ --usetargetpath --with-demos --with-tests --clean --target gnu
+
+ode:
+	@echo ==== Building ode ====
+	@$(MAKE) --no-print-directory -C . -f ode.make
+
+drawstuff:
+	@echo ==== Building drawstuff ====
+	@$(MAKE) --no-print-directory -C . -f drawstuff.make
+
+demo_boxstack: ode drawstuff
+	@echo ==== Building demo_boxstack ====
+	@$(MAKE) --no-print-directory -C . -f demo_boxstack.make
+
+demo_buggy: ode drawstuff
+	@echo ==== Building demo_buggy ====
+	@$(MAKE) --no-print-directory -C . -f demo_buggy.make
+
+demo_chain1: ode drawstuff
+	@echo ==== Building demo_chain1 ====
+	@$(MAKE) --no-print-directory -C . -f demo_chain1.make
+
+demo_chain2: ode drawstuff
+	@echo ==== Building demo_chain2 ====
+	@$(MAKE) --no-print-directory -C . -f demo_chain2.make
+
+demo_collision: ode drawstuff
+	@echo ==== Building demo_collision ====
+	@$(MAKE) --no-print-directory -C . -f demo_collision.make
+
+demo_crash: ode drawstuff
+	@echo ==== Building demo_crash ====
+	@$(MAKE) --no-print-directory -C . -f demo_crash.make
+
+demo_feedback: ode drawstuff
+	@echo ==== Building demo_feedback ====
+	@$(MAKE) --no-print-directory -C . -f demo_feedback.make
+
+demo_friction: ode drawstuff
+	@echo ==== Building demo_friction ====
+	@$(MAKE) --no-print-directory -C . -f demo_friction.make
+
+demo_heightfield: ode drawstuff
+	@echo ==== Building demo_heightfield ====
+	@$(MAKE) --no-print-directory -C . -f demo_heightfield.make
+
+demo_hinge: ode drawstuff
+	@echo ==== Building demo_hinge ====
+	@$(MAKE) --no-print-directory -C . -f demo_hinge.make
+
+demo_I: ode drawstuff
+	@echo ==== Building demo_I ====
+	@$(MAKE) --no-print-directory -C . -f demo_I.make
+
+demo_joints: ode drawstuff
+	@echo ==== Building demo_joints ====
+	@$(MAKE) --no-print-directory -C . -f demo_joints.make
+
+demo_motor: ode drawstuff
+	@echo ==== Building demo_motor ====
+	@$(MAKE) --no-print-directory -C . -f demo_motor.make
+
+demo_ode: ode drawstuff
+	@echo ==== Building demo_ode ====
+	@$(MAKE) --no-print-directory -C . -f demo_ode.make
+
+demo_plane2d: ode drawstuff
+	@echo ==== Building demo_plane2d ====
+	@$(MAKE) --no-print-directory -C . -f demo_plane2d.make
+
+demo_slider: ode drawstuff
+	@echo ==== Building demo_slider ====
+	@$(MAKE) --no-print-directory -C . -f demo_slider.make
+
+demo_space: ode drawstuff
+	@echo ==== Building demo_space ====
+	@$(MAKE) --no-print-directory -C . -f demo_space.make
+
+demo_space_stress: ode drawstuff
+	@echo ==== Building demo_space_stress ====
+	@$(MAKE) --no-print-directory -C . -f demo_space_stress.make
+
+demo_step: ode drawstuff
+	@echo ==== Building demo_step ====
+	@$(MAKE) --no-print-directory -C . -f demo_step.make
+
+demo_basket: ode drawstuff
+	@echo ==== Building demo_basket ====
+	@$(MAKE) --no-print-directory -C . -f demo_basket.make
+
+demo_cyl: ode drawstuff
+	@echo ==== Building demo_cyl ====
+	@$(MAKE) --no-print-directory -C . -f demo_cyl.make
+
+demo_moving_trimesh: ode drawstuff
+	@echo ==== Building demo_moving_trimesh ====
+	@$(MAKE) --no-print-directory -C . -f demo_moving_trimesh.make
+
+demo_trimesh: ode drawstuff
+	@echo ==== Building demo_trimesh ====
+	@$(MAKE) --no-print-directory -C . -f demo_trimesh.make
+
+demo_cylvssphere: ode drawstuff
+	@echo ==== Building demo_cylvssphere ====
+	@$(MAKE) --no-print-directory -C . -f demo_cylvssphere.make
+
+tests: ode
+	@echo ==== Building tests ====
+	@$(MAKE) --no-print-directory -C . -f tests.make
+
+clean:
+	@$(MAKE) --no-print-directory -C . -f ode.make clean
+	@$(MAKE) --no-print-directory -C . -f drawstuff.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_boxstack.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_buggy.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_chain1.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_chain2.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_collision.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_crash.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_feedback.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_friction.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_heightfield.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_hinge.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_I.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_joints.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_motor.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_ode.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_plane2d.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_slider.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_space.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_space_stress.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_step.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_basket.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_cyl.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_moving_trimesh.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_trimesh.make clean
+	@$(MAKE) --no-print-directory -C . -f demo_cylvssphere.make clean
+	@$(MAKE) --no-print-directory -C . -f tests.make clean
Index: /code/branches/ode/ode-0.9/build/gnu/demo_I.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_I.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_I.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/I/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_I.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/I/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_I.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/I/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_I.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/I/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_I.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_I.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_I
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_I
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_I.o: ../../ode/demo/demo_I.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_basket.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_basket.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_basket.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/basket/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_basket.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/basket/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_basket.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/basket/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_basket.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/basket/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_basket.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_basket.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_basket
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_basket
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_basket.o: ../../ode/demo/demo_basket.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_boxstack.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_boxstack.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_boxstack.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Static Library Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/boxstack/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_boxstack.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/boxstack/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_boxstack.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/boxstack/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_boxstack.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/boxstack/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_boxstack.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_boxstack.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_boxstack
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_boxstack
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_boxstack.o: ../../ode/demo/demo_boxstack.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_buggy.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_buggy.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_buggy.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/buggy/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_buggy.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/buggy/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_buggy.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/buggy/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_buggy.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/buggy/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_buggy.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_buggy.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_buggy
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_buggy
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_buggy.o: ../../ode/demo/demo_buggy.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_chain1.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_chain1.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_chain1.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/chain1/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain1.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/chain1/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain1.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/chain1/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain1.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/chain1/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain1.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_chain1.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_chain1
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_chain1
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_chain1.o: ../../ode/demo/demo_chain1.c
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CC) $(CFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_chain2.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_chain2.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_chain2.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/chain2/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain2.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/chain2/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain2.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/chain2/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain2.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/chain2/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_chain2.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_chain2.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_chain2
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_chain2
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_chain2.o: ../../ode/demo/demo_chain2.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_collision.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_collision.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_collision.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/collision/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_collision.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/collision/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_collision.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/collision/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_collision.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/collision/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_collision.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_collision.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_collision
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_collision
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_collision.o: ../../ode/demo/demo_collision.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_crash.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_crash.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_crash.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/crash/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_crash.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/crash/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_crash.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/crash/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_crash.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/crash/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_crash.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_crash.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_crash
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_crash
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_crash.o: ../../ode/demo/demo_crash.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_cyl.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_cyl.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_cyl.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/cyl/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cyl.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/cyl/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cyl.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/cyl/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cyl.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/cyl/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cyl.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_cyl.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_cyl
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_cyl
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_cyl.o: ../../ode/demo/demo_cyl.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_cylvssphere.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_cylvssphere.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_cylvssphere.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/cylvssphere/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cylvssphere.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/cylvssphere/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cylvssphere.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/cylvssphere/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cylvssphere.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/cylvssphere/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_cylvssphere.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_cylvssphere.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_cylvssphere
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_cylvssphere
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_cylvssphere.o: ../../ode/demo/demo_cylvssphere.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_feedback.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_feedback.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_feedback.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/feedback/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_feedback.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/feedback/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_feedback.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/feedback/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_feedback.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/feedback/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_feedback.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_feedback.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_feedback
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_feedback
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_feedback.o: ../../ode/demo/demo_feedback.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_friction.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_friction.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_friction.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/friction/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_friction.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/friction/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_friction.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/friction/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_friction.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/friction/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_friction.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_friction.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_friction
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_friction
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_friction.o: ../../ode/demo/demo_friction.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_heightfield.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_heightfield.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_heightfield.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/heightfield/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_heightfield.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/heightfield/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_heightfield.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/heightfield/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_heightfield.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/heightfield/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_heightfield.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_heightfield.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_heightfield
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_heightfield
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_heightfield.o: ../../ode/demo/demo_heightfield.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_hinge.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_hinge.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_hinge.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/hinge/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_hinge.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/hinge/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_hinge.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/hinge/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_hinge.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/hinge/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_hinge.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_hinge.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_hinge
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_hinge
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_hinge.o: ../../ode/demo/demo_hinge.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_joints.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_joints.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_joints.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/joints/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_joints.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/joints/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_joints.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/joints/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_joints.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/joints/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_joints.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_joints.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_joints
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_joints
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_joints.o: ../../ode/demo/demo_joints.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_motor.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_motor.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_motor.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/motor/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_motor.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/motor/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_motor.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/motor/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_motor.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/motor/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_motor.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_motor.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_motor
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_motor
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_motor.o: ../../ode/demo/demo_motor.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_moving_trimesh.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_moving_trimesh.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_moving_trimesh.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/moving_trimesh/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_moving_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/moving_trimesh/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_moving_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/moving_trimesh/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_moving_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/moving_trimesh/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_moving_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_moving_trimesh.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_moving_trimesh
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_moving_trimesh
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_moving_trimesh.o: ../../ode/demo/demo_moving_trimesh.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_ode.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_ode.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_ode.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/ode/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_ode.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/ode/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_ode.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/ode/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_ode.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/ode/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_ode.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_ode.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_ode
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_ode
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_ode.o: ../../ode/demo/demo_ode.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_plane2d.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_plane2d.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_plane2d.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/plane2d/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_plane2d.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/plane2d/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_plane2d.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/plane2d/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_plane2d.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/plane2d/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_plane2d.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_plane2d.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_plane2d
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_plane2d
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_plane2d.o: ../../ode/demo/demo_plane2d.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_slider.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_slider.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_slider.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/slider/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_slider.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/slider/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_slider.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/slider/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_slider.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/slider/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_slider.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_slider.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_slider
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_slider
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_slider.o: ../../ode/demo/demo_slider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_space.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_space.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_space.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/space/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/space/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/space/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/space/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_space.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_space
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_space
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_space.o: ../../ode/demo/demo_space.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_space_stress.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_space_stress.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_space_stress.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/space_stress/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space_stress.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/space_stress/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space_stress.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/space_stress/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space_stress.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/space_stress/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_space_stress.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_space_stress.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_space_stress
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_space_stress
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_space_stress.o: ../../ode/demo/demo_space_stress.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_step.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_step.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_step.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/step/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_step.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/step/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_step.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/step/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_step.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/step/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_step.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_step.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_step
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_step
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_step.o: ../../ode/demo/demo_step.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/demo_trimesh.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/demo_trimesh.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/demo_trimesh.make	(revision 216)
@@ -0,0 +1,124 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/trimesh/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugDLL/ode.dll ../../lib/DebugDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/trimesh/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll ../../lib/ReleaseDLL/drawstuff.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/trimesh/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/DebugLib/libode.a ../../lib/DebugLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/trimesh/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a -luser32 -lwinmm -lgdi32 -lopengl32 -lglu32
+  LDDEPS := ../../lib/ReleaseLib/libode.a ../../lib/ReleaseLib/libdrawstuff.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -D "WIN32" -I "../../include"
+  TARGET := demo_trimesh.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/demo_trimesh.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking demo_trimesh
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning demo_trimesh
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/demo_trimesh.o: ../../ode/demo/demo_trimesh.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/drawstuff.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/drawstuff.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/drawstuff.make	(revision 216)
@@ -0,0 +1,130 @@
+# C++ Static Library Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/drawstuff/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "WIN32" -D "DS_DLL" -D "USRDLL" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -shared -luser32 -lopengl32 -lglu32 -lwinmm -lgdi32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "DS_DLL" -D "USRDLL" -I "../../include"
+  TARGET := drawstuff.dll
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/drawstuff/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "WIN32" -D "DS_DLL" -D "USRDLL" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -fomit-frame-pointer
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -shared -s -luser32 -lopengl32 -lglu32 -lwinmm -lgdi32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "DS_DLL" -D "USRDLL" -I "../../include"
+  TARGET := drawstuff.dll
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/drawstuff/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "WIN32" -D "DS_LIB" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -luser32 -lopengl32 -lglu32 -lwinmm -lgdi32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "DS_LIB" -I "../../include"
+  TARGET := libdrawstuff.a
+  BLDCMD = ar -rcs $(OUTDIR)/$(TARGET) $(OBJECTS) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/drawstuff/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "WIN32" -D "DS_LIB" -I "../../include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -fomit-frame-pointer
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s -luser32 -lopengl32 -lglu32 -lwinmm -lgdi32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "DS_LIB" -I "../../include"
+  TARGET := libdrawstuff.a
+  BLDCMD = ar -rcs $(OUTDIR)/$(TARGET) $(OBJECTS) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/drawstuff.o \
+	$(OBJDIR)/windows.o \
+
+RESOURCES := \
+	$(OBJDIR)/resources.res \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking drawstuff
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning drawstuff
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/drawstuff.o: ../../drawstuff/src/drawstuff.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/windows.o: ../../drawstuff/src/windows.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/resources.res: ../../drawstuff/src/resources.rc
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@windres $< -O coff -o $@ $(RESFLAGS)
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/ode.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/ode.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/ode.make	(revision 216)
@@ -0,0 +1,706 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/ode/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "WIN32" -D "ODE_DLL" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -shared -luser32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "ODE_DLL" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  TARGET := ode.dll
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/ode/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "WIN32" -D "ODE_DLL" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -fomit-frame-pointer
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -shared -s -luser32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "ODE_DLL" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  TARGET := ode.dll
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/ode/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "WIN32" -D "ODE_LIB" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -luser32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "ODE_LIB" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  TARGET := libode.a
+  BLDCMD = ar -rcs $(OUTDIR)/$(TARGET) $(OBJECTS) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/ode/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "WIN32" -D "ODE_LIB" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -fomit-frame-pointer
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s -luser32
+  LDDEPS :=
+  RESFLAGS := -D "WIN32" -D "ODE_LIB" -I "../../include" -I "../../OPCODE" -I "../../GIMPACT/include"
+  TARGET := libode.a
+  BLDCMD = ar -rcs $(OUTDIR)/$(TARGET) $(OBJECTS) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/fastdot.o \
+	$(OBJDIR)/fastldlt.o \
+	$(OBJDIR)/fastlsolve.o \
+	$(OBJDIR)/fastltsolve.o \
+	$(OBJDIR)/array.o \
+	$(OBJDIR)/box.o \
+	$(OBJDIR)/capsule.o \
+	$(OBJDIR)/collision_cylinder_box.o \
+	$(OBJDIR)/collision_cylinder_plane.o \
+	$(OBJDIR)/collision_cylinder_sphere.o \
+	$(OBJDIR)/collision_cylinder_trimesh.o \
+	$(OBJDIR)/collision_kernel.o \
+	$(OBJDIR)/collision_quadtreespace.o \
+	$(OBJDIR)/collision_space.o \
+	$(OBJDIR)/collision_transform.o \
+	$(OBJDIR)/collision_trimesh_box.o \
+	$(OBJDIR)/collision_trimesh_ccylinder.o \
+	$(OBJDIR)/collision_trimesh_distance.o \
+	$(OBJDIR)/collision_trimesh_gimpact.o \
+	$(OBJDIR)/collision_trimesh_opcode.o \
+	$(OBJDIR)/collision_trimesh_plane.o \
+	$(OBJDIR)/collision_trimesh_ray.o \
+	$(OBJDIR)/collision_trimesh_sphere.o \
+	$(OBJDIR)/collision_trimesh_trimesh.o \
+	$(OBJDIR)/collision_trimesh_trimesh_new.o \
+	$(OBJDIR)/collision_util.o \
+	$(OBJDIR)/convex.o \
+	$(OBJDIR)/cylinder.o \
+	$(OBJDIR)/error.o \
+	$(OBJDIR)/export-dif.o \
+	$(OBJDIR)/heightfield.o \
+	$(OBJDIR)/joint.o \
+	$(OBJDIR)/lcp.o \
+	$(OBJDIR)/mass.o \
+	$(OBJDIR)/mat.o \
+	$(OBJDIR)/matrix.o \
+	$(OBJDIR)/memory.o \
+	$(OBJDIR)/misc.o \
+	$(OBJDIR)/obstack.o \
+	$(OBJDIR)/ode.o \
+	$(OBJDIR)/odemath.o \
+	$(OBJDIR)/plane.o \
+	$(OBJDIR)/quickstep.o \
+	$(OBJDIR)/ray.o \
+	$(OBJDIR)/rotation.o \
+	$(OBJDIR)/sphere.o \
+	$(OBJDIR)/step.o \
+	$(OBJDIR)/stepfast.o \
+	$(OBJDIR)/testing.o \
+	$(OBJDIR)/timer.o \
+	$(OBJDIR)/util.o \
+	$(OBJDIR)/gimpact.o \
+	$(OBJDIR)/gim_boxpruning.o \
+	$(OBJDIR)/gim_contact.o \
+	$(OBJDIR)/gim_math.o \
+	$(OBJDIR)/gim_memory.o \
+	$(OBJDIR)/gim_trimesh.o \
+	$(OBJDIR)/gim_trimesh_capsule_collision.o \
+	$(OBJDIR)/gim_trimesh_ray_collision.o \
+	$(OBJDIR)/gim_trimesh_sphere_collision.o \
+	$(OBJDIR)/gim_trimesh_trimesh_collision.o \
+	$(OBJDIR)/gim_tri_tri_overlap.o \
+	$(OBJDIR)/Opcode.o \
+	$(OBJDIR)/OPC_AABBCollider.o \
+	$(OBJDIR)/OPC_AABBTree.o \
+	$(OBJDIR)/OPC_BaseModel.o \
+	$(OBJDIR)/OPC_BoxPruning.o \
+	$(OBJDIR)/OPC_Collider.o \
+	$(OBJDIR)/OPC_Common.o \
+	$(OBJDIR)/OPC_HybridModel.o \
+	$(OBJDIR)/OPC_LSSCollider.o \
+	$(OBJDIR)/OPC_MeshInterface.o \
+	$(OBJDIR)/OPC_Model.o \
+	$(OBJDIR)/OPC_OBBCollider.o \
+	$(OBJDIR)/OPC_OptimizedTree.o \
+	$(OBJDIR)/OPC_Picking.o \
+	$(OBJDIR)/OPC_PlanesCollider.o \
+	$(OBJDIR)/OPC_RayCollider.o \
+	$(OBJDIR)/OPC_SphereCollider.o \
+	$(OBJDIR)/OPC_SweepAndPrune.o \
+	$(OBJDIR)/OPC_TreeBuilders.o \
+	$(OBJDIR)/OPC_TreeCollider.o \
+	$(OBJDIR)/OPC_VolumeCollider.o \
+	$(OBJDIR)/StdAfx.o \
+	$(OBJDIR)/IceAABB.o \
+	$(OBJDIR)/IceContainer.o \
+	$(OBJDIR)/IceHPoint.o \
+	$(OBJDIR)/IceIndexedTriangle.o \
+	$(OBJDIR)/IceMatrix3x3.o \
+	$(OBJDIR)/IceMatrix4x4.o \
+	$(OBJDIR)/IceOBB.o \
+	$(OBJDIR)/IcePlane.o \
+	$(OBJDIR)/IcePoint.o \
+	$(OBJDIR)/IceRandom.o \
+	$(OBJDIR)/IceRay.o \
+	$(OBJDIR)/IceRevisitedRadix.o \
+	$(OBJDIR)/IceSegment.o \
+	$(OBJDIR)/IceTriangle.o \
+	$(OBJDIR)/IceUtils.o \
+
+RESOURCES := \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking ode
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning ode
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/fastdot.o: ../../ode/src/fastdot.c
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CC) $(CFLAGS) -o $@ -c $<
+
+$(OBJDIR)/fastldlt.o: ../../ode/src/fastldlt.c
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CC) $(CFLAGS) -o $@ -c $<
+
+$(OBJDIR)/fastlsolve.o: ../../ode/src/fastlsolve.c
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CC) $(CFLAGS) -o $@ -c $<
+
+$(OBJDIR)/fastltsolve.o: ../../ode/src/fastltsolve.c
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CC) $(CFLAGS) -o $@ -c $<
+
+$(OBJDIR)/array.o: ../../ode/src/array.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/box.o: ../../ode/src/box.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/capsule.o: ../../ode/src/capsule.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_cylinder_box.o: ../../ode/src/collision_cylinder_box.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_cylinder_plane.o: ../../ode/src/collision_cylinder_plane.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_cylinder_sphere.o: ../../ode/src/collision_cylinder_sphere.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_cylinder_trimesh.o: ../../ode/src/collision_cylinder_trimesh.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_kernel.o: ../../ode/src/collision_kernel.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_quadtreespace.o: ../../ode/src/collision_quadtreespace.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_space.o: ../../ode/src/collision_space.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_transform.o: ../../ode/src/collision_transform.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_box.o: ../../ode/src/collision_trimesh_box.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_ccylinder.o: ../../ode/src/collision_trimesh_ccylinder.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_distance.o: ../../ode/src/collision_trimesh_distance.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_gimpact.o: ../../ode/src/collision_trimesh_gimpact.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_opcode.o: ../../ode/src/collision_trimesh_opcode.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_plane.o: ../../ode/src/collision_trimesh_plane.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_ray.o: ../../ode/src/collision_trimesh_ray.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_sphere.o: ../../ode/src/collision_trimesh_sphere.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_trimesh.o: ../../ode/src/collision_trimesh_trimesh.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_trimesh_trimesh_new.o: ../../ode/src/collision_trimesh_trimesh_new.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/collision_util.o: ../../ode/src/collision_util.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/convex.o: ../../ode/src/convex.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/cylinder.o: ../../ode/src/cylinder.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/error.o: ../../ode/src/error.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/export-dif.o: ../../ode/src/export-dif.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/heightfield.o: ../../ode/src/heightfield.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/joint.o: ../../ode/src/joint.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/lcp.o: ../../ode/src/lcp.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/mass.o: ../../ode/src/mass.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/mat.o: ../../ode/src/mat.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/matrix.o: ../../ode/src/matrix.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/memory.o: ../../ode/src/memory.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/misc.o: ../../ode/src/misc.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/obstack.o: ../../ode/src/obstack.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/ode.o: ../../ode/src/ode.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/odemath.o: ../../ode/src/odemath.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/plane.o: ../../ode/src/plane.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/quickstep.o: ../../ode/src/quickstep.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/ray.o: ../../ode/src/ray.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/rotation.o: ../../ode/src/rotation.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/sphere.o: ../../ode/src/sphere.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/step.o: ../../ode/src/step.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/stepfast.o: ../../ode/src/stepfast.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/testing.o: ../../ode/src/testing.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/timer.o: ../../ode/src/timer.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/util.o: ../../ode/src/util.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gimpact.o: ../../GIMPACT/src/gimpact.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_boxpruning.o: ../../GIMPACT/src/gim_boxpruning.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_contact.o: ../../GIMPACT/src/gim_contact.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_math.o: ../../GIMPACT/src/gim_math.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_memory.o: ../../GIMPACT/src/gim_memory.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_trimesh.o: ../../GIMPACT/src/gim_trimesh.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_trimesh_capsule_collision.o: ../../GIMPACT/src/gim_trimesh_capsule_collision.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_trimesh_ray_collision.o: ../../GIMPACT/src/gim_trimesh_ray_collision.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_trimesh_sphere_collision.o: ../../GIMPACT/src/gim_trimesh_sphere_collision.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_trimesh_trimesh_collision.o: ../../GIMPACT/src/gim_trimesh_trimesh_collision.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/gim_tri_tri_overlap.o: ../../GIMPACT/src/gim_tri_tri_overlap.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/Opcode.o: ../../OPCODE/Opcode.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_AABBCollider.o: ../../OPCODE/OPC_AABBCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_AABBTree.o: ../../OPCODE/OPC_AABBTree.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_BaseModel.o: ../../OPCODE/OPC_BaseModel.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_BoxPruning.o: ../../OPCODE/OPC_BoxPruning.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_Collider.o: ../../OPCODE/OPC_Collider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_Common.o: ../../OPCODE/OPC_Common.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_HybridModel.o: ../../OPCODE/OPC_HybridModel.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_LSSCollider.o: ../../OPCODE/OPC_LSSCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_MeshInterface.o: ../../OPCODE/OPC_MeshInterface.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_Model.o: ../../OPCODE/OPC_Model.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_OBBCollider.o: ../../OPCODE/OPC_OBBCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_OptimizedTree.o: ../../OPCODE/OPC_OptimizedTree.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_Picking.o: ../../OPCODE/OPC_Picking.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_PlanesCollider.o: ../../OPCODE/OPC_PlanesCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_RayCollider.o: ../../OPCODE/OPC_RayCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_SphereCollider.o: ../../OPCODE/OPC_SphereCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_SweepAndPrune.o: ../../OPCODE/OPC_SweepAndPrune.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_TreeBuilders.o: ../../OPCODE/OPC_TreeBuilders.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_TreeCollider.o: ../../OPCODE/OPC_TreeCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/OPC_VolumeCollider.o: ../../OPCODE/OPC_VolumeCollider.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/StdAfx.o: ../../OPCODE/StdAfx.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceAABB.o: ../../OPCODE/Ice/IceAABB.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceContainer.o: ../../OPCODE/Ice/IceContainer.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceHPoint.o: ../../OPCODE/Ice/IceHPoint.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceIndexedTriangle.o: ../../OPCODE/Ice/IceIndexedTriangle.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceMatrix3x3.o: ../../OPCODE/Ice/IceMatrix3x3.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceMatrix4x4.o: ../../OPCODE/Ice/IceMatrix4x4.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceOBB.o: ../../OPCODE/Ice/IceOBB.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IcePlane.o: ../../OPCODE/Ice/IcePlane.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IcePoint.o: ../../OPCODE/Ice/IcePoint.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceRandom.o: ../../OPCODE/Ice/IceRandom.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceRay.o: ../../OPCODE/Ice/IceRay.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceRevisitedRadix.o: ../../OPCODE/Ice/IceRevisitedRadix.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceSegment.o: ../../OPCODE/Ice/IceSegment.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceTriangle.o: ../../OPCODE/Ice/IceTriangle.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/IceUtils.o: ../../OPCODE/Ice/IceUtils.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/gnu/tests.make
===================================================================
--- /code/branches/ode/ode-0.9/build/gnu/tests.make	(revision 216)
+++ /code/branches/ode/ode-0.9/build/gnu/tests.make	(revision 216)
@@ -0,0 +1,166 @@
+# C++ Console Executable Makefile autogenerated by premake
+# Don't edit this file! Instead edit `premake.lua` then rerun `make`
+
+ifndef CONFIG
+  CONFIG=DebugDLL
+endif
+
+ifeq ($(CONFIG),DebugDLL)
+  BINDIR := ../../lib/DebugDLL
+  LIBDIR := ../../lib/DebugDLL
+  OBJDIR := obj/tests/DebugDLL
+  OUTDIR := ../../lib/DebugDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugDLL/ode.dll
+  LDDEPS := ../../lib/DebugDLL/ode.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  TARGET := tests.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseDLL)
+  BINDIR := ../../lib/ReleaseDLL
+  LIBDIR := ../../lib/ReleaseDLL
+  OBJDIR := obj/tests/ReleaseDLL
+  OUTDIR := ../../lib/ReleaseDLL
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseDLL/ode.dll
+  LDDEPS := ../../lib/ReleaseDLL/ode.dll
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  TARGET := tests.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),DebugLib)
+  BINDIR := ../../lib/DebugLib
+  LIBDIR := ../../lib/DebugLib
+  OBJDIR := obj/tests/DebugLib
+  OUTDIR := ../../lib/DebugLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/DebugLib/libode.a
+  LDDEPS := ../../lib/DebugLib/libode.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  TARGET := tests.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+ifeq ($(CONFIG),ReleaseLib)
+  BINDIR := ../../lib/ReleaseLib
+  LIBDIR := ../../lib/ReleaseLib
+  OBJDIR := obj/tests/ReleaseLib
+  OUTDIR := ../../lib/ReleaseLib
+  CPPFLAGS := -MMD -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g
+  CXXFLAGS := $(CFLAGS)
+  LDFLAGS += -L$(BINDIR) -L$(LIBDIR) ../../lib/ReleaseLib/libode.a
+  LDDEPS := ../../lib/ReleaseLib/libode.a
+  RESFLAGS := -D "_CRT_SECURE_NO_DEPRECATE" -I "../../include" -I "../../tests/CppTestHarness"
+  TARGET := tests.exe
+  BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
+endif
+
+OBJECTS := \
+	$(OBJDIR)/main.o \
+	$(OBJDIR)/box_sphere.o \
+	$(OBJDIR)/HTMLTestReporter.o \
+	$(OBJDIR)/PrintfTestReporter.o \
+	$(OBJDIR)/Test.o \
+	$(OBJDIR)/TestLauncher.o \
+	$(OBJDIR)/TestReporter.o \
+	$(OBJDIR)/TestResults.o \
+	$(OBJDIR)/TestRunner.o \
+
+RESOURCES := \
+
+MKDIR_TYPE := msdos
+CMD := $(subst \,\\,$(ComSpec)$(COMSPEC))
+ifeq (,$(CMD))
+  MKDIR_TYPE := posix
+endif
+ifeq (/bin/sh.exe,$(SHELL))
+  MKDIR_TYPE := posix
+endif
+ifeq ($(MKDIR_TYPE),posix)
+  CMD_MKBINDIR := mkdir -p $(BINDIR)
+  CMD_MKLIBDIR := mkdir -p $(LIBDIR)
+  CMD_MKOUTDIR := mkdir -p $(OUTDIR)
+  CMD_MKOBJDIR := mkdir -p $(OBJDIR)
+else
+  CMD_MKBINDIR := $(CMD) /c if not exist $(subst /,\\,$(BINDIR)) mkdir $(subst /,\\,$(BINDIR))
+  CMD_MKLIBDIR := $(CMD) /c if not exist $(subst /,\\,$(LIBDIR)) mkdir $(subst /,\\,$(LIBDIR))
+  CMD_MKOUTDIR := $(CMD) /c if not exist $(subst /,\\,$(OUTDIR)) mkdir $(subst /,\\,$(OUTDIR))
+  CMD_MKOBJDIR := $(CMD) /c if not exist $(subst /,\\,$(OBJDIR)) mkdir $(subst /,\\,$(OBJDIR))
+endif
+
+.PHONY: clean
+
+$(OUTDIR)/$(TARGET): $(OBJECTS) $(LDDEPS) $(RESOURCES)
+	@echo Linking tests
+	-@$(CMD_MKBINDIR)
+	-@$(CMD_MKLIBDIR)
+	-@$(CMD_MKOUTDIR)
+	@$(BLDCMD)
+
+clean:
+	@echo Cleaning tests
+ifeq ($(MKDIR_TYPE),posix)
+	-@rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
+else
+	-@if exist $(subst /,\,$(OUTDIR)/$(TARGET)) del /q $(subst /,\,$(OUTDIR)/$(TARGET))
+	-@if exist $(subst /,\,$(OBJDIR)) del /q $(subst /,\,$(OBJDIR))
+	-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
+endif
+
+$(OBJDIR)/main.o: ../../tests/main.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/box_sphere.o: ../../tests/colliders/box_sphere.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/HTMLTestReporter.o: ../../tests/CppTestHarness/HTMLTestReporter.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/PrintfTestReporter.o: ../../tests/CppTestHarness/PrintfTestReporter.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/Test.o: ../../tests/CppTestHarness/Test.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/TestLauncher.o: ../../tests/CppTestHarness/TestLauncher.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/TestReporter.o: ../../tests/CppTestHarness/TestReporter.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/TestResults.o: ../../tests/CppTestHarness/TestResults.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(OBJDIR)/TestRunner.o: ../../tests/CppTestHarness/TestRunner.cpp
+	-@$(CMD_MKOBJDIR)
+	@echo $(notdir $<)
+	@$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+-include $(OBJECTS:%.o=%.d)
+
Index: /code/branches/ode/ode-0.9/build/ode.lua
===================================================================
--- /code/branches/ode/ode-0.9/build/ode.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/build/ode.lua	(revision 216)
@@ -0,0 +1,166 @@
+package.name = "ode"
+package.language = "c++"
+package.objdir = "obj/ode"
+
+
+-- Separate distribution files into toolset subdirectories
+
+  if (options["usetargetpath"]) then
+    package.path = options["target"]
+  else
+    package.path = "custom"
+  end
+
+
+-- Write a custom <config.h> to include/ode, based on the specified flags
+
+  io.input("config-default.h")
+  local text = io.read("*a")
+
+  if (options["with-doubles"]) then
+    text = string.gsub(text, "#define dSINGLE", "/* #define dSINGLE */")
+    text = string.gsub(text, "/%* #define dDOUBLE %*/", "#define dDOUBLE")
+  end
+
+  if (options["no-trimesh"]) then
+    
+    text = string.gsub(text, "#define dTRIMESH_ENABLED 1", "/* #define dTRIMESH_ENABLED 1 */")
+    text = string.gsub(text, "#define dTRIMESH_OPCODE 1", "/* #define dTRIMESH_OPCODE 1 */")
+  
+  elseif (options["with-gimpact"]) then
+
+    text = string.gsub(text, "#define dTRIMESH_OPCODE 1", "#define dTRIMESH_GIMPACT 1")
+  
+  end
+  
+  if (options["no-alloca"]) then
+    text = string.gsub(text, "/%* #define dUSE_MALLOC_FOR_ALLOCA %*/", "#define dUSE_MALLOC_FOR_ALLOCA")
+  end
+
+  io.output("../include/ode/config.h")
+  io.write(text)
+  io.close()
+
+
+-- Package Build Settings
+
+  if (options["enable-shared-only"]) then
+  
+    package.kind = "dll"
+    table.insert(package.defines, "ODE_DLL")
+  
+  elseif (options["enable-static-only"]) then
+  
+    package.kind = "lib"
+    table.insert(package.defines, "ODE_LIB")
+  
+  else
+  
+    package.config["DebugDLL"].kind = "dll"
+    package.config["DebugLib"].kind = "lib"
+    package.config["ReleaseDLL"].kind = "dll"
+    package.config["ReleaseLib"].kind = "lib"
+
+    table.insert(package.config["DebugDLL"].defines, "ODE_DLL")
+    table.insert(package.config["ReleaseDLL"].defines, "ODE_DLL")
+    table.insert(package.config["DebugLib"].defines, "ODE_LIB")
+    table.insert(package.config["ReleaseLib"].defines, "ODE_LIB")
+  
+  end
+
+  package.includepaths =
+  {
+    "../../include",
+    "../../OPCODE",
+    "../../GIMPACT/include"
+  }
+
+  if (windows) then
+    table.insert(package.defines, "WIN32")
+  end
+
+  -- disable VS2005 CRT security warnings
+  if (options["target"] == "vs2005") then
+    table.insert(package.defines, "_CRT_SECURE_NO_DEPRECATE")
+  end
+
+
+-- Build Flags
+
+	package.config["DebugLib"].buildflags   = { }
+	package.config["DebugDLL"].buildflags   = { }
+
+	package.config["ReleaseDLL"].buildflags = { "optimize-speed", "no-symbols", "no-frame-pointer" }
+	package.config["ReleaseLib"].buildflags = { "optimize-speed", "no-symbols", "no-frame-pointer" }
+
+	if (options.target == "vs6" or options.target == "vs2002" or options.target == "vs2003") then
+		table.insert(package.config.DebugLib.buildflags, "static-runtime")
+		table.insert(package.config.ReleaseLib.buildflags, "static-runtime")
+	end
+
+
+-- Libraries
+
+  if (windows) then
+    table.insert(package.links, "user32")
+  end
+
+
+-- Files
+
+  core_files =
+  {
+    matchfiles("../../include/ode/*.h"),
+    matchfiles ("../../ode/src/*.h", "../../ode/src/*.c", "../../ode/src/*.cpp")
+  }
+
+  excluded_files =
+  {
+    "../../ode/src/collision_std.cpp",
+    "../../ode/src/scrapbook.cpp",
+    "../../ode/src/stack.cpp"
+  }
+
+  trimesh_files =
+  {
+    "../../ode/src/collision_trimesh_internal.h",
+    "../../ode/src/collision_trimesh_opcode.cpp",
+    "../../ode/src/collision_trimesh_gimpact.cpp",
+    "../../ode/src/collision_trimesh_box.cpp",
+    "../../ode/src/collision_trimesh_ccylinder.cpp",
+    "../../ode/src/collision_cylinder_trimesh.cpp",
+    "../../ode/src/collision_trimesh_distance.cpp",
+    "../../ode/src/collision_trimesh_ray.cpp",
+    "../../ode/src/collision_trimesh_sphere.cpp",
+    "../../ode/src/collision_trimesh_trimesh.cpp",
+    "../../ode/src/collision_trimesh_plane.cpp"
+  }
+
+  opcode_files =
+  {
+    matchrecursive("../../OPCODE/*.h", "../../OPCODE/*.cpp")
+  }
+  
+  gimpact_files =
+  {
+    matchrecursive("../../GIMPACT/*.h", "../../GIMPACT/*.cpp")
+  }
+
+  dif_files =
+  {
+    "../../ode/src/export-dif.cpp"
+  }
+
+  package.files = { core_files }
+  package.excludes = { excluded_files }
+
+  if (options["no-dif"]) then
+    table.insert(package.excludes, dif_files)
+  end
+
+  if (options["no-trimesh"]) then
+    table.insert(package.excludes, trimesh_files)
+  else
+    table.insert(package.files, gimpact_files)
+    table.insert(package.files, opcode_files)
+  end
Index: /code/branches/ode/ode-0.9/build/premake.lua
===================================================================
--- /code/branches/ode/ode-0.9/build/premake.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/build/premake.lua	(revision 216)
@@ -0,0 +1,98 @@
+project.name = "ode"
+
+  if (options["target"] == "vs6") then
+    error("Visual Studio 6 is no longer supported; please upgrade to Visual Studio 2005 C++ Express.")
+  end
+  
+
+-- Define the build configurations. You can also use the flags 
+-- `--enable-shared-only` and `--enable-static-only` if you want to 
+-- call these packages from within your own Premake-enabled project.
+
+  if (not options["enable-shared-only"] and not options["enable-static-only"]) then
+    project.configs = { "DebugDLL", "ReleaseDLL", "DebugLib", "ReleaseLib" }
+  end
+
+
+-- Project options
+
+  addoption("with-doubles",  "Use double instead of float as base numeric type")
+  addoption("with-demos",    "Builds the demo applications and DrawStuff library")
+  addoption("with-tests",    "Builds the unit test application")
+  addoption("with-gimpact",  "Use GIMPACT for trimesh collisions (experimental)")
+  addoption("no-dif",        "Exclude DIF (Dynamics Interchange Format) exports")
+  addoption("no-trimesh",    "Exclude trimesh collision geometry")
+  addoption("no-alloca",     "Use heap memory instead of the stack (experimental)")
+
+
+-- If the `--usetargetpath` flag is specified, each set of generated files
+-- be placed in a directory named for the target toolset. This flag is
+-- used by the `--makeall` command (see below).
+
+  if (options["usetargetpath"]) then
+    project.path = options["target"]
+  end
+
+
+-- Set the output directories
+
+  if (options["enable-shared-only"] or options["enable-static-only"]) then
+    project.config["Debug"].bindir   = "../lib/debug"
+    project.config["Debug"].libdir   = "../lib/debug"
+    project.config["Release"].bindir = "../lib/release"
+    project.config["Release"].bindir = "../lib/release"
+  else
+    project.config["DebugDLL"].bindir   = "../lib/DebugDLL"
+    project.config["DebugDLL"].libdir   = "../lib/DebugDLL"
+    project.config["ReleaseDLL"].bindir = "../lib/ReleaseDLL"
+    project.config["ReleaseDLL"].libdir = "../lib/ReleaseDLL"
+    project.config["DebugLib"].bindir   = "../lib/DebugLib"
+    project.config["DebugLib"].libdir   = "../lib/DebugLib"
+    project.config["ReleaseLib"].bindir = "../lib/ReleaseLib"
+    project.config["ReleaseLib"].libdir = "../lib/ReleaseLib"
+  end
+
+
+-- Build packages
+
+  dopackage("ode.lua")
+
+  if (options["with-demos"]) then
+    dopackage("drawstuff.lua")
+    dopackage("demos.lua")
+  end
+
+  if (options["with-tests"]) then
+    dopackage("tests.lua")
+  end
+  
+
+-- Remove all intermediate files
+
+  function doclean(cmd, arg)
+    docommand(cmd, arg)
+    if (options["target"] == "") then
+      os.remove("../include/ode/config.h")
+    end
+    os.rmdir("custom")
+    os.rmdir("../lib/debug")
+    os.rmdir("../lib/release")
+    os.rmdir("../lib/DebugDLL")
+    os.rmdir("../lib/DebugLib")
+    os.rmdir("../lib/ReleaseDLL")
+    os.rmdir("../lib/ReleaseLib")
+    os.rmdir("gnu/obj")
+    os.rmdir("vs2002/obj")
+    os.rmdir("vs2003/obj")
+    os.rmdir("vs2005/obj")
+  end
+
+
+-- Generate all toolsets in one go
+
+  function domakeall(cmd, arg)
+    os.execute("premake --usetargetpath --with-demos --with-tests --clean --target vs2002")
+    os.execute("premake --usetargetpath --with-demos --with-tests --clean --target vs2003")
+    os.execute("premake --usetargetpath --with-demos --with-tests --clean --target vs2005")
+    os.execute("premake --usetargetpath --with-demos --with-tests --clean --target gnu")
+  end
Index: /code/branches/ode/ode-0.9/build/tests.lua
===================================================================
--- /code/branches/ode/ode-0.9/build/tests.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/build/tests.lua	(revision 216)
@@ -0,0 +1,26 @@
+  package.name = "tests"
+  package.kind = "exe"
+  package.language = "c++"
+  package.path = packagepath
+  package.objdir = "obj/tests"
+
+  package.includepaths =
+  {
+    "../../include",
+    "../../tests/CppTestHarness"
+  }
+
+  package.defines =
+  {
+    "_CRT_SECURE_NO_DEPRECATE"
+  }
+
+  package.links =
+  {
+    "ode"
+  }
+
+  package.files =
+  {
+    matchrecursive("../../tests/*.h", "../../tests/*.cpp")
+  }
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_I.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_I.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_I.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_I"
+	ProjectGUID="{A382F22A-4053-3445-9E14-02B3447E5F1E}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/I/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/I/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/I/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/I/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_I.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_basket.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_basket.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_basket.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_basket"
+	ProjectGUID="{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/basket/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/basket/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/basket/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/basket/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_basket.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_boxstack.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_boxstack.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_boxstack.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_boxstack"
+	ProjectGUID="{B9222926-060B-3248-830A-7C83791F4C61}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/boxstack/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/boxstack/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/boxstack/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/boxstack/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_boxstack.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_buggy.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_buggy.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_buggy.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_buggy"
+	ProjectGUID="{8C0F98C4-A95C-6B42-A522-8BC78284EB24}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/buggy/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/buggy/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/buggy/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/buggy/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_buggy.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_chain1.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_chain1.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_chain1.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_chain1"
+	ProjectGUID="{AD6DDB03-D653-0A48-929F-EB8523978EF2}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/chain1/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/chain1/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/chain1/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/chain1/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_chain1.c">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_chain2.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_chain2.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_chain2.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_chain2"
+	ProjectGUID="{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/chain2/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/chain2/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/chain2/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/chain2/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_chain2.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_collision.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_collision.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_collision.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_collision"
+	ProjectGUID="{31540B38-E155-6443-B2CD-BA527144D859}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/collision/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/collision/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/collision/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/collision/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_collision.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_crash.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_crash.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_crash.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_crash"
+	ProjectGUID="{7021A282-47AE-294A-9482-DB85E9820FBA}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/crash/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/crash/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/crash/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/crash/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_crash.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_cyl.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_cyl.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_cyl.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_cyl"
+	ProjectGUID="{35B7AA42-1B0A-D644-9728-2D9E83806F40}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/cyl/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/cyl/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/cyl/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/cyl/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_cyl.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_cylvssphere.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_cylvssphere.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_cylvssphere.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_cylvssphere"
+	ProjectGUID="{81101776-8512-C64E-875D-4FE66D465AB1}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/cylvssphere/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/cylvssphere/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/cylvssphere/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/cylvssphere/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_cylvssphere.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_feedback.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_feedback.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_feedback.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_feedback"
+	ProjectGUID="{9749BFD4-C4AE-164E-80B4-909F77D77869}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/feedback/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/feedback/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/feedback/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/feedback/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_feedback.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_friction.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_friction.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_friction.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_friction"
+	ProjectGUID="{1C345B16-ACE5-6549-8E84-C91B8392FD0C}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/friction/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/friction/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/friction/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/friction/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_friction.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_heightfield.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_heightfield.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_heightfield.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_heightfield"
+	ProjectGUID="{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/heightfield/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/heightfield/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/heightfield/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/heightfield/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_heightfield.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_hinge.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_hinge.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_hinge.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_hinge"
+	ProjectGUID="{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/hinge/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/hinge/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/hinge/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/hinge/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_hinge.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_joints.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_joints.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_joints.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_joints"
+	ProjectGUID="{9C43F96A-1793-5743-A767-2519C9FA48F8}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/joints/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/joints/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/joints/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/joints/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_joints.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_motor.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_motor.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_motor.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_motor"
+	ProjectGUID="{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/motor/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/motor/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/motor/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/motor/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_motor.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_moving_trimesh.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_moving_trimesh.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_moving_trimesh.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_moving_trimesh"
+	ProjectGUID="{F98194BC-7D59-0742-A5A1-7CA698E65FE2}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/moving_trimesh/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/moving_trimesh/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/moving_trimesh/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/moving_trimesh/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_moving_trimesh.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_ode.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_ode.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_ode.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_ode"
+	ProjectGUID="{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/ode/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/ode/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/ode/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/ode/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_ode.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_plane2d.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_plane2d.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_plane2d.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_plane2d"
+	ProjectGUID="{17389BAF-67B5-0747-9126-D01B69F4A0C5}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/plane2d/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/plane2d/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/plane2d/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/plane2d/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_plane2d.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_slider.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_slider.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_slider.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_slider"
+	ProjectGUID="{B0D00D10-D115-5849-976C-2A03A5E0B7D5}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/slider/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/slider/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/slider/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/slider/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_slider.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_space.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_space.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_space.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_space"
+	ProjectGUID="{15F48142-ACD9-0347-B18C-3C26152AEADE}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/space/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/space/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/space/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/space/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_space.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_space_stress.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_space_stress.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_space_stress.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_space_stress"
+	ProjectGUID="{86143476-EE08-104B-9C2B-FADE62C8DC23}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/space_stress/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/space_stress/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/space_stress/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/space_stress/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_space_stress.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_step.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_step.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_step.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_step"
+	ProjectGUID="{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/step/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/step/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/step/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/step/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_step.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/demo_trimesh.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/demo_trimesh.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/demo_trimesh.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="demo_trimesh"
+	ProjectGUID="{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/trimesh/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/trimesh/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/trimesh/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/trimesh/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_trimesh.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/drawstuff.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/drawstuff.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/drawstuff.vcproj	(revision 216)
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="drawstuff"
+	ProjectGUID="{4E655490-1B05-844D-871C-BA0F04084AF7}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/drawstuff/DebugDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib opengl32.lib glu32.lib winmm.lib gdi32.lib"
+				OutputFile="$(OutDir)/drawstuff.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/drawstuff.pdb"
+				SubSystem="2"
+				ImportLibrary="../../lib/DebugDLL/drawstuff.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/drawstuff/ReleaseDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib opengl32.lib glu32.lib winmm.lib gdi32.lib"
+				OutputFile="$(OutDir)/drawstuff.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="FALSE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/ReleaseDLL/drawstuff.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/drawstuff/DebugLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/drawstuff.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/drawstuff/ReleaseLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				StringPooling="TRUE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/drawstuff.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="include"
+			Filter="">
+			<Filter
+				Name="drawstuff"
+				Filter="">
+				<File
+					RelativePath="..\..\include\drawstuff\drawstuff.h">
+				</File>
+				<File
+					RelativePath="..\..\include\drawstuff\version.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\internal.h">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\drawstuff.cpp">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\resource.h">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\windows.cpp">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/ode.sln
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/ode.sln	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/ode.sln	(revision 216)
@@ -0,0 +1,336 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ode", "./ode.vcproj", "{7530658D-B5A8-6046-ACD2-C155B5A252A8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "drawstuff", "./drawstuff.vcproj", "{4E655490-1B05-844D-871C-BA0F04084AF7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_boxstack", "./demo_boxstack.vcproj", "{B9222926-060B-3248-830A-7C83791F4C61}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_buggy", "./demo_buggy.vcproj", "{8C0F98C4-A95C-6B42-A522-8BC78284EB24}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_chain1", "./demo_chain1.vcproj", "{AD6DDB03-D653-0A48-929F-EB8523978EF2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_chain2", "./demo_chain2.vcproj", "{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_collision", "./demo_collision.vcproj", "{31540B38-E155-6443-B2CD-BA527144D859}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_crash", "./demo_crash.vcproj", "{7021A282-47AE-294A-9482-DB85E9820FBA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_feedback", "./demo_feedback.vcproj", "{9749BFD4-C4AE-164E-80B4-909F77D77869}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_friction", "./demo_friction.vcproj", "{1C345B16-ACE5-6549-8E84-C91B8392FD0C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_heightfield", "./demo_heightfield.vcproj", "{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_hinge", "./demo_hinge.vcproj", "{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_I", "./demo_I.vcproj", "{A382F22A-4053-3445-9E14-02B3447E5F1E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_joints", "./demo_joints.vcproj", "{9C43F96A-1793-5743-A767-2519C9FA48F8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_motor", "./demo_motor.vcproj", "{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_ode", "./demo_ode.vcproj", "{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_plane2d", "./demo_plane2d.vcproj", "{17389BAF-67B5-0747-9126-D01B69F4A0C5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_slider", "./demo_slider.vcproj", "{B0D00D10-D115-5849-976C-2A03A5E0B7D5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_space", "./demo_space.vcproj", "{15F48142-ACD9-0347-B18C-3C26152AEADE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_space_stress", "./demo_space_stress.vcproj", "{86143476-EE08-104B-9C2B-FADE62C8DC23}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_step", "./demo_step.vcproj", "{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_basket", "./demo_basket.vcproj", "{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_cyl", "./demo_cyl.vcproj", "{35B7AA42-1B0A-D644-9728-2D9E83806F40}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_moving_trimesh", "./demo_moving_trimesh.vcproj", "{F98194BC-7D59-0742-A5A1-7CA698E65FE2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_trimesh", "./demo_trimesh.vcproj", "{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_cylvssphere", "./demo_cylvssphere.vcproj", "{81101776-8512-C64E-875D-4FE66D465AB1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "./tests.vcproj", "{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = DebugDLL
+		ConfigName.1 = ReleaseDLL
+		ConfigName.2 = DebugLib
+		ConfigName.3 = ReleaseLib
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+		{B9222926-060B-3248-830A-7C83791F4C61}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{B9222926-060B-3248-830A-7C83791F4C61}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{31540B38-E155-6443-B2CD-BA527144D859}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{31540B38-E155-6443-B2CD-BA527144D859}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{81101776-8512-C64E-875D-4FE66D465AB1}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+		{81101776-8512-C64E-875D-4FE66D465AB1}.1 = {4E655490-1B05-844D-871C-BA0F04084AF7}
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.0 = {7530658D-B5A8-6046-ACD2-C155B5A252A8}
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.DebugDLL.Build.0 = DebugDLL|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.DebugLib.ActiveCfg = DebugLib|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.DebugLib.Build.0 = DebugLib|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{7530658D-B5A8-6046-ACD2-C155B5A252A8}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.DebugDLL.Build.0 = DebugDLL|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.DebugLib.ActiveCfg = DebugLib|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.DebugLib.Build.0 = DebugLib|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{4E655490-1B05-844D-871C-BA0F04084AF7}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.DebugDLL.Build.0 = DebugDLL|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.DebugLib.ActiveCfg = DebugLib|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.DebugLib.Build.0 = DebugLib|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{B9222926-060B-3248-830A-7C83791F4C61}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.DebugDLL.Build.0 = DebugDLL|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.DebugLib.ActiveCfg = DebugLib|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.DebugLib.Build.0 = DebugLib|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{8C0F98C4-A95C-6B42-A522-8BC78284EB24}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.DebugDLL.Build.0 = DebugDLL|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.DebugLib.ActiveCfg = DebugLib|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.DebugLib.Build.0 = DebugLib|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{AD6DDB03-D653-0A48-929F-EB8523978EF2}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.DebugDLL.Build.0 = DebugDLL|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.DebugLib.ActiveCfg = DebugLib|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.DebugLib.Build.0 = DebugLib|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{341B4B78-CA98-5244-8CB0-5F4BCA52B8AB}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.DebugDLL.Build.0 = DebugDLL|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.DebugLib.ActiveCfg = DebugLib|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.DebugLib.Build.0 = DebugLib|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{31540B38-E155-6443-B2CD-BA527144D859}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.DebugDLL.Build.0 = DebugDLL|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.DebugLib.ActiveCfg = DebugLib|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.DebugLib.Build.0 = DebugLib|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{7021A282-47AE-294A-9482-DB85E9820FBA}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.DebugDLL.Build.0 = DebugDLL|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.DebugLib.ActiveCfg = DebugLib|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.DebugLib.Build.0 = DebugLib|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{9749BFD4-C4AE-164E-80B4-909F77D77869}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.DebugDLL.Build.0 = DebugDLL|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.DebugLib.ActiveCfg = DebugLib|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.DebugLib.Build.0 = DebugLib|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{1C345B16-ACE5-6549-8E84-C91B8392FD0C}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.DebugDLL.Build.0 = DebugDLL|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.DebugLib.ActiveCfg = DebugLib|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.DebugLib.Build.0 = DebugLib|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{B8CB1716-5EFF-F442-B261-4056E3F8B8D1}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.DebugDLL.Build.0 = DebugDLL|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.DebugLib.ActiveCfg = DebugLib|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.DebugLib.Build.0 = DebugLib|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{FB9A21A7-A63E-D744-A1D0-F393E7730DC2}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.DebugDLL.Build.0 = DebugDLL|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.DebugLib.ActiveCfg = DebugLib|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.DebugLib.Build.0 = DebugLib|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{A382F22A-4053-3445-9E14-02B3447E5F1E}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.DebugDLL.Build.0 = DebugDLL|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.DebugLib.ActiveCfg = DebugLib|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.DebugLib.Build.0 = DebugLib|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{9C43F96A-1793-5743-A767-2519C9FA48F8}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.DebugDLL.Build.0 = DebugDLL|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.DebugLib.ActiveCfg = DebugLib|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.DebugLib.Build.0 = DebugLib|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{C0CBBFAD-5F99-9B43-969E-13B3B46EBED5}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.DebugDLL.Build.0 = DebugDLL|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.DebugLib.ActiveCfg = DebugLib|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.DebugLib.Build.0 = DebugLib|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{439C6FAA-CF31-3E42-AD89-CCC07CBE3727}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.DebugDLL.Build.0 = DebugDLL|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.DebugLib.ActiveCfg = DebugLib|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.DebugLib.Build.0 = DebugLib|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{17389BAF-67B5-0747-9126-D01B69F4A0C5}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.DebugDLL.Build.0 = DebugDLL|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.DebugLib.ActiveCfg = DebugLib|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.DebugLib.Build.0 = DebugLib|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{B0D00D10-D115-5849-976C-2A03A5E0B7D5}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.DebugDLL.Build.0 = DebugDLL|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.DebugLib.ActiveCfg = DebugLib|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.DebugLib.Build.0 = DebugLib|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{15F48142-ACD9-0347-B18C-3C26152AEADE}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.DebugDLL.Build.0 = DebugDLL|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.DebugLib.ActiveCfg = DebugLib|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.DebugLib.Build.0 = DebugLib|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{86143476-EE08-104B-9C2B-FADE62C8DC23}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.DebugDLL.Build.0 = DebugDLL|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.DebugLib.ActiveCfg = DebugLib|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.DebugLib.Build.0 = DebugLib|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{B818CB9B-879B-2B44-82E2-2F96FA8D61E8}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.DebugDLL.Build.0 = DebugDLL|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.DebugLib.ActiveCfg = DebugLib|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.DebugLib.Build.0 = DebugLib|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{4D85F0AA-E59F-3B43-918F-B5033A5E3BD4}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.DebugDLL.Build.0 = DebugDLL|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.DebugLib.ActiveCfg = DebugLib|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.DebugLib.Build.0 = DebugLib|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{35B7AA42-1B0A-D644-9728-2D9E83806F40}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.DebugDLL.Build.0 = DebugDLL|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.DebugLib.ActiveCfg = DebugLib|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.DebugLib.Build.0 = DebugLib|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{F98194BC-7D59-0742-A5A1-7CA698E65FE2}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.DebugDLL.Build.0 = DebugDLL|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.DebugLib.ActiveCfg = DebugLib|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.DebugLib.Build.0 = DebugLib|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{EE803EF6-9285-BA47-AD4A-C5AE76BF7FDC}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.DebugDLL.Build.0 = DebugDLL|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.DebugLib.ActiveCfg = DebugLib|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.DebugLib.Build.0 = DebugLib|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{81101776-8512-C64E-875D-4FE66D465AB1}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.DebugDLL.Build.0 = DebugDLL|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.DebugLib.ActiveCfg = DebugLib|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.DebugLib.Build.0 = DebugLib|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}.ReleaseLib.Build.0 = ReleaseLib|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: /code/branches/ode/ode-0.9/build/vs2002/ode.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/ode.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/ode.vcproj	(revision 216)
@@ -0,0 +1,864 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="ode"
+	ProjectGUID="{7530658D-B5A8-6046-ACD2-C155B5A252A8}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/ode/DebugDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib"
+				OutputFile="$(OutDir)/ode.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/ode.pdb"
+				SubSystem="2"
+				ImportLibrary="../../lib/DebugDLL/ode.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/ode/ReleaseDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib"
+				OutputFile="$(OutDir)/ode.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="FALSE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/ReleaseDLL/ode.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/ode/DebugLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/ode.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/ode/ReleaseLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				StringPooling="TRUE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/ode.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="include"
+			Filter="">
+			<Filter
+				Name="ode"
+				Filter="">
+				<File
+					RelativePath="..\..\include\ode\collision.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\collision_space.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\collision_trimesh.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\common.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\compatibility.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\config.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\contact.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\error.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\export-dif.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\mass.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\matrix.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\memory.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\misc.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\objects.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\ode.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odecpp.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odecpp_collision.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odemath.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\rotation.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\timer.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\src\array.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_kernel.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_space_internal.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_std.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_transform.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_internal.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_util.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\heightfield.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\joint.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\lcp.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mat.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\objects.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\obstack.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\quickstep.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\stack.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\step.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\testing.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\util.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastdot.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastldlt.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastlsolve.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastltsolve.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\array.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\capsule.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_kernel.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_quadtreespace.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_space.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_transform.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_ccylinder.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_distance.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_gimpact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_opcode.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_ray.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_trimesh_new.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_util.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\convex.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\cylinder.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\error.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\export-dif.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\heightfield.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\joint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\lcp.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mass.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mat.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\matrix.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\memory.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\misc.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\obstack.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\ode.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\odemath.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\quickstep.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\ray.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\rotation.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\step.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\stepfast.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\testing.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\timer.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\util.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="GIMPACT"
+			Filter="">
+			<Filter
+				Name="include"
+				Filter="">
+				<Filter
+					Name="GIMPACT"
+					Filter="">
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gimpact.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_boxpruning.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_contact.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_geometry.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_math.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_memory.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_radixsort.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_trimesh.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_capsule_collision.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_collision.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_sphere_collision.h">
+					</File>
+				</Filter>
+			</Filter>
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\GIMPACT\src\gimpact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_boxpruning.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_contact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_math.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_memory.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_capsule_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_ray_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_sphere_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_trimesh_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_tri_tri_overlap.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="OPCODE"
+			Filter="">
+			<Filter
+				Name="Ice"
+				Filter="">
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAABB.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAxes.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceBoundingSphere.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceContainer.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceFPU.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceHPoint.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceIndexedTriangle.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceLSS.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix3x3.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix4x4.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMemoryMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceOBB.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePairs.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePlane.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePoint.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePreprocessor.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRandom.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRay.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRevisitedRadix.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceSegment.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriangle.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriList.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTypes.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceUtils.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAABB.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceContainer.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceHPoint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceIndexedTriangle.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix3x3.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix4x4.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceOBB.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePlane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePoint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRandom.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRay.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRevisitedRadix.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceSegment.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriangle.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceUtils.cpp">
+				</File>
+			</Filter>
+			<File
+				RelativePath="..\..\OPCODE\Opcode.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBTree.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BaseModel.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxBoxOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxPruning.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Collider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Common.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_HybridModel.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_IceHook.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_MeshInterface.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Model.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OBBCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OptimizedTree.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Picking.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Settings.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SweepAndPrune.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeBuilders.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TriBoxOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TriTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_VolumeCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\Stdafx.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\Opcode.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBTree.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BaseModel.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxPruning.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Collider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Common.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_HybridModel.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_MeshInterface.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Model.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OBBCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OptimizedTree.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Picking.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SweepAndPrune.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeBuilders.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_VolumeCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\StdAfx.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2002/tests.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2002/tests.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2002/tests.vcproj	(revision 216)
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="tests"
+	ProjectGUID="{E10C083A-2A98-6D4F-A1D3-EF613C0C7141}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/tests/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/tests/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/tests/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/tests/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="tests"
+			Filter="">
+			<Filter
+				Name="CppTestHarness"
+				Filter="">
+				<File
+					RelativePath="..\..\tests\CppTestHarness\CheckMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Checks.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\CppTestHarness.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\HTMLTestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\PrintfTestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\SignalTranslator.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Test.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestLauncher.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestResults.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestRunner.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TypedTestLauncher.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\HTMLTestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\PrintfTestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Test.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestLauncher.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestResults.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestRunner.cpp">
+				</File>
+			</Filter>
+			<Filter
+				Name="colliders"
+				Filter="">
+				<File
+					RelativePath="..\..\tests\colliders\box_sphere.cpp">
+				</File>
+			</Filter>
+			<File
+				RelativePath="..\..\tests\main.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_I.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_I.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_I.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_I"
+	ProjectGUID="{F387003D-4CE3-7548-A471-3C2D188AB7D3}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/I/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/I/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/I/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/I/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_I.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_basket.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_basket.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_basket.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_basket"
+	ProjectGUID="{658A5390-4A5E-5A48-9A10-B04A53848994}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/basket/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/basket/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/basket/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/basket/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_basket.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_boxstack.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_boxstack.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_boxstack.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_boxstack"
+	ProjectGUID="{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/boxstack/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/boxstack/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/boxstack/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/boxstack/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_boxstack.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_buggy.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_buggy.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_buggy.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_buggy"
+	ProjectGUID="{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/buggy/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/buggy/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/buggy/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/buggy/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_buggy.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_chain1.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_chain1.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_chain1.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_chain1"
+	ProjectGUID="{DC6294E4-6A55-1D41-9846-53EC913D0DC3}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/chain1/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/chain1/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/chain1/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/chain1/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_chain1.c">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_chain2.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_chain2.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_chain2.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_chain2"
+	ProjectGUID="{D01EDE86-5B74-A24B-B084-FC79608D376D}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/chain2/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/chain2/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/chain2/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/chain2/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_chain2.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_collision.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_collision.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_collision.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_collision"
+	ProjectGUID="{238F8FBA-C48F-694E-9D78-6D99DA572645}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/collision/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/collision/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/collision/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/collision/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_collision.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_crash.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_crash.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_crash.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_crash"
+	ProjectGUID="{4D828A55-6AAD-B948-8817-38EB3E85F504}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/crash/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/crash/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/crash/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/crash/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_crash.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_cyl.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_cyl.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_cyl.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_cyl"
+	ProjectGUID="{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/cyl/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/cyl/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/cyl/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/cyl/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_cyl.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_cylvssphere.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_cylvssphere.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_cylvssphere.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_cylvssphere"
+	ProjectGUID="{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/cylvssphere/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/cylvssphere/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/cylvssphere/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/cylvssphere/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_cylvssphere.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_feedback.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_feedback.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_feedback.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_feedback"
+	ProjectGUID="{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/feedback/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/feedback/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/feedback/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/feedback/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_feedback.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_friction.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_friction.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_friction.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_friction"
+	ProjectGUID="{ECE402AB-3062-6745-AC2A-85BB65CA000F}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/friction/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/friction/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/friction/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/friction/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_friction.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_heightfield.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_heightfield.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_heightfield.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_heightfield"
+	ProjectGUID="{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/heightfield/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/heightfield/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/heightfield/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/heightfield/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_heightfield.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_hinge.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_hinge.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_hinge.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_hinge"
+	ProjectGUID="{1F4FB263-EF66-F247-807C-30DA768C7072}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/hinge/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/hinge/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/hinge/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/hinge/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_hinge.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_joints.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_joints.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_joints.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_joints"
+	ProjectGUID="{B05FDE9B-2066-9A49-A286-52FA07638F67}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/joints/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/joints/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/joints/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/joints/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_joints.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_motor.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_motor.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_motor.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_motor"
+	ProjectGUID="{94367E2E-BAD6-C04F-9929-77D2FFFD945B}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/motor/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/motor/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/motor/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/motor/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_motor.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_moving_trimesh.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_moving_trimesh.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_moving_trimesh.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_moving_trimesh"
+	ProjectGUID="{94C25B7D-977F-E744-A255-2554C19771A8}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/moving_trimesh/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/moving_trimesh/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/moving_trimesh/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/moving_trimesh/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_moving_trimesh.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_ode.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_ode.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_ode.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_ode"
+	ProjectGUID="{26876866-6691-1C48-BB6A-2CF14E2E2B16}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/ode/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/ode/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/ode/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/ode/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_ode.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_plane2d.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_plane2d.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_plane2d.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_plane2d"
+	ProjectGUID="{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/plane2d/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/plane2d/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/plane2d/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/plane2d/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_plane2d.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_slider.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_slider.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_slider.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_slider"
+	ProjectGUID="{5621B59B-14FB-5741-8F14-90A0865161F8}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/slider/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/slider/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/slider/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/slider/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_slider.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_space.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_space.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_space.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_space"
+	ProjectGUID="{8C77C726-B2ED-3745-9433-FF91E9D2556F}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/space/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/space/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/space/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/space/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_space.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_space_stress.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_space_stress.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_space_stress.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_space_stress"
+	ProjectGUID="{CE00A8A1-848B-9448-9A86-03F518195687}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/space_stress/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/space_stress/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/space_stress/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/space_stress/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_space_stress.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_step.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_step.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_step.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_step"
+	ProjectGUID="{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/step/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/step/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/step/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/step/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_step.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/demo_trimesh.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/demo_trimesh.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/demo_trimesh.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="demo_trimesh"
+	ProjectGUID="{01532891-8699-8846-9409-0DADE3A53422}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/trimesh/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/trimesh/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/trimesh/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/trimesh/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="demo"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\demo\demo_trimesh.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/drawstuff.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/drawstuff.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/drawstuff.vcproj	(revision 216)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="drawstuff"
+	ProjectGUID="{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/drawstuff/DebugDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib opengl32.lib glu32.lib winmm.lib gdi32.lib"
+				OutputFile="$(OutDir)/drawstuff.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/drawstuff.pdb"
+				SubSystem="2"
+				ImportLibrary="../../lib/DebugDLL/drawstuff.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/drawstuff/ReleaseDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib opengl32.lib glu32.lib winmm.lib gdi32.lib"
+				OutputFile="$(OutDir)/drawstuff.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="FALSE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/ReleaseDLL/drawstuff.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_DLL;USRDLL"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/drawstuff/DebugLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/drawstuff.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/drawstuff/ReleaseLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				StringPooling="TRUE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/drawstuff.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;DS_LIB"
+				AdditionalIncludeDirectories="../../include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="include"
+			Filter="">
+			<Filter
+				Name="drawstuff"
+				Filter="">
+				<File
+					RelativePath="..\..\include\drawstuff\drawstuff.h">
+				</File>
+				<File
+					RelativePath="..\..\include\drawstuff\version.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\drawstuff\src\internal.h">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\drawstuff.cpp">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\resource.h">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\windows.cpp">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/ode.sln
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/ode.sln	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/ode.sln	(revision 216)
@@ -0,0 +1,388 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ode", "./ode.vcproj", "{5F0953F1-B966-BA4E-A31A-C002A407FD47}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "drawstuff", "./drawstuff.vcproj", "{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_boxstack", "./demo_boxstack.vcproj", "{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_buggy", "./demo_buggy.vcproj", "{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_chain1", "./demo_chain1.vcproj", "{DC6294E4-6A55-1D41-9846-53EC913D0DC3}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_chain2", "./demo_chain2.vcproj", "{D01EDE86-5B74-A24B-B084-FC79608D376D}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_collision", "./demo_collision.vcproj", "{238F8FBA-C48F-694E-9D78-6D99DA572645}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_crash", "./demo_crash.vcproj", "{4D828A55-6AAD-B948-8817-38EB3E85F504}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_feedback", "./demo_feedback.vcproj", "{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_friction", "./demo_friction.vcproj", "{ECE402AB-3062-6745-AC2A-85BB65CA000F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_heightfield", "./demo_heightfield.vcproj", "{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_hinge", "./demo_hinge.vcproj", "{1F4FB263-EF66-F247-807C-30DA768C7072}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_I", "./demo_I.vcproj", "{F387003D-4CE3-7548-A471-3C2D188AB7D3}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_joints", "./demo_joints.vcproj", "{B05FDE9B-2066-9A49-A286-52FA07638F67}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_motor", "./demo_motor.vcproj", "{94367E2E-BAD6-C04F-9929-77D2FFFD945B}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_ode", "./demo_ode.vcproj", "{26876866-6691-1C48-BB6A-2CF14E2E2B16}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_plane2d", "./demo_plane2d.vcproj", "{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_slider", "./demo_slider.vcproj", "{5621B59B-14FB-5741-8F14-90A0865161F8}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_space", "./demo_space.vcproj", "{8C77C726-B2ED-3745-9433-FF91E9D2556F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_space_stress", "./demo_space_stress.vcproj", "{CE00A8A1-848B-9448-9A86-03F518195687}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_step", "./demo_step.vcproj", "{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_basket", "./demo_basket.vcproj", "{658A5390-4A5E-5A48-9A10-B04A53848994}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_cyl", "./demo_cyl.vcproj", "{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_moving_trimesh", "./demo_moving_trimesh.vcproj", "{94C25B7D-977F-E744-A255-2554C19771A8}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_trimesh", "./demo_trimesh.vcproj", "{01532891-8699-8846-9409-0DADE3A53422}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_cylvssphere", "./demo_cylvssphere.vcproj", "{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC} = {029C9CCD-2B3E-BE45-8520-A231CD8C67EC}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "./tests.vcproj", "{65028345-CDF4-B74C-B94F-8F4A0493D8C4}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47} = {5F0953F1-B966-BA4E-A31A-C002A407FD47}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		DebugDLL = DebugDLL
+		ReleaseDLL = ReleaseDLL
+		DebugLib = DebugLib
+		ReleaseLib = ReleaseLib
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.DebugDLL.Build.0 = DebugDLL|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.DebugLib.ActiveCfg = DebugLib|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.DebugLib.Build.0 = DebugLib|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{5F0953F1-B966-BA4E-A31A-C002A407FD47}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.DebugDLL.Build.0 = DebugDLL|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.DebugLib.ActiveCfg = DebugLib|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.DebugLib.Build.0 = DebugLib|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{029C9CCD-2B3E-BE45-8520-A231CD8C67EC}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.DebugDLL.Build.0 = DebugDLL|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.DebugLib.ActiveCfg = DebugLib|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.DebugLib.Build.0 = DebugLib|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{F25F1B18-2103-B147-A5F0-984D0D1EBBDA}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.DebugDLL.Build.0 = DebugDLL|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.DebugLib.ActiveCfg = DebugLib|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.DebugLib.Build.0 = DebugLib|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{79FFAF28-2FD1-6744-909F-7F7E68DDEB6D}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.DebugDLL.Build.0 = DebugDLL|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.DebugLib.ActiveCfg = DebugLib|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.DebugLib.Build.0 = DebugLib|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{DC6294E4-6A55-1D41-9846-53EC913D0DC3}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.DebugDLL.Build.0 = DebugDLL|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.DebugLib.ActiveCfg = DebugLib|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.DebugLib.Build.0 = DebugLib|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{D01EDE86-5B74-A24B-B084-FC79608D376D}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.DebugDLL.Build.0 = DebugDLL|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.DebugLib.ActiveCfg = DebugLib|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.DebugLib.Build.0 = DebugLib|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{238F8FBA-C48F-694E-9D78-6D99DA572645}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.DebugDLL.Build.0 = DebugDLL|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.DebugLib.ActiveCfg = DebugLib|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.DebugLib.Build.0 = DebugLib|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{4D828A55-6AAD-B948-8817-38EB3E85F504}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.DebugDLL.Build.0 = DebugDLL|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.DebugLib.ActiveCfg = DebugLib|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.DebugLib.Build.0 = DebugLib|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{2CFE9EEA-E735-BD49-96FF-34C2C3893AC7}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.DebugDLL.Build.0 = DebugDLL|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.DebugLib.ActiveCfg = DebugLib|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.DebugLib.Build.0 = DebugLib|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{ECE402AB-3062-6745-AC2A-85BB65CA000F}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.DebugDLL.Build.0 = DebugDLL|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.DebugLib.ActiveCfg = DebugLib|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.DebugLib.Build.0 = DebugLib|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{D746A3DA-E7D4-6A4A-B078-D5E5A79CFB5F}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.DebugDLL.Build.0 = DebugDLL|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.DebugLib.ActiveCfg = DebugLib|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.DebugLib.Build.0 = DebugLib|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{1F4FB263-EF66-F247-807C-30DA768C7072}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.DebugDLL.Build.0 = DebugDLL|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.DebugLib.ActiveCfg = DebugLib|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.DebugLib.Build.0 = DebugLib|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{F387003D-4CE3-7548-A471-3C2D188AB7D3}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.DebugDLL.Build.0 = DebugDLL|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.DebugLib.ActiveCfg = DebugLib|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.DebugLib.Build.0 = DebugLib|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{B05FDE9B-2066-9A49-A286-52FA07638F67}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.DebugDLL.Build.0 = DebugDLL|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.DebugLib.ActiveCfg = DebugLib|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.DebugLib.Build.0 = DebugLib|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{94367E2E-BAD6-C04F-9929-77D2FFFD945B}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.DebugDLL.Build.0 = DebugDLL|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.DebugLib.ActiveCfg = DebugLib|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.DebugLib.Build.0 = DebugLib|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{26876866-6691-1C48-BB6A-2CF14E2E2B16}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.DebugDLL.Build.0 = DebugDLL|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.DebugLib.ActiveCfg = DebugLib|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.DebugLib.Build.0 = DebugLib|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{4C672D5A-F87B-C645-8CA2-A9F4BF94525A}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.DebugDLL.Build.0 = DebugDLL|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.DebugLib.ActiveCfg = DebugLib|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.DebugLib.Build.0 = DebugLib|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{5621B59B-14FB-5741-8F14-90A0865161F8}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.DebugDLL.Build.0 = DebugDLL|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.DebugLib.ActiveCfg = DebugLib|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.DebugLib.Build.0 = DebugLib|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{8C77C726-B2ED-3745-9433-FF91E9D2556F}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.DebugDLL.Build.0 = DebugDLL|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.DebugLib.ActiveCfg = DebugLib|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.DebugLib.Build.0 = DebugLib|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{CE00A8A1-848B-9448-9A86-03F518195687}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.DebugDLL.Build.0 = DebugDLL|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.DebugLib.ActiveCfg = DebugLib|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.DebugLib.Build.0 = DebugLib|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{441E2B42-D9D5-FD48-872E-1F547FEFEC1D}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.DebugDLL.Build.0 = DebugDLL|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.DebugLib.ActiveCfg = DebugLib|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.DebugLib.Build.0 = DebugLib|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{658A5390-4A5E-5A48-9A10-B04A53848994}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.DebugDLL.Build.0 = DebugDLL|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.DebugLib.ActiveCfg = DebugLib|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.DebugLib.Build.0 = DebugLib|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{3E62DE94-D6E5-0F42-A99B-CAA0139E7C82}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.DebugDLL.Build.0 = DebugDLL|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.DebugLib.ActiveCfg = DebugLib|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.DebugLib.Build.0 = DebugLib|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{94C25B7D-977F-E744-A255-2554C19771A8}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.DebugDLL.Build.0 = DebugDLL|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.DebugLib.ActiveCfg = DebugLib|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.DebugLib.Build.0 = DebugLib|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{01532891-8699-8846-9409-0DADE3A53422}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.DebugDLL.Build.0 = DebugDLL|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.DebugLib.ActiveCfg = DebugLib|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.DebugLib.Build.0 = DebugLib|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{9419B36B-EB65-8F4C-9E29-9DE728FEF4BA}.ReleaseLib.Build.0 = ReleaseLib|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.DebugDLL.ActiveCfg = DebugDLL|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.DebugDLL.Build.0 = DebugDLL|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.ReleaseDLL.ActiveCfg = ReleaseDLL|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.ReleaseDLL.Build.0 = ReleaseDLL|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.DebugLib.ActiveCfg = DebugLib|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.DebugLib.Build.0 = DebugLib|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.ReleaseLib.ActiveCfg = ReleaseLib|Win32
+		{65028345-CDF4-B74C-B94F-8F4A0493D8C4}.ReleaseLib.Build.0 = ReleaseLib|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: /code/branches/ode/ode-0.9/build/vs2003/ode.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/ode.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/ode.vcproj	(revision 216)
@@ -0,0 +1,890 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="ode"
+	ProjectGUID="{5F0953F1-B966-BA4E-A31A-C002A407FD47}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/ode/DebugDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib"
+				OutputFile="$(OutDir)/ode.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/ode.pdb"
+				SubSystem="2"
+				ImportLibrary="../../lib/DebugDLL/ode.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/ode/ReleaseDLL"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib"
+				OutputFile="$(OutDir)/ode.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="FALSE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/ReleaseDLL/ode.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_DLL"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/ode/DebugLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/ode.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/ode/ReleaseLib"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				StringPooling="TRUE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/ode.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;ODE_LIB"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="include"
+			Filter="">
+			<Filter
+				Name="ode"
+				Filter="">
+				<File
+					RelativePath="..\..\include\ode\collision.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\collision_space.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\collision_trimesh.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\common.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\compatibility.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\config.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\contact.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\error.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\export-dif.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\mass.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\matrix.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\memory.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\misc.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\objects.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\ode.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odecpp.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odecpp_collision.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odemath.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\rotation.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\timer.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="ode"
+			Filter="">
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\ode\src\array.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_kernel.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_space_internal.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_std.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_transform.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_internal.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_util.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\heightfield.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\joint.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\lcp.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mat.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\objects.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\obstack.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\quickstep.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\stack.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\step.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\testing.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\util.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastdot.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastldlt.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastlsolve.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastltsolve.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\array.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\capsule.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_kernel.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_quadtreespace.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_space.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_transform.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_ccylinder.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_distance.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_gimpact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_opcode.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_ray.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_trimesh_new.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_util.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\convex.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\cylinder.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\error.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\export-dif.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\heightfield.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\joint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\lcp.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mass.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mat.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\matrix.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\memory.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\misc.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\obstack.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\ode.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\odemath.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\quickstep.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\ray.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\rotation.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\step.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\stepfast.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\testing.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\timer.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\util.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="GIMPACT"
+			Filter="">
+			<Filter
+				Name="include"
+				Filter="">
+				<Filter
+					Name="GIMPACT"
+					Filter="">
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gimpact.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_boxpruning.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_contact.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_geometry.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_math.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_memory.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_radixsort.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_trimesh.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_capsule_collision.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_collision.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_sphere_collision.h">
+					</File>
+				</Filter>
+			</Filter>
+			<Filter
+				Name="src"
+				Filter="">
+				<File
+					RelativePath="..\..\GIMPACT\src\gimpact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_boxpruning.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_contact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_math.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_memory.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_capsule_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_ray_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_sphere_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_trimesh_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_tri_tri_overlap.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="OPCODE"
+			Filter="">
+			<Filter
+				Name="Ice"
+				Filter="">
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAABB.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAxes.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceBoundingSphere.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceContainer.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceFPU.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceHPoint.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceIndexedTriangle.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceLSS.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix3x3.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix4x4.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMemoryMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceOBB.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePairs.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePlane.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePoint.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePreprocessor.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRandom.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRay.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRevisitedRadix.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceSegment.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriangle.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriList.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTypes.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceUtils.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAABB.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceContainer.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceHPoint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceIndexedTriangle.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix3x3.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix4x4.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceOBB.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePlane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePoint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRandom.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRay.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRevisitedRadix.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceSegment.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriangle.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceUtils.cpp">
+				</File>
+			</Filter>
+			<File
+				RelativePath="..\..\OPCODE\Opcode.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBTree.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BaseModel.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxBoxOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxPruning.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Collider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Common.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_HybridModel.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_IceHook.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_MeshInterface.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Model.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OBBCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OptimizedTree.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Picking.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Settings.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SweepAndPrune.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeBuilders.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TriBoxOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TriTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_VolumeCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\Stdafx.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\Opcode.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBTree.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BaseModel.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxPruning.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Collider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Common.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_HybridModel.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_MeshInterface.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Model.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OBBCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OptimizedTree.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Picking.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SweepAndPrune.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeBuilders.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_VolumeCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\StdAfx.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2003/tests.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2003/tests.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2003/tests.vcproj	(revision 216)
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="tests"
+	ProjectGUID="{65028345-CDF4-B74C-B94F-8F4A0493D8C4}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/tests/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/tests/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/tests/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/tests/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="TRUE"
+				RuntimeTypeInfo="TRUE"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="tests"
+			Filter="">
+			<Filter
+				Name="CppTestHarness"
+				Filter="">
+				<File
+					RelativePath="..\..\tests\CppTestHarness\CheckMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Checks.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\CppTestHarness.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\HTMLTestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\PrintfTestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\SignalTranslator.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Test.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestLauncher.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestResults.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestRunner.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TypedTestLauncher.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\HTMLTestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\PrintfTestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Test.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestLauncher.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestResults.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestRunner.cpp">
+				</File>
+			</Filter>
+			<Filter
+				Name="colliders"
+				Filter="">
+				<File
+					RelativePath="..\..\tests\colliders\box_sphere.cpp">
+				</File>
+			</Filter>
+			<File
+				RelativePath="..\..\tests\main.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_I.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_I.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_I.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_I"
+	ProjectGUID="{D03ABAA3-4C58-674E-B545-4AE8E993A57A}"
+	RootNamespace="demo_I"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/I/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/I/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/I/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/I/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_I.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_I.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_I.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_basket.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_basket.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_basket.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_basket"
+	ProjectGUID="{FE66E49C-CF34-5F4B-B43C-9A0C89185222}"
+	RootNamespace="demo_basket"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/basket/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/basket/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/basket/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/basket/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_basket.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_basket.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_basket.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_boxstack.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_boxstack.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_boxstack.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_boxstack"
+	ProjectGUID="{A71669E5-246A-794A-B2C2-646946E9EE64}"
+	RootNamespace="demo_boxstack"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/boxstack/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/boxstack/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/boxstack/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/boxstack/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_boxstack.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_boxstack.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_boxstack.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_buggy.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_buggy.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_buggy.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_buggy"
+	ProjectGUID="{081B462D-C222-144C-AF0C-384C47BE98D2}"
+	RootNamespace="demo_buggy"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/buggy/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/buggy/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/buggy/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/buggy/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_buggy.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_buggy.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_buggy.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_chain1.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_chain1.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_chain1.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_chain1"
+	ProjectGUID="{D329C439-EF31-4641-9B34-4DE23174C997}"
+	RootNamespace="demo_chain1"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/chain1/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/chain1/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/chain1/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/chain1/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain1.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain1.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_chain1.c">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_chain2.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_chain2.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_chain2.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_chain2"
+	ProjectGUID="{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}"
+	RootNamespace="demo_chain2"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/chain2/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/chain2/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/chain2/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/chain2/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_chain2.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_chain2.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_chain2.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_collision.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_collision.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_collision.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_collision"
+	ProjectGUID="{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}"
+	RootNamespace="demo_collision"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/collision/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/collision/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/collision/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/collision/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_collision.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_collision.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_collision.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_crash.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_crash.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_crash.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_crash"
+	ProjectGUID="{1478BD02-E2D4-1046-AD1C-63E59DD228BC}"
+	RootNamespace="demo_crash"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/crash/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/crash/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/crash/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/crash/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_crash.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_crash.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_crash.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_cyl.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_cyl.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_cyl.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_cyl"
+	ProjectGUID="{EA15C089-307B-8B4A-A598-0E06C82ADB1E}"
+	RootNamespace="demo_cyl"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/cyl/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/cyl/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/cyl/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/cyl/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cyl.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cyl.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_cyl.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_cylvssphere.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_cylvssphere.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_cylvssphere.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_cylvssphere"
+	ProjectGUID="{FA871426-5142-F646-B3D2-3AF70E784D68}"
+	RootNamespace="demo_cylvssphere"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/cylvssphere/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/cylvssphere/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/cylvssphere/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/cylvssphere/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_cylvssphere.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_cylvssphere.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_cylvssphere.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_feedback.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_feedback.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_feedback.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_feedback"
+	ProjectGUID="{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}"
+	RootNamespace="demo_feedback"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/feedback/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/feedback/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/feedback/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/feedback/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_feedback.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_feedback.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_feedback.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_friction.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_friction.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_friction.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_friction"
+	ProjectGUID="{BAD97423-A545-814E-8CCC-32603D25E6D4}"
+	RootNamespace="demo_friction"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/friction/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/friction/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/friction/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/friction/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_friction.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_friction.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_friction.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_heightfield.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_heightfield.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_heightfield.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_heightfield"
+	ProjectGUID="{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}"
+	RootNamespace="demo_heightfield"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/heightfield/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/heightfield/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/heightfield/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/heightfield/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_heightfield.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_heightfield.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_heightfield.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_hinge.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_hinge.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_hinge.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_hinge"
+	ProjectGUID="{DFD3F85E-944E-7740-A29F-715891AF8262}"
+	RootNamespace="demo_hinge"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/hinge/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/hinge/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/hinge/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/hinge/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_hinge.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_hinge.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_hinge.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_joints.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_joints.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_joints.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_joints"
+	ProjectGUID="{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}"
+	RootNamespace="demo_joints"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/joints/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/joints/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/joints/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/joints/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_joints.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_joints.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_joints.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_motor.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_motor.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_motor.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_motor"
+	ProjectGUID="{D63DCF21-8421-044C-910F-9758DFF417D0}"
+	RootNamespace="demo_motor"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/motor/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/motor/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/motor/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/motor/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_motor.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_motor.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_motor.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_moving_trimesh.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_moving_trimesh.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_moving_trimesh.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_moving_trimesh"
+	ProjectGUID="{BE3117C9-B067-0A4B-920D-7F3C00374BA0}"
+	RootNamespace="demo_moving_trimesh"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/moving_trimesh/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/moving_trimesh/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/moving_trimesh/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/moving_trimesh/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_moving_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_moving_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_moving_trimesh.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_ode.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_ode.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_ode.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_ode"
+	ProjectGUID="{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}"
+	RootNamespace="demo_ode"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/ode/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/ode/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/ode/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/ode/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_ode.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_ode.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_ode.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_plane2d.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_plane2d.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_plane2d.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_plane2d"
+	ProjectGUID="{BCF62E98-514B-254D-95C5-CEBF06A37108}"
+	RootNamespace="demo_plane2d"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/plane2d/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/plane2d/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/plane2d/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/plane2d/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_plane2d.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_plane2d.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_plane2d.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_slider.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_slider.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_slider.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_slider"
+	ProjectGUID="{B8043AEB-91BD-4D49-B580-D480DC1B979F}"
+	RootNamespace="demo_slider"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/slider/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/slider/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/slider/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/slider/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_slider.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_slider.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_slider.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_space.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_space.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_space.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_space"
+	ProjectGUID="{6DCB0D01-0638-0244-BEB9-A313999D14E9}"
+	RootNamespace="demo_space"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/space/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/space/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/space/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/space/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_space.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_space_stress.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_space_stress.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_space_stress.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_space_stress"
+	ProjectGUID="{29A4883C-6553-4D48-8FFC-10382F07DA72}"
+	RootNamespace="demo_space_stress"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/space_stress/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/space_stress/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/space_stress/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/space_stress/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_space_stress.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_space_stress.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_space_stress.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_step.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_step.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_step.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_step"
+	ProjectGUID="{D1B53AFE-F148-194C-B3A1-8386C9B25359}"
+	RootNamespace="demo_step"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/step/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/step/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/step/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/step/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_step.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_step.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_step.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/demo_trimesh.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/demo_trimesh.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/demo_trimesh.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="demo_trimesh"
+	ProjectGUID="{13D33F5C-1C2C-D740-A28A-BCFD15616E75}"
+	RootNamespace="demo_trimesh"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/trimesh/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib ../../lib/DebugDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/trimesh/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib ../../lib/ReleaseDLL/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/trimesh/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib ../../lib/DebugLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/trimesh/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib ../../lib/ReleaseLib/drawstuff.lib user32.lib winmm.lib gdi32.lib opengl32.lib glu32.lib"
+				OutputFile="$(OutDir)/demo_trimesh.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/demo_trimesh.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="demo"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\demo\demo_trimesh.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/drawstuff.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/drawstuff.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/drawstuff.vcproj	(revision 216)
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="drawstuff"
+	ProjectGUID="{B855BC68-59AE-BD44-82BB-88183332A6D9}"
+	RootNamespace="drawstuff"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/drawstuff/DebugDLL"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_DLL;USRDLL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_DLL;USRDLL"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib opengl32.lib glu32.lib winmm.lib gdi32.lib"
+				OutputFile="$(OutDir)/drawstuff.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/drawstuff.pdb"
+				SubSystem="2"
+				ImportLibrary="../../lib/DebugDLL/drawstuff.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/drawstuff/ReleaseDLL"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_DLL;USRDLL"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_DLL;USRDLL"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib opengl32.lib glu32.lib winmm.lib gdi32.lib"
+				OutputFile="$(OutDir)/drawstuff.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="false"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/ReleaseDLL/drawstuff.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/drawstuff/DebugLib"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_LIB"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_LIB"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/drawstuff.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/drawstuff/ReleaseLib"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="../../include"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_LIB"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;DS_LIB"
+				AdditionalIncludeDirectories="../../include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/drawstuff.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="include"
+			Filter=""
+			>
+			<Filter
+				Name="drawstuff"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\include\drawstuff\drawstuff.h">
+				</File>
+				<File
+					RelativePath="..\..\include\drawstuff\version.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="drawstuff"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\drawstuff\src\internal.h">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\drawstuff.cpp">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\resource.h">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\resources.rc">
+				</File>
+				<File
+					RelativePath="..\..\drawstuff\src\windows.cpp">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/ode.sln
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/ode.sln	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/ode.sln	(revision 216)
@@ -0,0 +1,388 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ode", "./ode.vcproj", "{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "drawstuff", "./drawstuff.vcproj", "{B855BC68-59AE-BD44-82BB-88183332A6D9}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_boxstack", "./demo_boxstack.vcproj", "{A71669E5-246A-794A-B2C2-646946E9EE64}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_buggy", "./demo_buggy.vcproj", "{081B462D-C222-144C-AF0C-384C47BE98D2}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_chain1", "./demo_chain1.vcproj", "{D329C439-EF31-4641-9B34-4DE23174C997}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_chain2", "./demo_chain2.vcproj", "{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_collision", "./demo_collision.vcproj", "{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_crash", "./demo_crash.vcproj", "{1478BD02-E2D4-1046-AD1C-63E59DD228BC}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_feedback", "./demo_feedback.vcproj", "{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_friction", "./demo_friction.vcproj", "{BAD97423-A545-814E-8CCC-32603D25E6D4}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_heightfield", "./demo_heightfield.vcproj", "{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_hinge", "./demo_hinge.vcproj", "{DFD3F85E-944E-7740-A29F-715891AF8262}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_I", "./demo_I.vcproj", "{D03ABAA3-4C58-674E-B545-4AE8E993A57A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_joints", "./demo_joints.vcproj", "{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_motor", "./demo_motor.vcproj", "{D63DCF21-8421-044C-910F-9758DFF417D0}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_ode", "./demo_ode.vcproj", "{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_plane2d", "./demo_plane2d.vcproj", "{BCF62E98-514B-254D-95C5-CEBF06A37108}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_slider", "./demo_slider.vcproj", "{B8043AEB-91BD-4D49-B580-D480DC1B979F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_space", "./demo_space.vcproj", "{6DCB0D01-0638-0244-BEB9-A313999D14E9}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_space_stress", "./demo_space_stress.vcproj", "{29A4883C-6553-4D48-8FFC-10382F07DA72}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_step", "./demo_step.vcproj", "{D1B53AFE-F148-194C-B3A1-8386C9B25359}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_basket", "./demo_basket.vcproj", "{FE66E49C-CF34-5F4B-B43C-9A0C89185222}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_cyl", "./demo_cyl.vcproj", "{EA15C089-307B-8B4A-A598-0E06C82ADB1E}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_moving_trimesh", "./demo_moving_trimesh.vcproj", "{BE3117C9-B067-0A4B-920D-7F3C00374BA0}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_trimesh", "./demo_trimesh.vcproj", "{13D33F5C-1C2C-D740-A28A-BCFD15616E75}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_cylvssphere", "./demo_cylvssphere.vcproj", "{FA871426-5142-F646-B3D2-3AF70E784D68}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+		{B855BC68-59AE-BD44-82BB-88183332A6D9} = {B855BC68-59AE-BD44-82BB-88183332A6D9}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "./tests.vcproj", "{EA829A28-B1B2-1345-98B9-897763B937AF}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE} = {2A8430BA-889E-EE4A-B1E3-A3231F6816EE}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		DebugDLL|Win32 = DebugDLL|Win32
+		ReleaseDLL|Win32 = ReleaseDLL|Win32
+		DebugLib|Win32 = DebugLib|Win32
+		ReleaseLib|Win32 = ReleaseLib|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{B855BC68-59AE-BD44-82BB-88183332A6D9}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{A71669E5-246A-794A-B2C2-646946E9EE64}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{081B462D-C222-144C-AF0C-384C47BE98D2}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{D329C439-EF31-4641-9B34-4DE23174C997}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{B27B11A1-72EB-8149-ABF2-63A9D7E05CA2}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{9C1C9F02-11C4-514C-AF5C-1CB45A31E1A9}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{1478BD02-E2D4-1046-AD1C-63E59DD228BC}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{B8BC0F67-D7F2-7F4E-8314-5EAAECCD671C}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{BAD97423-A545-814E-8CCC-32603D25E6D4}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{5DDFAAD0-23AC-9A42-AA5E-31B8E8E68CA0}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{DFD3F85E-944E-7740-A29F-715891AF8262}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{D03ABAA3-4C58-674E-B545-4AE8E993A57A}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{0F6BA7D9-8481-D34C-9CA7-C69AC15DCE4C}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{D63DCF21-8421-044C-910F-9758DFF417D0}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{B8D35A81-5E45-744C-BABD-BFCAA4CBF36E}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{BCF62E98-514B-254D-95C5-CEBF06A37108}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{B8043AEB-91BD-4D49-B580-D480DC1B979F}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{6DCB0D01-0638-0244-BEB9-A313999D14E9}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{29A4883C-6553-4D48-8FFC-10382F07DA72}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{D1B53AFE-F148-194C-B3A1-8386C9B25359}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{FE66E49C-CF34-5F4B-B43C-9A0C89185222}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{EA15C089-307B-8B4A-A598-0E06C82ADB1E}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{BE3117C9-B067-0A4B-920D-7F3C00374BA0}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{13D33F5C-1C2C-D740-A28A-BCFD15616E75}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{FA871426-5142-F646-B3D2-3AF70E784D68}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.DebugDLL|Win32.Build.0 = DebugDLL|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.DebugLib|Win32.ActiveCfg = DebugLib|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.DebugLib|Win32.Build.0 = DebugLib|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.ReleaseLib|Win32.ActiveCfg = ReleaseLib|Win32
+		{EA829A28-B1B2-1345-98B9-897763B937AF}.ReleaseLib|Win32.Build.0 = ReleaseLib|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: /code/branches/ode/ode-0.9/build/vs2005/ode.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/ode.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/ode.vcproj	(revision 216)
@@ -0,0 +1,1017 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="ode"
+	ProjectGUID="{2A8430BA-889E-EE4A-B1E3-A3231F6816EE}"
+	RootNamespace="ode"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/ode/DebugDLL"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_DLL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_DLL"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib"
+				OutputFile="$(OutDir)/ode.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/ode.pdb"
+				SubSystem="2"
+				ImportLibrary="../../lib/DebugDLL/ode.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/ode/ReleaseDLL"
+			ConfigurationType="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_DLL"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_DLL"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="user32.lib"
+				OutputFile="$(OutDir)/ode.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="false"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/ReleaseDLL/ode.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/ode/DebugLib"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_LIB"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_LIB"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/ode.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/ode/ReleaseLib"
+			ConfigurationType="4"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_LIB"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;ODE_LIB"
+				AdditionalIncludeDirectories="../../include;../../OPCODE;../../GIMPACT/include"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/ode.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="include"
+			Filter=""
+			>
+			<Filter
+				Name="ode"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\include\ode\collision.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\collision_space.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\collision_trimesh.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\common.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\compatibility.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\config.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\contact.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\error.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\export-dif.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\mass.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\matrix.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\memory.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\misc.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\objects.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\ode.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odecpp.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odecpp_collision.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\odemath.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\rotation.h">
+				</File>
+				<File
+					RelativePath="..\..\include\ode\timer.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="ode"
+			Filter=""
+			>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\ode\src\array.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_kernel.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_space_internal.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_std.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_transform.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_internal.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_util.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\heightfield.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\joint.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\lcp.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mat.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\objects.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\obstack.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\quickstep.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\stack.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\step.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\testing.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\util.h">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastdot.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastldlt.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastlsolve.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\fastltsolve.c">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\array.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\capsule.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_cylinder_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_kernel.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_quadtreespace.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_space.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_transform.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_box.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_ccylinder.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_distance.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_gimpact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_opcode.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_ray.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_trimesh_trimesh_new.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\collision_util.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\convex.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\cylinder.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\error.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\export-dif.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\heightfield.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\joint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\lcp.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mass.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\mat.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\matrix.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\memory.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\misc.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\obstack.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\ode.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\odemath.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\plane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\quickstep.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\ray.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\rotation.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\sphere.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\step.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\stepfast.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\testing.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\timer.cpp">
+				</File>
+				<File
+					RelativePath="..\..\ode\src\util.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="GIMPACT"
+			Filter=""
+			>
+			<Filter
+				Name="include"
+				Filter=""
+				>
+				<Filter
+					Name="GIMPACT"
+					Filter=""
+					>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gimpact.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_boxpruning.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_contact.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_geometry.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_math.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_memory.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_radixsort.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_trimesh.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_capsule_collision.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_collision.h">
+					</File>
+					<File
+						RelativePath="..\..\GIMPACT\include\GIMPACT\gim_tri_sphere_collision.h">
+					</File>
+				</Filter>
+			</Filter>
+			<Filter
+				Name="src"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\GIMPACT\src\gimpact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_boxpruning.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_contact.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_math.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_memory.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_capsule_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_ray_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_sphere_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_trimesh_trimesh_collision.cpp">
+				</File>
+				<File
+					RelativePath="..\..\GIMPACT\src\gim_tri_tri_overlap.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="OPCODE"
+			Filter=""
+			>
+			<Filter
+				Name="Ice"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAABB.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAxes.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceBoundingSphere.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceContainer.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceFPU.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceHPoint.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceIndexedTriangle.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceLSS.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix3x3.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix4x4.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMemoryMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceOBB.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePairs.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePlane.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePoint.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePreprocessor.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRandom.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRay.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRevisitedRadix.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceSegment.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriangle.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriList.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTypes.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceUtils.h">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceAABB.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceContainer.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceHPoint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceIndexedTriangle.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix3x3.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceMatrix4x4.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceOBB.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePlane.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IcePoint.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRandom.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRay.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceRevisitedRadix.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceSegment.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceTriangle.cpp">
+				</File>
+				<File
+					RelativePath="..\..\OPCODE\Ice\IceUtils.cpp">
+				</File>
+			</Filter>
+			<File
+				RelativePath="..\..\OPCODE\Opcode.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBTree.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BaseModel.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxBoxOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxPruning.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Collider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Common.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_HybridModel.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_IceHook.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_MeshInterface.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Model.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OBBCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OptimizedTree.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Picking.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Settings.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereAABBOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SweepAndPrune.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeBuilders.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TriBoxOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TriTriOverlap.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_VolumeCollider.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\Stdafx.h">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\Opcode.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_AABBTree.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BaseModel.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_BoxPruning.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Collider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Common.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_HybridModel.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_LSSCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_MeshInterface.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Model.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OBBCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_OptimizedTree.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_Picking.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_PlanesCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_RayCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SphereCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_SweepAndPrune.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeBuilders.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_TreeCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\OPC_VolumeCollider.cpp">
+			</File>
+			<File
+				RelativePath="..\..\OPCODE\StdAfx.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/build/vs2005/tests.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/build/vs2005/tests.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/build/vs2005/tests.vcproj	(revision 216)
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="tests"
+	ProjectGUID="{EA829A28-B1B2-1345-98B9-897763B937AF}"
+	RootNamespace="tests"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="DebugDLL|Win32"
+			OutputDirectory="../../lib/DebugDLL"
+			IntermediateDirectory="obj/tests/DebugDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugDLL/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseDLL|Win32"
+			OutputDirectory="../../lib/ReleaseDLL"
+			IntermediateDirectory="obj/tests/ReleaseDLL"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseDLL/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseDLL"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="DebugLib|Win32"
+			OutputDirectory="../../lib/DebugLib"
+			IntermediateDirectory="obj/tests/DebugLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/DebugLib/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/DebugLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="ReleaseLib|Win32"
+			OutputDirectory="../../lib/ReleaseLib"
+			IntermediateDirectory="obj/tests/ReleaseLib"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE"
+				AdditionalIncludeDirectories="../../include;../../tests/CppTestHarness"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="../../lib/ReleaseLib/ode.lib"
+				OutputFile="$(OutDir)/tests.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib/ReleaseLib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/tests.pdb"
+				SubSystem="1"
+				EntryPointSymbol="mainCRTStartup"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="tests"
+			Filter=""
+			>
+			<Filter
+				Name="CppTestHarness"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\CheckMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Checks.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\CppTestHarness.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\HTMLTestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\PrintfTestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\SignalTranslator.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Test.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestLauncher.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestMacros.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestReporter.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestResults.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestRunner.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TypedTestLauncher.h">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\HTMLTestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\PrintfTestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\Test.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestLauncher.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestReporter.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestResults.cpp">
+				</File>
+				<File
+					RelativePath="..\..\tests\CppTestHarness\TestRunner.cpp">
+				</File>
+			</Filter>
+			<Filter
+				Name="colliders"
+				Filter=""
+				>
+				<File
+					RelativePath="..\..\tests\colliders\box_sphere.cpp">
+				</File>
+			</Filter>
+			<File
+				RelativePath="..\..\tests\main.cpp">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/config.guess
===================================================================
--- /code/branches/ode/ode-0.9/config.guess	(revision 216)
+++ /code/branches/ode/ode-0.9/config.guess	(revision 216)
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2006-07-02'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    x86:Interix*:[3456]*)
+	echo i586-pc-interix${UNAME_RELEASE}
+	exit ;;
+    EM64T:Interix*:[3456]*)
+	echo x86_64-unknown-interix${UNAME_RELEASE}
+	exit ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /code/branches/ode/ode-0.9/config.sub
===================================================================
--- /code/branches/ode/ode-0.9/config.sub	(revision 216)
+++ /code/branches/ode/ode-0.9/config.sub	(revision 216)
@@ -0,0 +1,1616 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
+
+timestamp='2006-09-20'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16c)
+		basic_machine=cr16c-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /code/branches/ode/ode-0.9/configure
===================================================================
--- /code/branches/ode/ode-0.9/configure	(revision 216)
+++ /code/branches/ode/ode-0.9/configure	(revision 216)
@@ -0,0 +1,14308 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for ODE 0.9.0.
+#
+# Report bugs to <ode@ode.org>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes && 	 (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	   done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+	 # Try only shells that exist, to save several forks.
+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		{ ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+	       as_have_required=yes
+	       if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+	case $1 in
+        -*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='ODE'
+PACKAGE_TARNAME='ode'
+PACKAGE_VERSION='0.9.0'
+PACKAGE_STRING='ODE 0.9.0'
+PACKAGE_BUGREPORT='ode@ode.org'
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+am__isrc
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+CPP
+GREP
+EGREP
+XMKMF
+X_CFLAGS
+X_PRE_LIBS
+X_LIBS
+X_EXTRA_LIBS
+ODE_CURRENT
+ODE_REVISION
+ODE_AGE
+ODE_RELEASE
+ODE_SONAME
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+WINDRES
+ac_ct_WINDRES
+RANLIB
+USE_SONAME_TRUE
+USE_SONAME_FALSE
+ENABLE_DEMOS_TRUE
+ENABLE_DEMOS_FALSE
+ARCHFLAGS
+OPCODE_TRUE
+OPCODE_FALSE
+GIMPACT_TRUE
+GIMPACT_FALSE
+TRIMESH_TRUE
+TRIMESH_FALSE
+X86_64_SYSTEM_TRUE
+X86_64_SYSTEM_FALSE
+WIN32_TRUE
+WIN32_FALSE
+X11_TRUE
+X11_FALSE
+OSX_TRUE
+OSX_FALSE
+DRAWSTUFF
+so_ext
+SHARED_LDFLAGS
+GL_LIBS
+TOPDIR
+ALLOCA
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+XMKMF
+CXX
+CXXFLAGS
+CCC'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$0" : 'X\(//\)[^/]' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures ODE 0.9.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+			  [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+			  [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/ode]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+X features:
+  --x-includes=DIR    X include files are in DIR
+  --x-libraries=DIR   X library files are in DIR
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of ODE 0.9.0:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --enable-soname         Configure ODE shared library to set the soname field
+                          on ELF files
+  --enable-demos          build tests
+  --disable-gyroscopic    Configure ODE to work without gyroscopic term (may
+                          improve stability)
+  --enable-double-precision
+                          Configure ODE to work with double precision, if not
+                          specified, single precision is used
+  --enable-release        build a release library with -fomit-frame-pointer
+                          and -ffast-math
+  --enable-debug          Add debug symbols to the library with -g
+  --enable-gprof          enable profiling with gprof
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-x                use the X Window System
+  --with-arch=arch        build for $arch, where arch is any of the -march
+                          flags passed to gcc, without the -march, for example
+                          --with-arch=pentium3
+  --with-trimesh=opcode|gimpact|none
+                          use the specified system for trimesh support.
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  XMKMF       Path to xmkmf, Makefile generator for X Window System
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <ode@ode.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+ODE configure 0.9.0
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ODE $as_me 0.9.0, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+	"$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+	ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ODE_CURRENT=0
+ODE_REVISION=9
+ODE_AGE=0
+ODE_RELEASE=$ODE_CURRENT.$ODE_REVISION.$ODE_AGE
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+am__api_version='1.10'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  SET_MAKE=
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=ODE
+ VERSION=$ODE_RELEASE
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ac_config_headers="$ac_config_headers include/ode/config.h"
+
+CFLAGS=
+CXXFLAGS=
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+	@echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC"   am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if  ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+	&& BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long int l;
+    char c[sizeof (long int)];
+  } u;
+  u.l = 1;
+  return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for X" >&5
+echo $ECHO_N "checking for X... $ECHO_C" >&6; }
+
+
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then
+  withval=$with_x;
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+  # The user explicitly disabled X.
+  have_x=disabled
+else
+  case $x_includes,$x_libraries in #(
+    *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5
+echo "$as_me: error: Cannot use X directory names containing '" >&2;}
+   { (exit 1); exit 1; }; };; #(
+    *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=no ac_x_libraries=no
+rm -f -r conftest.dir
+if mkdir conftest.dir; then
+  cd conftest.dir
+  cat >Imakefile <<'_ACEOF'
+incroot:
+	@echo incroot='${INCROOT}'
+usrlibdir:
+	@echo usrlibdir='${USRLIBDIR}'
+libdir:
+	@echo libdir='${LIBDIR}'
+_ACEOF
+  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
+    # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+    for ac_var in incroot usrlibdir libdir; do
+      eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+    done
+    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+    for ac_extension in a so sl; do
+      if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+	 test -f "$ac_im_libdir/libX11.$ac_extension"; then
+	ac_im_usrlibdir=$ac_im_libdir; break
+      fi
+    done
+    # Screen out bogus values from the imake configuration.  They are
+    # bogus both because they are the default anyway, and because
+    # using them would break gcc on systems where it needs fixed includes.
+    case $ac_im_incroot in
+	/usr/include) ac_x_includes= ;;
+	*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
+    esac
+    case $ac_im_usrlibdir in
+	/usr/lib | /lib) ;;
+	*) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
+    esac
+  fi
+  cd ..
+  rm -f -r conftest.dir
+fi
+
+# Standard set of common directories for X headers.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ac_x_header_dirs='
+/usr/X11/include
+/usr/X11R6/include
+/usr/X11R5/include
+/usr/X11R4/include
+
+/usr/include/X11
+/usr/include/X11R6
+/usr/include/X11R5
+/usr/include/X11R4
+
+/usr/local/X11/include
+/usr/local/X11R6/include
+/usr/local/X11R5/include
+/usr/local/X11R4/include
+
+/usr/local/include/X11
+/usr/local/include/X11R6
+/usr/local/include/X11R5
+/usr/local/include/X11R4
+
+/usr/X386/include
+/usr/x386/include
+/usr/XFree86/include/X11
+
+/usr/include
+/usr/local/include
+/usr/unsupported/include
+/usr/athena/include
+/usr/local/x11r5/include
+/usr/lpp/Xamples/include
+
+/usr/openwin/include
+/usr/openwin/share/include'
+
+if test "$ac_x_includes" = no; then
+  # Guess where to find include files, by looking for Xlib.h.
+  # First, try using that file with no special directory specified.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  for ac_dir in $ac_x_header_dirs; do
+  if test -r "$ac_dir/X11/Xlib.h"; then
+    ac_x_includes=$ac_dir
+    break
+  fi
+done
+fi
+
+rm -f conftest.err conftest.$ac_ext
+fi # $ac_x_includes = no
+
+if test "$ac_x_libraries" = no; then
+  # Check for the libraries.
+  # See if we find them without any special options.
+  # Don't add to $LIBS permanently.
+  ac_save_LIBS=$LIBS
+  LIBS="-lX11 $LIBS"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+int
+main ()
+{
+XrmInitialize ()
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  LIBS=$ac_save_LIBS
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	LIBS=$ac_save_LIBS
+for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+do
+  # Don't even attempt the hair of trying to link an X program!
+  for ac_extension in a so sl; do
+    if test -r "$ac_dir/libX11.$ac_extension"; then
+      ac_x_libraries=$ac_dir
+      break 2
+    fi
+  done
+done
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi # $ac_x_libraries = no
+
+case $ac_x_includes,$ac_x_libraries in #(
+  no,* | *,no | *\'*)
+    # Didn't find X, or a directory has "'" in its name.
+    ac_cv_have_x="have_x=no";; #(
+  *)
+    # Record where we found X for the cache.
+    ac_cv_have_x="have_x=yes\
+	ac_x_includes='$ac_x_includes'\
+	ac_x_libraries='$ac_x_libraries'"
+esac
+fi
+;; #(
+    *) have_x=yes;;
+  esac
+  eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+  { echo "$as_me:$LINENO: result: $have_x" >&5
+echo "${ECHO_T}$have_x" >&6; }
+  no_x=yes
+else
+  # If each of the values was on the command line, it overrides each guess.
+  test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+  test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+  # Update the cache value to reflect the command line values.
+  ac_cv_have_x="have_x=yes\
+	ac_x_includes='$x_includes'\
+	ac_x_libraries='$x_libraries'"
+  { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5
+echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; }
+fi
+
+if test "$no_x" = yes; then
+  # Not all programs may use this symbol, but it does not hurt to define it.
+
+cat >>confdefs.h <<\_ACEOF
+#define X_DISPLAY_MISSING 1
+_ACEOF
+
+  X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+  if test -n "$x_includes"; then
+    X_CFLAGS="$X_CFLAGS -I$x_includes"
+  fi
+
+  # It would also be nice to do this for all -L options, not just this one.
+  if test -n "$x_libraries"; then
+    X_LIBS="$X_LIBS -L$x_libraries"
+    # For Solaris; some versions of Sun CC require a space after -R and
+    # others require no space.  Words are not sufficient . . . .
+    { echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5
+echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6; }
+    ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
+    ac_xsave_c_werror_flag=$ac_c_werror_flag
+    ac_c_werror_flag=yes
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+       X_LIBS="$X_LIBS -R$x_libraries"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	LIBS="$ac_xsave_LIBS -R $x_libraries"
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+	  X_LIBS="$X_LIBS -R $x_libraries"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: result: neither works" >&5
+echo "${ECHO_T}neither works" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+    ac_c_werror_flag=$ac_xsave_c_werror_flag
+    LIBS=$ac_xsave_LIBS
+  fi
+
+  # Check for system-dependent libraries X programs must link with.
+  # Do this before checking for the system-independent R6 libraries
+  # (-lICE), since we may need -lsocket or whatever for X linking.
+
+  if test "$ISC" = yes; then
+    X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+  else
+    # Martyn Johnson says this is needed for Ultrix, if the X
+    # libraries were built with DECnet support.  And Karl Berry says
+    # the Alpha needs dnet_stub (dnet does not exist).
+    ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XOpenDisplay ();
+int
+main ()
+{
+return XOpenDisplay ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5
+echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dnet_dnet_ntoa=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dnet_dnet_ntoa=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6; }
+if test $ac_cv_lib_dnet_dnet_ntoa = yes; then
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+fi
+
+    if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+      { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5
+echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet_stub  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dnet_stub_dnet_ntoa=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dnet_stub_dnet_ntoa=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; }
+if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+fi
+
+    fi
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+    LIBS="$ac_xsave_LIBS"
+
+    # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+    # to get the SysV transport functions.
+    # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4)
+    # needs -lnsl.
+    # The nsl library prevents programs from opening the X display
+    # on Irix 5.2, according to T.E. Dickey.
+    # The functions gethostbyname, getservbyname, and inet_addr are
+    # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking.
+    { echo "$as_me:$LINENO: checking for gethostbyname" >&5
+echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6; }
+if test "${ac_cv_func_gethostbyname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define gethostbyname to an innocuous variant, in case <limits.h> declares gethostbyname.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define gethostbyname innocuous_gethostbyname
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char gethostbyname (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef gethostbyname
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_gethostbyname || defined __stub___gethostbyname
+choke me
+#endif
+
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_gethostbyname=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_gethostbyname=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6; }
+
+    if test $ac_cv_func_gethostbyname = no; then
+      { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5
+echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_nsl_gethostbyname=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_nsl_gethostbyname=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test $ac_cv_lib_nsl_gethostbyname = yes; then
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+fi
+
+      if test $ac_cv_lib_nsl_gethostbyname = no; then
+	{ echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5
+echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6; }
+if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_bsd_gethostbyname=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_bsd_gethostbyname=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6; }
+if test $ac_cv_lib_bsd_gethostbyname = yes; then
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
+fi
+
+      fi
+    fi
+
+    # lieder@skyler.mavd.honeywell.com says without -lsocket,
+    # socket/setsockopt and other routines are undefined under SCO ODT
+    # 2.0.  But -lsocket is broken on IRIX 5.2 (and is not necessary
+    # on later versions), says Simon Leinen: it contains gethostby*
+    # variants that don't use the name server (or something).  -lsocket
+    # must be given before -lnsl if both are needed.  We assume that
+    # if connect needs -lnsl, so does gethostbyname.
+    { echo "$as_me:$LINENO: checking for connect" >&5
+echo $ECHO_N "checking for connect... $ECHO_C" >&6; }
+if test "${ac_cv_func_connect+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define connect to an innocuous variant, in case <limits.h> declares connect.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define connect innocuous_connect
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char connect (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef connect
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char connect ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_connect || defined __stub___connect
+choke me
+#endif
+
+int
+main ()
+{
+return connect ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_connect=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_connect=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5
+echo "${ECHO_T}$ac_cv_func_connect" >&6; }
+
+    if test $ac_cv_func_connect = no; then
+      { echo "$as_me:$LINENO: checking for connect in -lsocket" >&5
+echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6; }
+if test "${ac_cv_lib_socket_connect+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char connect ();
+int
+main ()
+{
+return connect ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_socket_connect=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_socket_connect=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6; }
+if test $ac_cv_lib_socket_connect = yes; then
+  X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+fi
+
+    fi
+
+    # Guillermo Gomez says -lposix is necessary on A/UX.
+    { echo "$as_me:$LINENO: checking for remove" >&5
+echo $ECHO_N "checking for remove... $ECHO_C" >&6; }
+if test "${ac_cv_func_remove+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define remove to an innocuous variant, in case <limits.h> declares remove.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define remove innocuous_remove
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char remove (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef remove
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char remove ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_remove || defined __stub___remove
+choke me
+#endif
+
+int
+main ()
+{
+return remove ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_remove=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_remove=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5
+echo "${ECHO_T}$ac_cv_func_remove" >&6; }
+
+    if test $ac_cv_func_remove = no; then
+      { echo "$as_me:$LINENO: checking for remove in -lposix" >&5
+echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6; }
+if test "${ac_cv_lib_posix_remove+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lposix  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char remove ();
+int
+main ()
+{
+return remove ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_posix_remove=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_posix_remove=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5
+echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6; }
+if test $ac_cv_lib_posix_remove = yes; then
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+fi
+
+    fi
+
+    # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+    { echo "$as_me:$LINENO: checking for shmat" >&5
+echo $ECHO_N "checking for shmat... $ECHO_C" >&6; }
+if test "${ac_cv_func_shmat+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define shmat to an innocuous variant, in case <limits.h> declares shmat.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define shmat innocuous_shmat
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shmat (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shmat
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shmat ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_shmat || defined __stub___shmat
+choke me
+#endif
+
+int
+main ()
+{
+return shmat ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_shmat=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_shmat=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5
+echo "${ECHO_T}$ac_cv_func_shmat" >&6; }
+
+    if test $ac_cv_func_shmat = no; then
+      { echo "$as_me:$LINENO: checking for shmat in -lipc" >&5
+echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ipc_shmat+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lipc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shmat ();
+int
+main ()
+{
+return shmat ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_ipc_shmat=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_ipc_shmat=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5
+echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6; }
+if test $ac_cv_lib_ipc_shmat = yes; then
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+fi
+
+    fi
+  fi
+
+  # Check for libraries that X11R6 Xt/Xaw programs need.
+  ac_save_LDFLAGS=$LDFLAGS
+  test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+  # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+  # check for ICE first), but we must link in the order -lSM -lICE or
+  # we get undefined symbols.  So assume we have SM if we have ICE.
+  # These have to be linked with before -lX11, unlike the other
+  # libraries we check for below, so use a different variable.
+  # John Interrante, Karl Berry
+  { echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5
+echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char IceConnectionNumber ();
+int
+main ()
+{
+return IceConnectionNumber ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_ICE_IceConnectionNumber=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_ICE_IceConnectionNumber=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
+echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6; }
+if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then
+  X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+fi
+
+  LDFLAGS=$ac_save_LDFLAGS
+
+fi
+
+
+ODE_SONAME=libode.so.$ODE_CURRENT
+
+
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  SET_MAKE=
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CXXFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	    break 3
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in windres
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_WINDRES+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$WINDRES"; then
+  ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_WINDRES="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+WINDRES=$ac_cv_prog_WINDRES
+if test -n "$WINDRES"; then
+  { echo "$as_me:$LINENO: result: $WINDRES" >&5
+echo "${ECHO_T}$WINDRES" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$WINDRES" && break
+  done
+fi
+if test -z "$WINDRES"; then
+  ac_ct_WINDRES=$WINDRES
+  for ac_prog in windres
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_WINDRES+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_WINDRES"; then
+  ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_WINDRES="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES
+if test -n "$ac_ct_WINDRES"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_WINDRES" >&5
+echo "${ECHO_T}$ac_ct_WINDRES" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_WINDRES" && break
+done
+
+  if test "x$ac_ct_WINDRES" = x; then
+    WINDRES=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    WINDRES=$ac_ct_WINDRES
+  fi
+fi
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_inline=$ac_kw
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for working volatile" >&5
+echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; }
+if test "${ac_cv_c_volatile+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_volatile=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_c_volatile=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_volatile" >&5
+echo "${ECHO_T}$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define volatile
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for stdbool.h that conforms to C99" >&5
+echo $ECHO_N "checking for stdbool.h that conforms to C99... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdbool_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdbool.h>
+#ifndef bool
+ "error: bool is not defined"
+#endif
+#ifndef false
+ "error: false is not defined"
+#endif
+#if false
+ "error: false is not 0"
+#endif
+#ifndef true
+ "error: true is not defined"
+#endif
+#if true != 1
+ "error: true is not 1"
+#endif
+#ifndef __bool_true_false_are_defined
+ "error: __bool_true_false_are_defined is not defined"
+#endif
+
+	struct s { _Bool s: 1; _Bool t; } s;
+
+	char a[true == 1 ? 1 : -1];
+	char b[false == 0 ? 1 : -1];
+	char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+	char d[(bool) 0.5 == true ? 1 : -1];
+	bool e = &s;
+	char f[(_Bool) 0.0 == false ? 1 : -1];
+	char g[true];
+	char h[sizeof (_Bool)];
+	char i[sizeof s.t];
+	enum { j = false, k = true, l = false * true, m = true * 256 };
+	_Bool n[m];
+	char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+	char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+#	if defined __xlc__ || defined __GNUC__
+	 /* Catch a bug in IBM AIX xlc compiler version 6.0.0.0
+	    reported by James Lemley on 2005-10-05; see
+	    http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html
+	    This test is not quite right, since xlc is allowed to
+	    reject this program, as the initializer for xlcbug is
+	    not one of the forms that C requires support for.
+	    However, doing the test right would require a runtime
+	    test, and that would make cross-compilation harder.
+	    Let us hope that IBM fixes the xlc bug, and also adds
+	    support for this kind of constant expression.  In the
+	    meantime, this test will reject xlc, which is OK, since
+	    our stdbool.h substitute should suffice.  We also test
+	    this with GCC, where it should work, to detect more
+	    quickly whether someone messes up the test in the
+	    future.  */
+	 char digs[] = "0123456789";
+	 int xlcbug = 1 / (&(digs + 5)[-2 + (bool) 1] == &digs[4] ? 1 : -1);
+#	endif
+	/* Catch a bug in an HP-UX C compiler.  See
+	   http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+	   http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+	 */
+	_Bool q = true;
+	_Bool *pq = &q;
+
+int
+main ()
+{
+
+	*pq |= q;
+	*pq |= ! q;
+	/* Refer to every declared value, to avoid compiler optimizations.  */
+	return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+		+ !m + !n + !o + !p + !q + !pq);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdbool_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdbool_h=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6; }
+{ echo "$as_me:$LINENO: checking for _Bool" >&5
+echo $ECHO_N "checking for _Bool... $ECHO_C" >&6; }
+if test "${ac_cv_type__Bool+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef _Bool ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type__Bool=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type__Bool=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5
+echo "${ECHO_T}$ac_cv_type__Bool" >&6; }
+if test $ac_cv_type__Bool = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STDBOOL_H 1
+_ACEOF
+
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+  :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking if a soname should be set" >&5
+echo $ECHO_N "checking if a soname should be set... $ECHO_C" >&6; }
+# Check whether --enable-soname was given.
+if test "${enable_soname+set}" = set; then
+  enableval=$enable_soname; use_soname=$enableval
+else
+  use_soname=no
+fi
+
+{ echo "$as_me:$LINENO: result: $use_soname" >&5
+echo "${ECHO_T}$use_soname" >&6; }
+ if test x$use_soname = xyes; then
+  USE_SONAME_TRUE=
+  USE_SONAME_FALSE='#'
+else
+  USE_SONAME_TRUE='#'
+  USE_SONAME_FALSE=
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking if tests should be built" >&5
+echo $ECHO_N "checking if tests should be built... $ECHO_C" >&6; }
+# Check whether --enable-demos was given.
+if test "${enable_demos+set}" = set; then
+  enableval=$enable_demos; enable_demos=$enableval
+else
+  enable_demos=yes
+fi
+
+{ echo "$as_me:$LINENO: result: $enable_demos" >&5
+echo "${ECHO_T}$enable_demos" >&6; }
+ if test x$enable_demos = xyes; then
+  ENABLE_DEMOS_TRUE=
+  ENABLE_DEMOS_FALSE='#'
+else
+  ENABLE_DEMOS_TRUE='#'
+  ENABLE_DEMOS_FALSE=
+fi
+
+
+
+
+# Check whether --with-arch was given.
+if test "${with_arch+set}" = set; then
+  withval=$with_arch; arch=$withval
+else
+  arch=no
+fi
+
+ARCHFLAGS=""
+if test "x$arch" != xno
+then
+    ARCHFLAGS="-march=$arch"
+fi
+
+
+case "$arch" in
+  pentium3 | pentium4 | athlon* )
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SSE
+_ACEOF
+
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in alloca.h ieeefp.h stdio.h stdlib.h math.h string.h stdarg.h malloc.h values.h float.h time.h sys/time.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------- ##
+## Report this to ode@ode.org ##
+## -------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+opcode=no
+gimpact=no
+
+# Check whether --with-trimesh was given.
+if test "${with_trimesh+set}" = set; then
+  withval=$with_trimesh; trimesh=$withval
+else
+  trimesh=opcode
+
+fi
+
+if test "$trimesh" = opcode
+then
+  opcode=yes
+fi
+if test "$trimesh" = gimpact
+then
+  gimpact=yes
+fi
+
+ if test $opcode  = yes; then
+  OPCODE_TRUE=
+  OPCODE_FALSE='#'
+else
+  OPCODE_TRUE='#'
+  OPCODE_FALSE=
+fi
+
+ if test $gimpact = yes; then
+  GIMPACT_TRUE=
+  GIMPACT_FALSE='#'
+else
+  GIMPACT_TRUE='#'
+  GIMPACT_FALSE=
+fi
+
+ if test $opcode = yes -o $gimpact = yes; then
+  TRIMESH_TRUE=
+  TRIMESH_FALSE='#'
+else
+  TRIMESH_TRUE='#'
+  TRIMESH_FALSE=
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking if gyroscopic term should be used" >&5
+echo $ECHO_N "checking if gyroscopic term should be used... $ECHO_C" >&6; }
+# Check whether --enable-gyroscopic was given.
+if test "${enable_gyroscopic+set}" = set; then
+  enableval=$enable_gyroscopic; gyroscopic=$enableval
+else
+  gyroscopic=yes
+fi
+
+{ echo "$as_me:$LINENO: result: $gyroscopic" >&5
+echo "${ECHO_T}$gyroscopic" >&6; }
+if test x"$gyroscopic" = xyes
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define dGYROSCOPIC
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking if double precision is requested" >&5
+echo $ECHO_N "checking if double precision is requested... $ECHO_C" >&6; }
+# Check whether --enable-double-precision was given.
+if test "${enable_double_precision+set}" = set; then
+  enableval=$enable_double_precision; precision=$enableval
+else
+  precision=no
+fi
+
+if test "$precision" != no
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define dDOUBLE
+_ACEOF
+
+if test "$build_os" == "$target_os"
+then
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#define dInfinity 1e20
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=1e20
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#define dInfinity 1.7976931348623157e+308
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=1.7976931348623157e+308
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <float.h>
+#define dInfinity HUGE_VAL
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=HUGE_VAL
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <float.h>
+#define dInfinity DBL_MAX
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=DBL_MAX
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+#cross-compiling, use a reasonable value. We should add an option for setting this.
+dinfinity=DBL_MAX
+fi
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define dSINGLE
+_ACEOF
+
+if test "$build_os" == "$target_os"
+then
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#define dInfinity 1e20f
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=1e20f
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#define dInfinity 3.402823466e+38F
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=3.402823466e+38F
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <float.h>
+#define dInfinity HUGE_VALF
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=HUGE_VALF
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <float.h>
+#define dInfinity FLT_MAX
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity)
+return 0;
+else return -1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  dinfinity=FLT_MAX
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+#cross-compiling, use a reasonable value. We should add an option for setting this.
+dinfinity=FLT_MAX
+fi
+fi
+{ echo "$as_me:$LINENO: result: $precision" >&5
+echo "${ECHO_T}$precision" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define dInfinity ${dinfinity}
+_ACEOF
+
+{ echo "$as_me:$LINENO: checking for appropriate dInfinity constant" >&5
+echo $ECHO_N "checking for appropriate dInfinity constant... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $dinfinity" >&5
+echo "${ECHO_T}$dinfinity" >&6; }
+
+if test "${ac_cv_header_float_h+set}" = set; then
+  { echo "$as_me:$LINENO: checking for float.h" >&5
+echo $ECHO_N "checking for float.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_float_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5
+echo "${ECHO_T}$ac_cv_header_float_h" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking float.h usability" >&5
+echo $ECHO_N "checking float.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <float.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking float.h presence" >&5
+echo $ECHO_N "checking float.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <float.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: float.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: float.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: float.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: float.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: float.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: float.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: float.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: float.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: float.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: float.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: float.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: float.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: float.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: float.h: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------- ##
+## Report this to ode@ode.org ##
+## -------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for float.h" >&5
+echo $ECHO_N "checking for float.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_float_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_float_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_float_h" >&5
+echo "${ECHO_T}$ac_cv_header_float_h" >&6; }
+
+fi
+if test $ac_cv_header_float_h = yes; then
+  have_float_h=yes
+else
+  have_float_h=no
+fi
+
+
+{ echo "$as_me:$LINENO: checking for appropriate dEpsilon constant" >&5
+echo $ECHO_N "checking for appropriate dEpsilon constant... $ECHO_C" >&6; }
+if test "x$have_float_h" == xyes
+then
+if test $precision == yes
+then
+dEpsilon=DBL_EPSILON
+else
+dEpsilon=FLT_EPSILON
+fi
+else
+if test $precision == yes
+then
+dEpsilon=2.2204460492503131e-16
+else
+dEpsilon=1.19209290e-07f
+fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define dEpsilon ${dEpsilon}
+_ACEOF
+
+{ echo "$as_me:$LINENO: result: $dEpsilon" >&5
+echo "${ECHO_T}$dEpsilon" >&6; }
+
+
+if test "$build_os" == "$target_os"
+then
+{ echo "$as_me:$LINENO: checking for a Pentium CPU" >&5
+echo $ECHO_N "checking for a Pentium CPU... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int main()
+{
+asm ("mov \$0,%%eax;\n"
+     "cpuid\n" : : : "%eax");
+return 0;
+};
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pentium=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+pentium=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+pentium=no
+fi
+if test "x$pentium" == xyes
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define PENTIUM 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $pentium" >&5
+echo "${ECHO_T}$pentium" >&6; }
+
+{ echo "$as_me:$LINENO: checking for a x86-64 CPU" >&5
+echo $ECHO_N "checking for a x86-64 CPU... $ECHO_C" >&6; }
+if test "$build_os" == "$target_os"
+then
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int main()
+{
+int a = 0;
+int * pa = &a;
+asm ("mov %0,%%rax\n"
+     "movl (%%rax),%%eax\n"
+     : : "r"(pa) : "%rax");
+return 0;
+};
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  cpu64=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+cpu64=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+cpu64=no
+fi
+if test "x$cpu64" == xyes
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define X86_64_SYSTEM 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $cpu64" >&5
+echo "${ECHO_T}$cpu64" >&6; }
+ if test x$cpu64 = xyes; then
+  X86_64_SYSTEM_TRUE=
+  X86_64_SYSTEM_FALSE='#'
+else
+  X86_64_SYSTEM_TRUE='#'
+  X86_64_SYSTEM_FALSE=
+fi
+
+
+{ echo "$as_me:$LINENO: checking if building a release library" >&5
+echo $ECHO_N "checking if building a release library... $ECHO_C" >&6; }
+# Check whether --enable-release was given.
+if test "${enable_release+set}" = set; then
+  enableval=$enable_release; release=$enableval
+else
+  release=no
+fi
+
+if test "x$release" == xyes
+then
+    CFLAGS="$CFLAGS -fomit-frame-pointer -ffast-math"
+    CPPFLAGS="$CPPFLAGS -fomit-frame-pointer -ffast-math"
+    CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -ffast-math"
+
+cat >>confdefs.h <<\_ACEOF
+#define dNODEBUG
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $release" >&5
+echo "${ECHO_T}$release" >&6; }
+
+{ echo "$as_me:$LINENO: checking if building a debug library" >&5
+echo $ECHO_N "checking if building a debug library... $ECHO_C" >&6; }
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then
+  enableval=$enable_debug; debug=$enableval
+else
+  debug=yes
+fi
+
+if test "x$debug" == xyes
+then
+    CFLAGS="$CFLAGS -g"
+    CPPFLAGS="$CPPFLAGS -g"
+    CXXFLAGS="$CXXFLAGS -g"
+fi
+{ echo "$as_me:$LINENO: result: $debug" >&5
+echo "${ECHO_T}$debug" >&6; }
+
+
+{ echo "$as_me:$LINENO: checking for char" >&5
+echo $ECHO_N "checking for char... $ECHO_C" >&6; }
+if test "${ac_cv_type_char+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef char ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_char=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_char=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_char" >&5
+echo "${ECHO_T}$ac_cv_type_char" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of char" >&5
+echo $ECHO_N "checking size of char... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_char+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef char ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef char ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef char ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef char ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef char ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_char=$ac_lo;;
+'') if test "$ac_cv_type_char" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (char)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (char)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_char=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef char ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_char=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_char" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (char)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (char)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_char=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_char" >&5
+echo "${ECHO_T}$ac_cv_sizeof_char" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR $ac_cv_sizeof_char
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6; }
+if test "${ac_cv_type_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_int=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') if test "$ac_cv_type_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_int=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_int=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for short" >&5
+echo $ECHO_N "checking for short... $ECHO_C" >&6; }
+if test "${ac_cv_type_short+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef short ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_short=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_short=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_short" >&5
+echo "${ECHO_T}$ac_cv_type_short" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of short" >&5
+echo $ECHO_N "checking size of short... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_short+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef short ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef short ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef short ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef short ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef short ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_short=$ac_lo;;
+'') if test "$ac_cv_type_short" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (short)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (short)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_short=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef short ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_short=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_short" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (short)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (short)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_short=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5
+echo "${ECHO_T}$ac_cv_sizeof_short" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for long int" >&5
+echo $ECHO_N "checking for long int... $ECHO_C" >&6; }
+if test "${ac_cv_type_long_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef long int ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_long_int=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_long_int=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_long_int" >&5
+echo "${ECHO_T}$ac_cv_type_long_int" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of long int" >&5
+echo $ECHO_N "checking size of long int... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_long_int+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_int=$ac_lo;;
+'') if test "$ac_cv_type_long_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long_int=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long int ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long_int=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_long_int" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long int)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long_int=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for void*" >&5
+echo $ECHO_N "checking for void*... $ECHO_C" >&6; }
+if test "${ac_cv_type_voidp+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef void* ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_voidp=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_type_voidp=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_voidp" >&5
+echo "${ECHO_T}$ac_cv_type_voidp" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of void*" >&5
+echo $ECHO_N "checking size of void*... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_voidp+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void* ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void* ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr $ac_mid + 1`
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void* ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void* ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_hi=`expr '(' $ac_mid ')' - 1`
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void* ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_voidp=$ac_lo;;
+'') if test "$ac_cv_type_voidp" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (void*)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void*)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_voidp=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void* ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+	return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_voidp=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_voidp" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (void*)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void*)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_voidp=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_voidp" >&5
+echo "${ECHO_T}$ac_cv_sizeof_voidp" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOIDP $ac_cv_sizeof_voidp
+_ACEOF
+
+
+
+case "$host_os" in
+  cygwin* | mingw*)
+    so_ext=".dll"
+    DLLDEFINE="-DODE_DLL"
+    SHARED_LDFLAGS="-shared"
+    drawstuff="Win32" # if in a Windows enviroment
+    ;;
+  *apple* | *darwin*) # For Mac OS X
+    so_ext=".dylib"
+    DLLDEFINE=""
+    SHARED_LDFLAGS="-dynamiclib"
+    drawstuff="OSX"
+            CC="$CXX"
+    LINK="$CXXLINK"
+    ;;
+  *)
+   drawstuff="X11" # if anything else default to X11
+    if test x$use_soname = xyes; then
+      so_ext=".so.$ODE_RELEASE"
+    else
+      so_ext=".so"
+    fi
+    DLLDEFINE=""
+    SHARED_LDFLAGS="-shared"
+    ;;
+esac
+ if test x$drawstuff = xWin32; then
+  WIN32_TRUE=
+  WIN32_FALSE='#'
+else
+  WIN32_TRUE='#'
+  WIN32_FALSE=
+fi
+
+ if test x$drawstuff = xX11; then
+  X11_TRUE=
+  X11_FALSE='#'
+else
+  X11_TRUE='#'
+  X11_FALSE=
+fi
+
+ if test x$drawstuff = xOSX; then
+  OSX_TRUE=
+  OSX_FALSE='#'
+else
+  OSX_TRUE='#'
+  OSX_FALSE=
+fi
+
+{ echo "$as_me:$LINENO: checking which drawstuff lib to build" >&5
+echo $ECHO_N "checking which drawstuff lib to build... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $drawstuff" >&5
+echo "${ECHO_T}$drawstuff" >&6; }
+
+{ echo "$as_me:$LINENO: checking for the suffix of shared libraries" >&5
+echo $ECHO_N "checking for the suffix of shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $so_ext" >&5
+echo "${ECHO_T}$so_ext" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SO_EXT "$so_ext"
+_ACEOF
+
+
+
+
+if test "X$x_includes" != "XNONE"; then
+	CFLAGS="$CFLAGS -I$x_includes"
+	CXXFLAGS="$CXXFLAGS -I$x_includes"
+fi
+if test "X$x_libraries" != "XNONE"; then
+	CFLAGS="$CFLAGS -L$x_libraries"
+	CXXFLAGS="$CXXFLAGS -L$x_libraries"
+fi
+
+if test "x$drawstuff" = "xOSX"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_APPLE_OPENGL_FRAMEWORK 1
+_ACEOF
+
+  GL_LIBS="-framework OpenGL -framework Carbon -framework AGL"
+else
+
+
+
+for ac_header in GL/gl.h GL/glu.h GL/glext.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if HAVE_GL_GL_H
+         #include <GL/gl.h>
+         #endif
+  	   #if HAVE_GL_GLU_H
+         #include <GL/glu.h>
+         #endif
+
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+  { echo "$as_me:$LINENO: checking for main in -lGL" >&5
+echo $ECHO_N "checking for main in -lGL... $ECHO_C" >&6; }
+if test "${ac_cv_lib_GL_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lGL  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_GL_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_GL_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_GL_main" >&5
+echo "${ECHO_T}$ac_cv_lib_GL_main" >&6; }
+if test $ac_cv_lib_GL_main = yes; then
+  GL_LIBS="$GL_LIBS -lGL"
+fi
+
+  TEMP_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $GL_LIBS"
+  { echo "$as_me:$LINENO: checking for main in -lGLU" >&5
+echo $ECHO_N "checking for main in -lGLU... $ECHO_C" >&6; }
+if test "${ac_cv_lib_GLU_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lGLU  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_GLU_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_GLU_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_GLU_main" >&5
+echo "${ECHO_T}$ac_cv_lib_GLU_main" >&6; }
+if test $ac_cv_lib_GLU_main = yes; then
+  GL_LIBS="$GL_LIBS -lGLU"
+fi
+
+  LDFLAGS="$TEMP_LDFLAGS"
+  { echo "$as_me:$LINENO: checking for main in -lopengl32" >&5
+echo $ECHO_N "checking for main in -lopengl32... $ECHO_C" >&6; }
+if test "${ac_cv_lib_opengl32_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lopengl32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_opengl32_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_opengl32_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_opengl32_main" >&5
+echo "${ECHO_T}$ac_cv_lib_opengl32_main" >&6; }
+if test $ac_cv_lib_opengl32_main = yes; then
+  GL_LIBS="$GL_LIBS -lopengl32"
+fi
+
+  { echo "$as_me:$LINENO: checking for main in -lglu32" >&5
+echo $ECHO_N "checking for main in -lglu32... $ECHO_C" >&6; }
+if test "${ac_cv_lib_glu32_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lglu32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_glu32_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_glu32_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_glu32_main" >&5
+echo "${ECHO_T}$ac_cv_lib_glu32_main" >&6; }
+if test $ac_cv_lib_glu32_main = yes; then
+  GL_LIBS="$GL_LIBS -lglu32"
+fi
+
+  { echo "$as_me:$LINENO: checking for main in -lXmu" >&5
+echo $ECHO_N "checking for main in -lXmu... $ECHO_C" >&6; }
+if test "${ac_cv_lib_Xmu_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXmu  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_Xmu_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_Xmu_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_Xmu_main" >&5
+echo "${ECHO_T}$ac_cv_lib_Xmu_main" >&6; }
+if test $ac_cv_lib_Xmu_main = yes; then
+  GL_LIBS="$GL_LIBS -lXmu"
+fi
+
+  { echo "$as_me:$LINENO: checking for main in -lXi" >&5
+echo $ECHO_N "checking for main in -lXi... $ECHO_C" >&6; }
+if test "${ac_cv_lib_Xi_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXi  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_Xi_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_Xi_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_Xi_main" >&5
+echo "${ECHO_T}$ac_cv_lib_Xi_main" >&6; }
+if test $ac_cv_lib_Xi_main = yes; then
+  GL_LIBS="$GL_LIBS -lXi"
+fi
+
+  { echo "$as_me:$LINENO: checking for main in -lX" >&5
+echo $ECHO_N "checking for main in -lX... $ECHO_C" >&6; }
+if test "${ac_cv_lib_X_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lX  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_X_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_X_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_X_main" >&5
+echo "${ECHO_T}$ac_cv_lib_X_main" >&6; }
+if test $ac_cv_lib_X_main = yes; then
+  GL_LIBS="$GL_LIBS -lX"
+fi
+
+  { echo "$as_me:$LINENO: checking for main in -lX11" >&5
+echo $ECHO_N "checking for main in -lX11... $ECHO_C" >&6; }
+if test "${ac_cv_lib_X11_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lX11  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_X11_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_X11_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_X11_main" >&5
+echo "${ECHO_T}$ac_cv_lib_X11_main" >&6; }
+if test $ac_cv_lib_X11_main = yes; then
+  GL_LIBS="$GL_LIBS -lX11"
+fi
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for main in -lcomctl32" >&5
+echo $ECHO_N "checking for main in -lcomctl32... $ECHO_C" >&6; }
+if test "${ac_cv_lib_comctl32_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcomctl32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_comctl32_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_comctl32_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_comctl32_main" >&5
+echo "${ECHO_T}$ac_cv_lib_comctl32_main" >&6; }
+if test $ac_cv_lib_comctl32_main = yes; then
+  LIBS="$LIBS -lcomctl32"
+fi
+
+{ echo "$as_me:$LINENO: checking for main in -lkernel32" >&5
+echo $ECHO_N "checking for main in -lkernel32... $ECHO_C" >&6; }
+if test "${ac_cv_lib_kernel32_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkernel32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_kernel32_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_kernel32_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_kernel32_main" >&5
+echo "${ECHO_T}$ac_cv_lib_kernel32_main" >&6; }
+if test $ac_cv_lib_kernel32_main = yes; then
+  LIBS="$LIBS -lkernel32"
+fi
+
+{ echo "$as_me:$LINENO: checking for main in -luser32" >&5
+echo $ECHO_N "checking for main in -luser32... $ECHO_C" >&6; }
+if test "${ac_cv_lib_user32_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-luser32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_user32_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_user32_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_user32_main" >&5
+echo "${ECHO_T}$ac_cv_lib_user32_main" >&6; }
+if test $ac_cv_lib_user32_main = yes; then
+  LIBS="$LIBS -luser32"
+fi
+
+{ echo "$as_me:$LINENO: checking for main in -lgdi32" >&5
+echo $ECHO_N "checking for main in -lgdi32... $ECHO_C" >&6; }
+if test "${ac_cv_lib_gdi32_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdi32  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_gdi32_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_gdi32_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_gdi32_main" >&5
+echo "${ECHO_T}$ac_cv_lib_gdi32_main" >&6; }
+if test $ac_cv_lib_gdi32_main = yes; then
+  LIBS="$LIBS -lgdi32"
+fi
+
+{ echo "$as_me:$LINENO: checking for main in -lwinmm" >&5
+echo $ECHO_N "checking for main in -lwinmm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_winmm_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lwinmm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_winmm_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_winmm_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_winmm_main" >&5
+echo "${ECHO_T}$ac_cv_lib_winmm_main" >&6; }
+if test $ac_cv_lib_winmm_main = yes; then
+  LIBS="$LIBS -lwinmm"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for main in -lstdc++" >&5
+echo $ECHO_N "checking for main in -lstdc++... $ECHO_C" >&6; }
+if test "${ac_cv_lib_stdcpp_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lstdc++  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_stdcpp_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_stdcpp_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_stdcpp_main" >&5
+echo "${ECHO_T}$ac_cv_lib_stdcpp_main" >&6; }
+if test $ac_cv_lib_stdcpp_main = yes; then
+  LIBS="$LIBS -lstdc++"
+fi
+
+{ echo "$as_me:$LINENO: checking for main in -lm" >&5
+echo $ECHO_N "checking for main in -lm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_m_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_m_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_m_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5
+echo "${ECHO_T}$ac_cv_lib_m_main" >&6; }
+if test $ac_cv_lib_m_main = yes; then
+  LIBS="$LIBS -lm"
+fi
+
+{ echo "$as_me:$LINENO: checking for main in -lpthread" >&5
+echo $ECHO_N "checking for main in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_pthread_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_pthread_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_main" >&6; }
+if test $ac_cv_lib_pthread_main = yes; then
+  LIBS="$LIBS -lpthread"
+fi
+
+
+
+TOPDIR=`cd $srcdir;pwd`
+
+
+{ echo "$as_me:$LINENO: checking for gprof" >&5
+echo $ECHO_N "checking for gprof... $ECHO_C" >&6; }
+# Check whether --enable-gprof was given.
+if test "${enable_gprof+set}" = set; then
+  enableval=$enable_gprof; gprof=$enableval
+else
+  gprof=no
+fi
+
+if test "$gprof" != no
+then
+    CFLAGS="-pg $CFLAGS"
+    CPPFLAGS="-pg $CPPFLAGS"
+    CXXFLAGS="-pg $CXXFLAGS"
+    { echo "$as_me:$LINENO: checking for main in -lgmon" >&5
+echo $ECHO_N "checking for main in -lgmon... $ECHO_C" >&6; }
+if test "${ac_cv_lib_gmon_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgmon  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_gmon_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_gmon_main=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_gmon_main" >&5
+echo "${ECHO_T}$ac_cv_lib_gmon_main" >&6; }
+if test $ac_cv_lib_gmon_main = yes; then
+  LIBS="$LIBS -lgmon"
+fi
+
+    { echo "$as_me:$LINENO: result: enabled" >&5
+echo "${ECHO_T}enabled" >&6; }
+else
+    { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in floor memmove memset select sqrt sqrtf sinf cosf fabsf atan2f fmodf copysignf copysign snprintf vsnprintf gettimeofday isnan isnanf _isnan _isnanf __isnan __isnanf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "$build_os" == "$target_os"
+then
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+{ echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6; }
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+			  if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_working_alloca_h=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6; }
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+				    if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_alloca_works=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6; }
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+{ echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6; }
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  return find_stack_direction () < 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------- ##
+## Report this to ode@ode.org ##
+## -------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_malloc_0_nonnull=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_malloc_0_nonnull=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+   case " $LIBOBJS " in
+  *" malloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for obstacks" >&5
+echo $ECHO_N "checking for obstacks... $ECHO_C" >&6; }
+if test "${ac_cv_func_obstack+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+		      #include "obstack.h"
+int
+main ()
+{
+struct obstack mem;
+		       #define obstack_chunk_alloc malloc
+		       #define obstack_chunk_free free
+		       obstack_init (&mem);
+		       obstack_free (&mem, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_obstack=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func_obstack=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_obstack" >&5
+echo "${ECHO_T}$ac_cv_func_obstack" >&6; }
+if test $ac_cv_func_obstack = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_OBSTACK 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" obstack.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS obstack.$ac_objext"
+ ;;
+esac
+
+fi
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------- ##
+## Report this to ode@ode.org ##
+## -------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5
+echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_realloc_0_nonnull=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *realloc ();
+#endif
+
+int
+main ()
+{
+return ! realloc (0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_realloc_0_nonnull=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_realloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6; }
+if test $ac_cv_func_realloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 1
+_ACEOF
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 0
+_ACEOF
+
+   case " $LIBOBJS " in
+  *" realloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS realloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define realloc rpl_realloc
+_ACEOF
+
+fi
+
+
+
+
+
+for ac_header in sys/select.h sys/socket.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------- ##
+## Report this to ode@ode.org ##
+## -------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking types of arguments for select" >&5
+echo $ECHO_N "checking types of arguments for select... $ECHO_C" >&6; }
+if test "${ac_cv_func_select_args+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  for ac_arg234 in 'fd_set *' 'int *' 'void *'; do
+ for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do
+  for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+extern int select ($ac_arg1,
+					    $ac_arg234, $ac_arg234, $ac_arg234,
+					    $ac_arg5);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+ done
+done
+# Provide a safe default value.
+: ${ac_cv_func_select_args='int,int *,struct timeval *'}
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_select_args" >&5
+echo "${ECHO_T}$ac_cv_func_select_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG1 $1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG234 ($2)
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG5 ($3)
+_ACEOF
+
+rm -f conftest*
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+{ echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; }
+if test "${ac_cv_func__doprnt+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub__doprnt || defined __stub____doprnt
+choke me
+#endif
+
+int
+main ()
+{
+return _doprnt ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_func__doprnt=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6; }
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+fi
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile include/Makefile include/ode/Makefile ode/Makefile ode/src/Makefile drawstuff/Makefile drawstuff/src/Makefile drawstuff/dstest/Makefile ode/demo/Makefile tests/Makefile tests/CppTestHarness/Makefile ode-config"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${USE_SONAME_TRUE}" && test -z "${USE_SONAME_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"USE_SONAME\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"USE_SONAME\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${ENABLE_DEMOS_TRUE}" && test -z "${ENABLE_DEMOS_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"ENABLE_DEMOS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ENABLE_DEMOS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${OPCODE_TRUE}" && test -z "${OPCODE_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"OPCODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"OPCODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${GIMPACT_TRUE}" && test -z "${GIMPACT_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"GIMPACT\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"GIMPACT\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${TRIMESH_TRUE}" && test -z "${TRIMESH_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"TRIMESH\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"TRIMESH\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X86_64_SYSTEM_TRUE}" && test -z "${X86_64_SYSTEM_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X86_64_SYSTEM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X86_64_SYSTEM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${WIN32_TRUE}" && test -z "${WIN32_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"WIN32\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"WIN32\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X11_TRUE}" && test -z "${X11_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X11\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X11\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${OSX_TRUE}" && test -z "${OSX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"OSX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"OSX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+	case $1 in
+        -*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ODE $as_me 0.9.0, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+		   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+		   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+ODE config.status 0.9.0
+configured by $0, generated by GNU Autoconf 2.61,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "include/ode/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/ode/config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "include/ode/Makefile") CONFIG_FILES="$CONFIG_FILES include/ode/Makefile" ;;
+    "ode/Makefile") CONFIG_FILES="$CONFIG_FILES ode/Makefile" ;;
+    "ode/src/Makefile") CONFIG_FILES="$CONFIG_FILES ode/src/Makefile" ;;
+    "drawstuff/Makefile") CONFIG_FILES="$CONFIG_FILES drawstuff/Makefile" ;;
+    "drawstuff/src/Makefile") CONFIG_FILES="$CONFIG_FILES drawstuff/src/Makefile" ;;
+    "drawstuff/dstest/Makefile") CONFIG_FILES="$CONFIG_FILES drawstuff/dstest/Makefile" ;;
+    "ode/demo/Makefile") CONFIG_FILES="$CONFIG_FILES ode/demo/Makefile" ;;
+    "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+    "tests/CppTestHarness/Makefile") CONFIG_FILES="$CONFIG_FILES tests/CppTestHarness/Makefile" ;;
+    "ode-config") CONFIG_FILES="$CONFIG_FILES ode-config" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+am__isrc!$am__isrc$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+XMKMF!$XMKMF$ac_delim
+X_CFLAGS!$X_CFLAGS$ac_delim
+X_PRE_LIBS!$X_PRE_LIBS$ac_delim
+X_LIBS!$X_LIBS$ac_delim
+X_EXTRA_LIBS!$X_EXTRA_LIBS$ac_delim
+ODE_CURRENT!$ODE_CURRENT$ac_delim
+ODE_REVISION!$ODE_REVISION$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+ODE_AGE!$ODE_AGE$ac_delim
+ODE_RELEASE!$ODE_RELEASE$ac_delim
+ODE_SONAME!$ODE_SONAME$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+WINDRES!$WINDRES$ac_delim
+ac_ct_WINDRES!$ac_ct_WINDRES$ac_delim
+RANLIB!$RANLIB$ac_delim
+USE_SONAME_TRUE!$USE_SONAME_TRUE$ac_delim
+USE_SONAME_FALSE!$USE_SONAME_FALSE$ac_delim
+ENABLE_DEMOS_TRUE!$ENABLE_DEMOS_TRUE$ac_delim
+ENABLE_DEMOS_FALSE!$ENABLE_DEMOS_FALSE$ac_delim
+ARCHFLAGS!$ARCHFLAGS$ac_delim
+OPCODE_TRUE!$OPCODE_TRUE$ac_delim
+OPCODE_FALSE!$OPCODE_FALSE$ac_delim
+GIMPACT_TRUE!$GIMPACT_TRUE$ac_delim
+GIMPACT_FALSE!$GIMPACT_FALSE$ac_delim
+TRIMESH_TRUE!$TRIMESH_TRUE$ac_delim
+TRIMESH_FALSE!$TRIMESH_FALSE$ac_delim
+X86_64_SYSTEM_TRUE!$X86_64_SYSTEM_TRUE$ac_delim
+X86_64_SYSTEM_FALSE!$X86_64_SYSTEM_FALSE$ac_delim
+WIN32_TRUE!$WIN32_TRUE$ac_delim
+WIN32_FALSE!$WIN32_FALSE$ac_delim
+X11_TRUE!$X11_TRUE$ac_delim
+X11_FALSE!$X11_FALSE$ac_delim
+OSX_TRUE!$OSX_TRUE$ac_delim
+OSX_FALSE!$OSX_FALSE$ac_delim
+DRAWSTUFF!$DRAWSTUFF$ac_delim
+so_ext!$so_ext$ac_delim
+SHARED_LDFLAGS!$SHARED_LDFLAGS$ac_delim
+GL_LIBS!$GL_LIBS$ac_delim
+TOPDIR!$TOPDIR$ac_delim
+ALLOCA!$ALLOCA$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 39; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+	  echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([	 #]*\\)[^	 ]*\\([	 ]*'
+ac_dB='\\)[	 (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+	t rset
+	:rset
+	s/^[	 ]*#[	 ]*define[	 ][	 ]*//
+	t ok
+	d
+	:ok
+	s/[\\&,]/\\&/g
+	s/^\('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+	s/^\('"$ac_word_re"'\)[	 ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[	 #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:	 sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:	 sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:	 sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[	 ]*#[	 ]*undef[	 ][	 ]*$ac_word_re[	 ]*\$/b def
+/^[	 ]*#[	 ]*define[	 ][	 ]*$ac_word_re[(	 ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $ac_file | $ac_file:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $ac_file" >`$as_dirname -- $ac_file ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X$ac_file : 'X\(//\)[^/]' \| \
+	 X$ac_file : 'X\(//\)$' \| \
+	 X$ac_file : 'X\(/\)' \| . 2>/dev/null ||
+echo X$ac_file |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # Grep'ing the whole file is not good either: AIX grep has a line
+  # limit of 2048, but all sed's we know have understand at least 4000.
+  if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
+    dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$mf" : 'X\(//\)[^/]' \| \
+	 X"$mf" : 'X\(//\)$' \| \
+	 X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$file" : 'X\(//\)[^/]' \| \
+	 X"$file" : 'X\(//\)$' \| \
+	 X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    { as_dir=$dirpart/$fdir
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+
+  esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+chmod +x ode-config
+
+echo "Configuration:"
+echo "  Target system type:      $target"
+echo "  Build  system type:      $build"
+echo "  Host   system type:      $host"
+echo "  Use double precision:    $precision"
+echo "  Use OPCODE:              $opcode"
+echo "  Use GIMPACT:             $gimpact"
+echo "  Use gyroscopic term:     $gyroscopic"
+echo "  Is this a Pentium:       $pentium"
+echo "  Is the CPU x86-64:       $cpu64"
+echo "  Is this a release build: $release"
+echo "  Adding debug symbols:    $debug"
+echo "  Using SONAME:		 $use_soname"
+echo "  Headers will be installed in $prefix/include/ode"
+echo "  Libraries will be installed in $prefix/lib"
+
+if test $gimpact = yes -a $precision = yes
+then
+  echo "WARNING! Double precision not yet supported for GIMPACT"
+fi
+
Index: /code/branches/ode/ode-0.9/configure.in
===================================================================
--- /code/branches/ode/ode-0.9/configure.in	(revision 216)
+++ /code/branches/ode/ode-0.9/configure.in	(revision 216)
@@ -0,0 +1,580 @@
+dnl Initial configure.in by Rodrigo Hernandez
+dnl Modified in 26/10/2005 by Rodrigo Hernandez
+
+dnl AC_INIT does not take a macro as a version nr: set it separately! - Bram
+AC_INIT(ODE,0.9.0,ode@ode.org)
+
+dnl When upgrading version nr, also change the AC_INIT line! - Bram
+ODE_CURRENT=0
+ODE_REVISION=9
+ODE_AGE=0
+ODE_RELEASE=[$ODE_CURRENT].[$ODE_REVISION].[$ODE_AGE]
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+AM_INIT_AUTOMAKE(ODE,[$ODE_RELEASE])
+AM_CONFIG_HEADER(include/ode/config.h)
+dnl Set CFLAGS to zero, so that we avoid getting the gratis -g -O2
+CFLAGS=
+CXXFLAGS=
+AC_C_BIGENDIAN
+AC_PATH_X
+AC_PATH_XTRA
+
+ODE_SONAME=libode.so.[$ODE_CURRENT]
+
+AC_SUBST(ODE_CURRENT)
+AC_SUBST(ODE_REVISION)
+AC_SUBST(ODE_AGE)
+AC_SUBST(ODE_RELEASE)
+AC_SUBST(ODE_SONAME)
+
+dnl This is needed because we have subdirectories
+AC_PROG_MAKE_SET
+
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_CHECK_TOOLS([WINDRES], [windres])
+AC_C_CONST 
+AC_C_INLINE
+AC_C_VOLATILE
+AC_HEADER_STDBOOL
+AC_PROG_RANLIB
+AC_TYPE_SIZE_T
+
+dnl Check if using sonames is requested
+dnl THIS IS TEMPORARY!
+AC_MSG_CHECKING(if a soname should be set)
+AC_ARG_ENABLE(soname,AC_HELP_STRING([--enable-soname],
+[Configure ODE shared library to set the soname field on ELF files]),
+use_soname=$enableval,use_soname=no)
+AC_MSG_RESULT($use_soname)
+AM_CONDITIONAL(USE_SONAME, test x$use_soname = xyes)
+
+
+dnl Check if we want to build demos
+AC_MSG_CHECKING(if tests should be built)
+AC_ARG_ENABLE(demos,AC_HELP_STRING([--enable-demos], [build tests]), enable_demos=$enableval,enable_demos=yes)
+AC_MSG_RESULT($enable_demos)
+AM_CONDITIONAL(ENABLE_DEMOS, test x$enable_demos = xyes)
+
+
+AC_ARG_WITH(arch,AC_HELP_STRING([--with-arch=[arch]],
+[build for $arch, where arch is any of the -march flags passed to gcc, without the -march, for example --with-arch=pentium3]),
+arch=$withval,arch=no)
+ARCHFLAGS=""
+if test "x$arch" != xno
+then
+    ARCHFLAGS="-march=$arch"
+fi
+AC_SUBST(ARCHFLAGS)
+
+dnl Decide whether or not SSE is available
+dnl Why dont we compile and run programs like we do to find out if
+dnl this is a Pentium machine further down? simple!
+dnl this may NOT be the machine on which the code is going to run in,
+dnl so allow users to compile programs for their target machine.
+case "$arch" in
+  pentium3 | pentium4 | athlon* )
+	AC_DEFINE(HAVE_SSE,,[Use SSE Optimizations])
+    ;;
+dnl this space available for other architectures specific extensions and/or
+dnl other Intel based extensions such as 3DNow, SSE2, MMX, etc.
+esac
+
+dnl check for required headers
+AC_CHECK_HEADERS( alloca.h ieeefp.h stdio.h stdlib.h math.h string.h stdarg.h malloc.h values.h float.h time.h sys/time.h )
+
+
+opcode=no
+gimpact=no
+AC_ARG_WITH(trimesh,AC_HELP_STRING([--with-trimesh=[opcode|gimpact|none]],
+[use the specified system for trimesh support.]),
+trimesh=$withval,trimesh=opcode
+)
+if test "$trimesh" = opcode
+then
+  opcode=yes
+fi
+if test "$trimesh" = gimpact
+then
+  gimpact=yes
+fi
+
+AM_CONDITIONAL(OPCODE,  test $opcode  = yes)
+AM_CONDITIONAL(GIMPACT, test $gimpact = yes)
+AM_CONDITIONAL(TRIMESH, test $opcode = yes -o $gimpact = yes)
+
+
+AC_MSG_CHECKING(if gyroscopic term should be used)
+AC_ARG_ENABLE(gyroscopic,AC_HELP_STRING([--disable-gyroscopic],
+[Configure ODE to work without gyroscopic term (may improve stability)]),
+gyroscopic=$enableval,gyroscopic=yes)
+AC_MSG_RESULT($gyroscopic)
+if test x"$gyroscopic" = xyes
+then
+AC_DEFINE(dGYROSCOPIC,,[Use gyroscopic terms])
+fi
+
+dnl Check Precision, define the dInfinity constant--------------------------/
+AC_MSG_CHECKING(if double precision is requested)
+AC_ARG_ENABLE(double-precision,AC_HELP_STRING([--enable-double-precision],
+[Configure ODE to work with double precision, if not specified, single precision is used]),
+precision=$enableval,precision=no)
+if test "$precision" != no
+then
+dnl DOUBLE was chosen
+AC_DEFINE(dDOUBLE,,[Use double precision])
+dnl Check from lest likelly to more likelly.
+if test "$build_os" == "$target_os"
+then
+AC_TRY_RUN([
+#define dInfinity 1e20
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=1e20,,)
+AC_TRY_RUN([
+#define dInfinity 1.7976931348623157e+308
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=1.7976931348623157e+308,,)
+AC_TRY_RUN([
+#include <float.h>
+#define dInfinity HUGE_VAL
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=HUGE_VAL,,)
+AC_TRY_RUN([
+#include <float.h>
+#define dInfinity DBL_MAX
+int main()
+{
+if (dInfinity > 1e10 && -dInfinity < -1e10 && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=DBL_MAX,,)
+else
+#cross-compiling, use a reasonable value. We should add an option for setting this.
+dinfinity=DBL_MAX
+fi
+else
+dnl default to SINGLE.
+AC_DEFINE(dSINGLE,,[Use single precision])
+dnl Check from lest likelly to more likelly.
+if test "$build_os" == "$target_os"
+then
+AC_TRY_RUN([
+#define dInfinity 1e20f
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=1e20f,,)
+AC_TRY_RUN([
+#define dInfinity 3.402823466e+38F
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=3.402823466e+38F,,)
+AC_TRY_RUN([
+#include <float.h>
+#define dInfinity HUGE_VALF
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=HUGE_VALF,,)
+AC_TRY_RUN([
+#include <float.h>
+#define dInfinity FLT_MAX
+int main()
+{
+if (dInfinity > 1e10f && -dInfinity < -1e10f && -dInfinity < dInfinity) 
+return 0;
+else return -1;
+}
+],dinfinity=FLT_MAX,,)
+#cross-compiling, use a reasonable value. We should add an option for setting this.
+dinfinity=FLT_MAX
+fi
+fi
+AC_MSG_RESULT($precision)
+AC_DEFINE_UNQUOTED(dInfinity,${dinfinity},[dInfinity Constant])
+AC_MSG_CHECKING(for appropriate dInfinity constant)
+AC_MSG_RESULT($dinfinity)
+dnl --------------------------------------------------------------------------/
+
+dnl Define dEpsilon
+AC_CHECK_HEADER(float.h,[have_float_h=yes],[have_float_h=no])
+AC_MSG_CHECKING(for appropriate dEpsilon constant)
+if test "x$have_float_h" == xyes 
+then
+if test $precision == yes
+then
+dEpsilon=DBL_EPSILON
+else
+dEpsilon=FLT_EPSILON
+fi
+else
+if test $precision == yes
+then
+dEpsilon=2.2204460492503131e-16
+else
+dEpsilon=1.19209290e-07f
+fi
+fi
+AC_DEFINE_UNQUOTED(dEpsilon,${dEpsilon},[dEpsilon Constant])
+AC_MSG_RESULT($dEpsilon)
+
+
+dnl Check for PENTIUM
+if test "$build_os" == "$target_os"
+then
+AC_MSG_CHECKING(for a Pentium CPU)
+AC_TRY_RUN([
+int main() 
+{
+asm ("mov \$0,%%eax;\n"
+     "cpuid\n" : : : "%eax");
+return 0;
+};
+],pentium=yes,pentium=no,)
+else
+pentium=no
+fi
+if test "x$pentium" == xyes 
+then
+AC_DEFINE(PENTIUM,1,[is this a pentium on a gcc-based platform?])
+fi
+AC_MSG_RESULT($pentium)
+
+dnl Check for 64bit CPU
+AC_MSG_CHECKING(for a x86-64 CPU)
+if test "$build_os" == "$target_os"
+then
+AC_TRY_RUN([
+int main()
+{
+int a = 0; 
+int * pa = &a;
+asm ("mov %0,%%rax\n"
+     "movl (%%rax),%%eax\n"
+     : : "r"(pa) : "%rax");
+return 0;
+};
+],cpu64=yes,cpu64=no,)
+else
+cpu64=no
+fi
+if test "x$cpu64" == xyes 
+then
+AC_DEFINE(X86_64_SYSTEM,1,[is this a X86_64 system on a gcc-based platform?])
+fi
+AC_MSG_RESULT($cpu64)
+AM_CONDITIONAL(X86_64_SYSTEM, test x$cpu64 = xyes)
+
+AC_MSG_CHECKING(if building a release library)
+AC_ARG_ENABLE(release,AC_HELP_STRING([--enable-release],
+[build a release library with -fomit-frame-pointer and -ffast-math]),
+release=$enableval,release=no)
+if test "x$release" == xyes
+then
+    CFLAGS="$CFLAGS -fomit-frame-pointer -ffast-math"
+    CPPFLAGS="$CPPFLAGS -fomit-frame-pointer -ffast-math"
+    CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -ffast-math"
+    AC_DEFINE(dNODEBUG,,[Disable debug output])
+fi
+AC_MSG_RESULT($release)
+
+AC_MSG_CHECKING(if building a debug library)
+AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],
+[Add debug symbols to the library with -g]),
+debug=$enableval,debug=yes)
+if test "x$debug" == xyes
+then
+    CFLAGS="$CFLAGS -g"
+    CPPFLAGS="$CPPFLAGS -g"
+    CXXFLAGS="$CXXFLAGS -g"
+fi
+AC_MSG_RESULT($debug)
+
+
+dnl Check variable type sizes
+AC_CHECK_SIZEOF(char)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(long int)
+AC_CHECK_SIZEOF(void*)
+
+dnl Set some Platform Specific Variables
+case "$host_os" in
+  cygwin* | mingw*)
+    so_ext=".dll"
+    DLLDEFINE="-DODE_DLL"
+    SHARED_LDFLAGS="-shared"
+    drawstuff="Win32" # if in a Windows enviroment
+    ;;
+  *apple* | *darwin*) # For Mac OS X
+    so_ext=".dylib"
+    DLLDEFINE=""
+    SHARED_LDFLAGS="-dynamiclib"
+    drawstuff="OSX"
+    dnl We need to use C++ compilation and linking for ode on Mac
+    dnl Might as well do it for all code.
+    CC="$CXX"
+    LINK="$CXXLINK"
+    ;;
+  *)
+   drawstuff="X11" # if anything else default to X11
+    if test x$use_soname = xyes; then
+      so_ext=".so.$ODE_RELEASE"
+    else
+      so_ext=".so"
+    fi
+    DLLDEFINE=""
+    SHARED_LDFLAGS="-shared"
+    ;;
+esac
+dnl Set Conditionals
+AM_CONDITIONAL(WIN32, test x$drawstuff = xWin32)
+AM_CONDITIONAL(X11, test x$drawstuff = xX11)
+AM_CONDITIONAL(OSX, test x$drawstuff = xOSX)
+dnl Set Drawstuff variables
+AC_MSG_CHECKING(which drawstuff lib to build)
+AC_MSG_RESULT($drawstuff)
+AC_SUBST(DRAWSTUFF)
+dnl Set shared library variables
+AC_MSG_CHECKING(for the suffix of shared libraries)
+AC_MSG_RESULT($so_ext)
+AC_DEFINE_UNQUOTED(SO_EXT,"$so_ext",[The extension for shared libraries.])
+AC_SUBST(so_ext)
+AC_SUBST(SHARED_LDFLAGS)
+
+dnl Check for AC_PATH_X variables
+if test "X$x_includes" != "XNONE"; then
+	CFLAGS="$CFLAGS -I$x_includes"
+	CXXFLAGS="$CXXFLAGS -I$x_includes"
+fi
+if test "X$x_libraries" != "XNONE"; then
+	CFLAGS="$CFLAGS -L$x_libraries"
+	CXXFLAGS="$CXXFLAGS -L$x_libraries"
+fi
+
+dnl Check for OpenGL
+if test "x$drawstuff" = "xOSX"; then
+  AC_DEFINE([HAVE_APPLE_OPENGL_FRAMEWORK], [1],
+            [Use the Apple OpenGL framework.])
+  GL_LIBS="-framework OpenGL -framework Carbon -framework AGL"
+else
+  AC_CHECK_HEADERS(GL/gl.h GL/glu.h GL/glext.h,,,
+       [[#if HAVE_GL_GL_H
+         #include <GL/gl.h>
+         #endif
+  	   #if HAVE_GL_GLU_H
+         #include <GL/glu.h>
+         #endif
+       ]])
+  AC_CHECK_LIB(GL, main,[GL_LIBS="$GL_LIBS -lGL"])
+  TEMP_LDFLAGS="$LDFLAGS"
+  LDFLAGS="$LDFLAGS $GL_LIBS"
+  AC_CHECK_LIB(GLU, main,[GL_LIBS="$GL_LIBS -lGLU"])
+  LDFLAGS="$TEMP_LDFLAGS"
+  AC_CHECK_LIB(opengl32, main,[GL_LIBS="$GL_LIBS -lopengl32"])
+  AC_CHECK_LIB(glu32, main,[GL_LIBS="$GL_LIBS -lglu32"])
+  AC_CHECK_LIB(Xmu, main,[GL_LIBS="$GL_LIBS -lXmu"])
+  AC_CHECK_LIB(Xi, main,[GL_LIBS="$GL_LIBS -lXi"])
+  AC_CHECK_LIB(X, main,[GL_LIBS="$GL_LIBS -lX"])
+  AC_CHECK_LIB(X11, main,[GL_LIBS="$GL_LIBS -lX11"])
+fi
+AC_SUBST(GL_LIBS)
+
+dnl Add some Windows libraries if found
+AC_CHECK_LIB(comctl32,main,[LIBS="$LIBS -lcomctl32"])
+AC_CHECK_LIB(kernel32,main,[LIBS="$LIBS -lkernel32"])
+AC_CHECK_LIB(user32,main,[LIBS="$LIBS -luser32"])
+AC_CHECK_LIB(gdi32,main,[LIBS="$LIBS -lgdi32"])
+AC_CHECK_LIB(winmm,main,[LIBS="$LIBS -lwinmm"])
+
+dnl Add math and standard c++ lib just in case
+AC_CHECK_LIB(stdc++,main,[LIBS="$LIBS -lstdc++"])
+AC_CHECK_LIB(m,main,[LIBS="$LIBS -lm"])
+AC_CHECK_LIB(pthread,main,[LIBS="$LIBS -lpthread"])
+
+
+TOPDIR=`cd $srcdir;pwd`
+AC_SUBST(TOPDIR)
+
+dnl Check if the user wants to profile ODE using gprof
+AC_MSG_CHECKING(for gprof)
+AC_ARG_ENABLE(gprof,
+AC_HELP_STRING([--enable-gprof],[enable profiling with gprof]),
+gprof=$enableval,gprof=no)
+if test "$gprof" != no
+then
+    CFLAGS="-pg $CFLAGS"
+    CPPFLAGS="-pg $CPPFLAGS"
+    CXXFLAGS="-pg $CXXFLAGS"
+    AC_CHECK_LIB(gmon, main,[LIBS="$LIBS -lgmon"])
+    AC_MSG_RESULT(enabled)
+else
+    AC_MSG_RESULT(no)
+fi
+
+dnl Check for autoscan sugested functions
+AC_CHECK_FUNCS([floor memmove memset select sqrt sqrtf sinf cosf fabsf atan2f fmodf copysignf copysign snprintf vsnprintf gettimeofday isnan isnanf _isnan _isnanf __isnan __isnanf])
+if test "$build_os" == "$target_os"
+then
+AC_FUNC_ALLOCA 
+AC_FUNC_MALLOC
+AC_FUNC_OBSTACK 
+AC_FUNC_REALLOC
+AC_FUNC_SELECT_ARGTYPES
+AC_FUNC_VPRINTF
+fi
+
+dnl include found system headers into config.h
+AH_TOP([
+#ifndef ODE_CONFIG_H
+#define ODE_CONFIG_H
+])
+AH_BOTTOM([
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#if defined(HAVE_IEEEFP_H) && !defined(__CYGWIN__)
+// This header creates conflicts with math.h in Cygwin.
+#include <ieeefp.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#if SIZEOF_CHAR == 1
+typedef char int8;
+typedef unsigned char uint8;
+#else
+#error "expecting sizeof(char) == 1"
+#endif
+#if SIZEOF_SHORT == 2
+typedef short int16;
+typedef unsigned short uint16;
+#else
+#error "can not find 2 byte integer type"
+#endif
+/* integer types (we assume int >= 32 bits) */
+#if SIZEOF_INT == 4
+typedef short int32;
+typedef unsigned short uint32;
+#else
+#error "can not find 4 byte integer type"
+#endif
+/* an integer type that we can safely cast a pointer to and
+ * from without loss of bits.
+ */
+#if SIZEOF_SHORT == SIZEOF_VOIDP
+typedef unsigned short intP;
+#elif SIZEOF_INT == SIZEOF_VOIDP
+typedef unsigned int intP;
+#elif SIZEOF_LONG_INT == SIZEOF_VOIDP
+typedef unsigned long int intP;
+#endif
+
+/* 
+Handle Windows DLL odities
+Its easier to export all symbols using the -shared flag
+for MinGW than differentiating with declspec,
+so only do it for MSVC
+*/
+#if defined(ODE_DLL) && defined(WIN32) && defined(_MSC_VER)
+#define ODE_API __declspec( dllexport )
+#elif !defined(ODE_DLL) && defined(WIN32) && defined(MSC_VER)
+#define ODE_API __declspec( dllimport )
+#else
+#define ODE_API
+#endif
+
+#endif /* #define ODE_CONFIG_H */
+])
+
+
+dnl Finally write our Makefiles
+AC_OUTPUT([
+ Makefile
+ include/Makefile
+ include/ode/Makefile
+ ode/Makefile
+ ode/src/Makefile
+ drawstuff/Makefile
+ drawstuff/src/Makefile
+ drawstuff/dstest/Makefile
+ ode/demo/Makefile
+ tests/Makefile
+ tests/CppTestHarness/Makefile
+ ode-config
+ ])
+
+chmod +x ode-config
+
+dnl Print some useful information
+echo "Configuration:"
+echo "  Target system type:      $target"
+echo "  Build  system type:      $build"
+echo "  Host   system type:      $host"
+echo "  Use double precision:    $precision"
+echo "  Use OPCODE:              $opcode"
+echo "  Use GIMPACT:             $gimpact"
+echo "  Use gyroscopic term:     $gyroscopic"
+echo "  Is this a Pentium:       $pentium"
+echo "  Is the CPU x86-64:       $cpu64"
+echo "  Is this a release build: $release"
+echo "  Adding debug symbols:    $debug"
+echo "  Using SONAME:		 $use_soname"
+echo "  Headers will be installed in $prefix/include/ode"
+echo "  Libraries will be installed in $prefix/lib"
+
+if test $gimpact = yes -a $precision = yes
+then
+  echo "WARNING! Double precision not yet supported for GIMPACT"
+fi
+
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/README.txt
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/README.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/README.txt	(revision 216)
@@ -0,0 +1,110 @@
+Breakable Joints
+
+================================================================================
+
+Description:
+This is a small addition to ODE that makes joints breakable. Breakable means
+that if a force on a joint is to high it wil break. I have included a modified
+version of test_buggy.cpp (test_breakable.cpp) so you can see it for your self.
+Just drive your buggy into an obstacle and enjoy!
+
+================================================================================
+
+Installation instructions:
+- copy joint.h, joint.cpp, ode.cpp and step.cpp to the ode/src/ directory
+- copy common.h and object.h to the include/ directory
+- copy test_breakable.cpp to the ode/test/ directory
+- add test_breakable.cpp to the ODE_TEST_SRC_CPP object in the makefile.
+- make ode-lib
+- make ode-test
+You can also use the diffs. The above files will quickly go out of sync with the
+rest of ODE but the diffs wil remain valid longer.
+
+================================================================================
+
+Functions:
+dJointSetBreakable (dJointID joint, int b)
+	If b is 1 the joint is made breakable. If b is 0 the joint is made
+	unbreakable.
+
+void dJointSetBreakCallback (dJointID joint, dJointBreakCallback *callbackFunc)
+	Sets the callback function for this joint. If a funtion is set it will be
+	called if the joint is broken but before it is actually detached or deleted.
+
+void dJointSetBreakMode (dJointID joint, int mode)
+	Use this functions to set some flags. These flags can be ORred ( | )
+	together; ie. dJointSetBreakMode (someJoint,
+dJOINT_BREAK_AT_B1_FORCE|dJOINT_DELETE_ON_BREAK)
+	dJOINT_DELETE_ON_BREAK    - If the joint breaks it wil be deleted.
+	dJOINT_BREAK_AT_B1_FORCE  - If the force on body 1 is to high the joint will
+								break
+	dJOINT_BREAK_AT_B1_TORQUE - If the torque on body 1 is to high the joint will
+								break
+	dJOINT_BREAK_AT_B2_FORCE  - If the force on body 2 is to high the joint will
+								break
+	dJOINT_BREAK_AT_B2_TORQUE - If the torque on body 2 is to high the joint will
+								break
+
+void dJointSetBreakForce (dJointID joint, int body, dReal x, dReal y, dReal z)
+	With this function you can set the maximum force for a body connected to this
+	joint. A value of 0 for body means body 1, 1 means body 2. The force is 
+	relative to the	bodies rotation.
+
+void dJointSetBreakTorque (dJointID joint, int body, dReal x, dReal y, dReal z)
+	With this function you can set the maximum torque for a body connected to this
+	joint. A value of 0 for body means body 1, 1 means body 2. The torque is 
+	relative to the	bodies rotation.
+
+int dJointIsBreakable (dJointID joint)
+	Returns 1 if this joint is breakable, 0 otherwise.
+	
+int dJointGetBreakMode (dJointID joint)
+	Returns the breakmode flag.
+
+void dJointGetBreakForce (dJointID joint, int body, dReal *force)
+	Returns the force at what this joint will break. A value of 0 for body means
+	body 1, 1 means body 2. force must have enough space for 3 dReal values.
+
+void dJointGetBreakTorque (dJointID joint, int body, dReal *torque)
+	Returns the torque at what this joint will break. A value of 0 for body 
+	means body 1, 1 means body 2. force must have enough space for 3 dReal 
+	values.
+
+================================================================================
+
+The callback function is defined like this (in common.h):
+void dJointBreakCallback (dJointID);
+
+================================================================================
+
+Problems, known bugs & other issues:
+- If the timestep is very small then joints get a lot weaker. They can even fall
+  apart!
+- I have tested all this with the latest checkout from CVS (at the time of 
+  writing ofcourse). I haven't tested it with earlier versions of ODE.
+- I have modified the code that fills the jointfeedback struct. I haven't tested
+  if it still works.
+- I'm not sure if the forces are really relative to the connected bodies.
+- There are some memory leaks in the test_breakable.cpp example.
+
+================================================================================
+
+Bugfixes and changes:
+09/08/2003
+- I fixed a bug when there where 0 joints in the simulation
+
+06/12/2003
+- dJointGetBreakMode() added, by vadim_mcagon@hotmail.com
+
+11/03/2004
+- Updated files to work with latest CVS checkout. 
+- Added support for dWorldStepFast1()
+- Added separate test_breakable.cpp example.
+- Updated the code that breaks and destroys a joint.
+
+================================================================================
+
+Send me an e-mail if you have any suggestions, ideas, bugs, bug-fixes, anything!
+e-mail: roelvandijk@home.nl
+
+Roel van Dijk - 11/03/2004
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/common.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/common.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/common.h	(revision 216)
@@ -0,0 +1,337 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_COMMON_H_
+#define _ODE_COMMON_H_
+
+#include <ode/config.h>
+#include <ode/error.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* configuration stuff */
+
+/* the efficient alignment. most platforms align data structures to some
+ * number of bytes, but this is not always the most efficient alignment.
+ * for example, many x86 compilers align to 4 bytes, but on a pentium it
+ * is important to align doubles to 8 byte boundaries (for speed), and
+ * the 4 floats in a SIMD register to 16 byte boundaries. many other
+ * platforms have similar behavior. setting a larger alignment can waste
+ * a (very) small amount of memory. NOTE: this number must be a power of
+ * two. this is set to 16 by default.
+ */
+#define EFFICIENT_ALIGNMENT 16
+
+
+/* constants */
+
+/* pi and 1/sqrt(2) are defined here if necessary because they don't get
+ * defined in <math.h> on some platforms (like MS-Windows)
+ */
+
+#ifndef M_PI
+#define M_PI REAL(3.1415926535897932384626433832795029)
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 REAL(0.7071067811865475244008443621048490)
+#endif
+
+
+/* debugging:
+ *   IASSERT  is an internal assertion, i.e. a consistency check. if it fails
+ *            we want to know where.
+ *   UASSERT  is a user assertion, i.e. if it fails a nice error message
+ *            should be printed for the user.
+ *   AASSERT  is an arguments assertion, i.e. if it fails "bad argument(s)"
+ *            is printed.
+ *   DEBUGMSG just prints out a message
+ */
+
+#ifndef dNODEBUG
+#ifdef __GNUC__
+#define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \
+  "assertion \"" #a "\" failed in %s() [%s]",__FUNCTION__,__FILE__);
+#define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \
+  msg " in %s()", __FUNCTION__);
+#define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT, \
+  msg " in %s()", __FUNCTION__);
+#else
+#define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \
+  "assertion \"" #a "\" failed in %s:%d",__FILE__,__LINE__);
+#define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \
+  msg " (%s:%d)", __FILE__,__LINE__);
+#define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT, \
+  msg " (%s:%d)", __FILE__,__LINE__);
+#endif
+#else
+#define dIASSERT(a) ;
+#define dUASSERT(a,msg) ;
+#define dDEBUGMSG(msg) ;
+#endif
+#define dAASSERT(a) dUASSERT(a,"Bad argument(s)")
+
+/* floating point data type, vector, matrix and quaternion types */
+
+#if defined(dSINGLE)
+typedef float dReal;
+#elif defined(dDOUBLE)
+typedef double dReal;
+#else
+#error You must #define dSINGLE or dDOUBLE
+#endif
+
+
+/* round an integer up to a multiple of 4, except that 0 and 1 are unmodified
+ * (used to compute matrix leading dimensions)
+ */
+#define dPAD(a) (((a) > 1) ? ((((a)-1)|3)+1) : (a))
+
+/* these types are mainly just used in headers */
+typedef dReal dVector3[4];
+typedef dReal dVector4[4];
+typedef dReal dMatrix3[4*3];
+typedef dReal dMatrix4[4*4];
+typedef dReal dMatrix6[8*6];
+typedef dReal dQuaternion[4];
+
+
+/* precision dependent scalar math functions */
+
+#if defined(dSINGLE)
+
+#define REAL(x) (x ## f)			/* form a constant */
+#define dRecip(x) ((float)(1.0f/(x)))		/* reciprocal */
+#define dSqrt(x) ((float)sqrt(x))		/* square root */
+#define dRecipSqrt(x) ((float)(1.0f/sqrt(x)))	/* reciprocal square root */
+#define dSin(x) ((float)sin(x))			/* sine */
+#define dCos(x) ((float)cos(x))			/* cosine */
+#define dFabs(x) ((float)fabs(x))		/* absolute value */
+#define dAtan2(y,x) ((float)atan2((y),(x)))	/* arc tangent with 2 args */
+
+#elif defined(dDOUBLE)
+
+#define REAL(x) (x)
+#define dRecip(x) (1.0/(x))
+#define dSqrt(x) sqrt(x)
+#define dRecipSqrt(x) (1.0/sqrt(x))
+#define dSin(x) sin(x)
+#define dCos(x) cos(x)
+#define dFabs(x) fabs(x)
+#define dAtan2(y,x) atan2((y),(x))
+
+#else
+#error You must #define dSINGLE or dDOUBLE
+#endif
+
+
+/* utility */
+
+
+/* round something up to be a multiple of the EFFICIENT_ALIGNMENT */
+
+#define dEFFICIENT_SIZE(x) ((((x)-1)|(EFFICIENT_ALIGNMENT-1))+1)
+
+
+/* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste
+ * up to 15 bytes per allocation, depending on what alloca() returns.
+ */
+
+#define dALLOCA16(n) \
+  ((char*)dEFFICIENT_SIZE(((int)(alloca((n)+(EFFICIENT_ALIGNMENT-1))))))
+
+
+/* internal object types (all prefixed with `dx') */
+
+struct dxWorld;		/* dynamics world */
+struct dxSpace;		/* collision space */
+struct dxBody;		/* rigid body (dynamics object) */
+struct dxGeom;		/* geometry (collision object) */
+struct dxJoint;
+struct dxJointNode;
+struct dxJointGroup;
+
+typedef struct dxWorld *dWorldID;
+typedef struct dxSpace *dSpaceID;
+typedef struct dxBody *dBodyID;
+typedef struct dxGeom *dGeomID;
+typedef struct dxJoint *dJointID;
+typedef struct dxJointGroup *dJointGroupID;
+
+
+/* error numbers */
+
+enum {
+  d_ERR_UNKNOWN = 0,		/* unknown error */
+  d_ERR_IASSERT,		/* internal assertion failed */
+  d_ERR_UASSERT,		/* user assertion failed */
+  d_ERR_LCP			/* user assertion failed */
+};
+
+
+/* joint type numbers */
+
+enum {
+  dJointTypeNone = 0,		/* or "unknown" */
+  dJointTypeBall,
+  dJointTypeHinge,
+  dJointTypeSlider,
+  dJointTypeContact,
+  dJointTypeUniversal,
+  dJointTypeHinge2,
+  dJointTypeFixed,
+  dJointTypeNull,
+  dJointTypeAMotor
+};
+
+/******************** breakable joint contribution ***********************/
+/* joint break callback function */
+typedef void dJointBreakCallback (dJointID joint);
+
+/* joint break modes */
+enum {
+  // if this flag is set, the joint wil break
+  dJOINT_BROKEN =             0x0001,
+  // if this flag is set, the joint wil be deleted when it breaks
+  dJOINT_DELETE_ON_BREAK =    0x0002,
+  // if this flag is set, the joint can break at a certain force on body 1
+  dJOINT_BREAK_AT_B1_FORCE =  0x0004,
+  // if this flag is set, the joint can break at a certain torque on body 1
+  dJOINT_BREAK_AT_B1_TORQUE = 0x0008,
+  // if this flag is set, the joint can break at a certain force on body 2
+  dJOINT_BREAK_AT_B2_FORCE =  0x0010,
+  // if this flag is set, the joint can break at a certain torque on body 2
+  dJOINT_BREAK_AT_B2_TORQUE = 0x0020
+};
+/*************************************************************************/
+
+/* an alternative way of setting joint parameters, using joint parameter
+ * structures and member constants. we don't actually do this yet.
+ */
+
+/*
+typedef struct dLimot {
+  int mode;
+  dReal lostop, histop;
+  dReal vel, fmax;
+  dReal fudge_factor;
+  dReal bounce, soft;
+  dReal suspension_erp, suspension_cfm;
+} dLimot;
+
+enum {
+  dLimotLoStop		= 0x0001,
+  dLimotHiStop		= 0x0002,
+  dLimotVel		= 0x0004,
+  dLimotFMax		= 0x0008,
+  dLimotFudgeFactor	= 0x0010,
+  dLimotBounce		= 0x0020,
+  dLimotSoft		= 0x0040
+};
+*/
+
+
+/* standard joint parameter names. why are these here? - because we don't want
+ * to include all the joint function definitions in joint.cpp. hmmmm.
+ * MSVC complains if we call D_ALL_PARAM_NAMES_X with a blank second argument,
+ * which is why we have the D_ALL_PARAM_NAMES macro as well. please copy and
+ * paste between these two.
+ */
+
+#define D_ALL_PARAM_NAMES(start) \
+  /* parameters for limits and motors */ \
+  dParamLoStop = start, \
+  dParamHiStop, \
+  dParamVel, \
+  dParamFMax, \
+  dParamFudgeFactor, \
+  dParamBounce, \
+  dParamCFM, \
+  dParamStopERP, \
+  dParamStopCFM, \
+  /* parameters for suspension */ \
+  dParamSuspensionERP, \
+  dParamSuspensionCFM,
+
+#define D_ALL_PARAM_NAMES_X(start,x) \
+  /* parameters for limits and motors */ \
+  dParamLoStop ## x = start, \
+  dParamHiStop ## x, \
+  dParamVel ## x, \
+  dParamFMax ## x, \
+  dParamFudgeFactor ## x, \
+  dParamBounce ## x, \
+  dParamCFM ## x, \
+  dParamStopERP ## x, \
+  dParamStopCFM ## x, \
+  /* parameters for suspension */ \
+  dParamSuspensionERP ## x, \
+  dParamSuspensionCFM ## x,
+
+enum {
+  D_ALL_PARAM_NAMES(0)
+  D_ALL_PARAM_NAMES_X(0x100,2)
+  D_ALL_PARAM_NAMES_X(0x200,3)
+
+  /* add a multiple of this constant to the basic parameter numbers to get
+   * the parameters for the second, third etc axes.
+   */
+  dParamGroup=0x100
+};
+
+
+/* angular motor mode numbers */
+
+enum{
+  dAMotorUser = 0,
+  dAMotorEuler = 1
+};
+
+
+/* joint force feedback information */
+
+typedef struct dJointFeedback {
+  dVector3 f1;		/* force applied to body 1 */
+  dVector3 t1;		/* torque applied to body 1 */
+  dVector3 f2;		/* force applied to body 2 */
+  dVector3 t2;		/* torque applied to body 2 */
+} dJointFeedback;
+
+
+/* private functions that must be implemented by the collision library:
+ * (1) indicate that a geom has moved, (2) get the next geom in a body list.
+ * these functions are called whenever the position of geoms connected to a
+ * body have changed, e.g. with dBodySetPosition(), dBodySetRotation(), or
+ * when the ODE step function updates the body state.
+ */
+
+void dGeomMoved (dGeomID);
+dGeomID dGeomGetBodyNext (dGeomID);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/common.h.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/common.h.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/common.h.diff	(revision 216)
@@ -0,0 +1,21 @@
+208,227d207
+< /******************** breakable joint contribution ***********************/
+< /* joint break callback function */
+< typedef void dJointBreakCallback (dJointID joint);
+< 
+< /* joint break modes */
+< enum {
+<   // if this flag is set, the joint wil break
+<   dJOINT_BROKEN =             0x0001,
+<   // if this flag is set, the joint wil be deleted when it breaks
+<   dJOINT_DELETE_ON_BREAK =    0x0002,
+<   // if this flag is set, the joint can break at a certain force on body 1
+<   dJOINT_BREAK_AT_B1_FORCE =  0x0004,
+<   // if this flag is set, the joint can break at a certain torque on body 1
+<   dJOINT_BREAK_AT_B1_TORQUE = 0x0008,
+<   // if this flag is set, the joint can break at a certain force on body 2
+<   dJOINT_BREAK_AT_B2_FORCE =  0x0010,
+<   // if this flag is set, the joint can break at a certain torque on body 2
+<   dJOINT_BREAK_AT_B2_TORQUE = 0x0020
+< };
+< /*************************************************************************/
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/joint.cpp.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/joint.cpp.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/joint.cpp.diff	(revision 216)
@@ -0,0 +1,148 @@
+2659,2804d2658
+< 
+< /******************** breakable joint contribution ***********************/
+< extern "C" void dJointSetBreakable (dxJoint *joint, int b) {
+<   dAASSERT(joint);
+<   if (b) {
+<     // we want this joint to be breakable but we must first check if it
+<     // was already breakable
+<     if (!joint->breakInfo) {
+<       // allocate a dxJointBreakInfo struct
+<       joint->breakInfo = new dxJointBreakInfo;
+<       joint->breakInfo->flags = 0;
+<       for (int i = 0; i < 3; i++) {
+<         joint->breakInfo->b1MaxF[0] = 0;
+<         joint->breakInfo->b1MaxT[0] = 0;
+<         joint->breakInfo->b2MaxF[0] = 0;
+<         joint->breakInfo->b2MaxT[0] = 0;
+<       }
+< 	  joint->breakInfo->callback = 0;
+<     }
+<     else {
+<       // the joint was already breakable
+<       return;
+<     }
+<   }
+<   else {
+<     // we want this joint to be unbreakable mut we must first check if
+<     // it is alreay unbreakable
+<     if (joint->breakInfo) {
+<       // deallocate the dxJointBreakInfo struct
+<       delete joint->breakInfo;
+<       joint->breakInfo = 0;
+<     }
+<     else {
+<       // the joint was already unbreakable
+<       return;
+<     }
+<   }
+< }
+< 
+< extern "C" void dJointSetBreakCallback (dxJoint *joint, dJointBreakCallback *callbackFunc) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<     dDebug (0, "dJointSetBreakCallback called on unbreakable joint");
+<   }
+< # endif
+<   joint->breakInfo->callback = callbackFunc;
+< }
+< 
+< extern "C" void dJointSetBreakMode (dxJoint *joint, int mode) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<     dDebug (0, "dJointSetBreakMode called on unbreakable joint");
+<   }
+< # endif
+<   joint->breakInfo->flags = mode;
+< }
+< 
+< extern "C" int dJointGetBreakMode (dxJoint *joint) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<     dDebug (0, "dJointGetBreakMode called on unbreakable joint");
+<   }
+< # endif
+<   return joint->breakInfo->flags;
+< }
+< 
+< extern "C" void dJointSetBreakForce (dxJoint *joint, int body, dReal x, dReal y, dReal z) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<   dDebug (0, "dJointSetBreakForce called on unbreakable joint");
+<   }
+< # endif
+<   if (body) {
+< 	joint->breakInfo->b2MaxF[0] = x;
+< 	joint->breakInfo->b2MaxF[1] = y;
+< 	joint->breakInfo->b2MaxF[2] = z;
+<   }
+<   else {
+< 	joint->breakInfo->b1MaxF[0] = x;
+< 	joint->breakInfo->b1MaxF[1] = y;
+< 	joint->breakInfo->b1MaxF[2] = z;
+<   }
+< }
+< 
+< extern "C" void dJointSetBreakTorque (dxJoint *joint, int body, dReal x, dReal y, dReal z) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<   dDebug (0, "dJointSetBreakTorque called on unbreakable joint");
+<   }
+< # endif
+<   if (body) {
+< 	joint->breakInfo->b2MaxT[0] = x;
+< 	joint->breakInfo->b2MaxT[1] = y;
+< 	joint->breakInfo->b2MaxT[2] = z;
+<   }
+<   else {
+< 	joint->breakInfo->b1MaxT[0] = x;
+< 	joint->breakInfo->b1MaxT[1] = y;
+< 	joint->breakInfo->b1MaxT[2] = z;
+<   }
+< }
+< 
+< extern "C" int dJointIsBreakable (dxJoint *joint) {
+<   dAASSERT(joint);
+<   return joint->breakInfo != 0;
+< }
+< 
+< extern "C" void dJointGetBreakForce (dxJoint *joint, int body, dReal *force) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<     dDebug (0, "dJointGetBreakForce called on unbreakable joint");
+<   }
+< # endif
+<   if (body)
+<     for (int i=0; i<3; i++) force[i]=joint->breakInfo->b2MaxF[i];
+<   else
+<     for (int i=0; i<3; i++) force[i]=joint->breakInfo->b1MaxF[i];
+< }
+< 
+< extern "C" void dJointGetBreakTorque (dxJoint *joint, int body, dReal *torque) {
+<   dAASSERT(joint);
+< # ifndef dNODEBUG
+<   // only works for a breakable joint
+<   if (!joint->breakInfo) {
+<     dDebug (0, "dJointGetBreakTorque called on unbreakable joint");
+<   }
+< # endif
+<   if (body)
+<     for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b2MaxT[i];
+<   else
+<     for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b1MaxT[i];
+< }
+< /*************************************************************************/
+<   
+\ No newline at end of file
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/joint.h.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/joint.h.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/joint.h.diff	(revision 216)
@@ -0,0 +1,18 @@
+61,70d60
+< /******************** breakable joint contribution ***********************/
+< struct dxJointBreakInfo : public dBase {
+< 	int flags;
+< 	dReal b1MaxF[3]; // maximum force on body 1
+< 	dReal b1MaxT[3]; // maximum torque on body 1
+< 	dReal b2MaxF[3]; // maximum force on body 2
+< 	dReal b2MaxT[3]; // maximum torque on body 2
+< 	dJointBreakCallback *callback; // function that is called when this joint breaks
+< };
+< /*************************************************************************/
+135,140d124
+<   
+<   /******************** breakable joint contribution ***********************/
+<   // optional break info structure. if this is not NULL the the joint is
+<   // breakable.
+<   dxJointBreakInfo *breakInfo;
+<   /*************************************************************************/
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/objects.h.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/objects.h.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/objects.h.diff	(revision 216)
@@ -0,0 +1,13 @@
+168,179d167
+< /******************** breakable joint contribution ***********************/
+< void dJointSetBreakable (dJointID, int b);
+< void dJointSetBreakCallback (dJointID, dJointBreakCallback *callbackFunc);
+< void dJointSetBreakMode (dJointID, int mode);
+< int dJointGetBreakMode (dJointID);
+< void dJointSetBreakForce (dJointID, int body, dReal x, dReal y, dReal z);
+< void dJointSetBreakTorque (dJointID, int body, dReal x, dReal y, dReal z);
+< int dJointIsBreakable (dJointID);
+< void dJointGetBreakForce (dJointID, int body, dReal *force);
+< void dJointGetBreakTorque (dJointID, int body, dReal *torque);
+< /*************************************************************************/
+< 
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/ode.cpp.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/ode.cpp.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/ode.cpp.diff	(revision 216)
@@ -0,0 +1,28 @@
+212,230d211
+<   /******************** breakable joint contribution ***********************/
+<   dxJoint* nextJ;
+<   if (!world->firstjoint)
+<     nextJ = 0;
+<   else
+<     nextJ = (dxJoint*)world->firstjoint->next;
+<   for (j=world->firstjoint; j; j=nextJ) {
+<   	nextJ = (dxJoint*)j->next;
+< 	// check if joint is breakable and broken
+<     if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) {
+< 		// detach (break) the joint
+<         dJointAttach (j, 0, 0);
+< 		// call the callback function if it is set
+< 		if (j->breakInfo->callback) j->breakInfo->callback (j);
+< 		// finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set
+< 		if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j);
+<       }
+<   }
+<   /*************************************************************************/
+931,933d911
+<   /******************** breakable joint contribution ***********************/
+<   j->breakInfo = 0;
+<   /*************************************************************************/
+1011,1013d988
+<   /******************** breakable joint contribution ***********************/
+<   if (j->breakInfo) delete j->breakInfo;
+<   /*************************************************************************/
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/step.cpp.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/step.cpp.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/step.cpp.diff	(revision 216)
@@ -0,0 +1,130 @@
+966,1066c966,989
+< /******************** breakable joint contribution ***********************/
+<     // this saves us a few dereferences
+<     dxJointBreakInfo *jBI = joint[i]->breakInfo;
+<     // we need joint feedback if the joint is breakable or if the user
+<     // requested feedback.
+< 	if (jBI||fb) {
+<       // we need feedback on the amount of force that this joint is
+<       // applying to the bodies. we use a slightly slower computation
+<       // that splits out the force components and puts them in the
+<       // feedback structure.
+<       dJointFeedback temp_fb; // temporary storage for joint feedback
+< 	  dReal data1[8],data2[8];
+< 	  Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m);
+< 	  dReal *cf1 = cforce + 8*b1->tag;
+< 	  cf1[0] += (temp_fb.f1[0] = data1[0]);
+< 	  cf1[1] += (temp_fb.f1[1] = data1[1]);
+< 	  cf1[2] += (temp_fb.f1[2] = data1[2]);
+< 	  cf1[4] += (temp_fb.t1[0] = data1[4]);
+< 	  cf1[5] += (temp_fb.t1[1] = data1[5]);
+< 	  cf1[6] += (temp_fb.t1[2] = data1[6]);
+< 	  if (b2) {
+< 	    Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
+< 	    dReal *cf2 = cforce + 8*b2->tag;
+< 	    cf2[0] += (temp_fb.f2[0] = data2[0]);
+< 	    cf2[1] += (temp_fb.f2[1] = data2[1]);
+< 	    cf2[2] += (temp_fb.f2[2] = data2[2]);
+< 	    cf2[4] += (temp_fb.t2[0] = data2[4]);
+< 	    cf2[5] += (temp_fb.t2[1] = data2[5]);
+< 	    cf2[6] += (temp_fb.t2[2] = data2[6]);
+< 	  }
+< 	  // if the user requested so we must copy the feedback information to
+< 	  // the feedback struct that the user suplied.
+< 	  if (fb) {
+< 	    // copy temp_fb to fb
+< 	    fb->f1[0] = temp_fb.f1[0];
+< 	    fb->f1[1] = temp_fb.f1[1];
+< 	    fb->f1[2] = temp_fb.f1[2];
+< 	    fb->t1[0] = temp_fb.t1[0];
+< 	    fb->t1[1] = temp_fb.t1[1];
+< 	    fb->t1[2] = temp_fb.t1[2];
+< 	    if (b2) {
+< 	      fb->f2[0] = temp_fb.f2[0];
+< 	      fb->f2[1] = temp_fb.f2[1];
+< 	      fb->f2[2] = temp_fb.f2[2];
+< 	      fb->t2[0] = temp_fb.t2[0];
+< 	      fb->t2[1] = temp_fb.t2[1];
+< 	      fb->t2[2] = temp_fb.t2[2];
+< 	    }
+< 	  }
+< 	  // if the joint is breakable we need to check the breaking conditions
+<       if (jBI) {
+<         dReal relCF1[3];
+< 		dReal relCT1[3];
+< 		// multiply the force and torque vectors by the rotation matrix of body 1
+< 		dMULTIPLY1_331 (&relCF1[0],b1->R,&temp_fb.f1[0]);
+< 		dMULTIPLY1_331 (&relCT1[0],b1->R,&temp_fb.t1[0]);
+< 		if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) {
+< 		  // check if the force is to high
+<           for (int i = 0; i < 3; i++) {
+<             if (relCF1[i] > jBI->b1MaxF[i]) {
+< 		      jBI->flags |= dJOINT_BROKEN;
+< 		      goto doneCheckingBreaks;
+< 		    }
+<           }
+< 		}
+< 		if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) {
+< 		  // check if the torque is to high
+<           for (int i = 0; i < 3; i++) {
+<             if (relCT1[i] > jBI->b1MaxT[i]) {
+< 		      jBI->flags |= dJOINT_BROKEN;
+< 		      goto doneCheckingBreaks;
+<             }
+<           }
+< 		}
+<         if (b2) {
+<           dReal relCF2[3];
+<           dReal relCT2[3];
+<           // multiply the force and torque vectors by the rotation matrix of body 2
+<           dMULTIPLY1_331 (&relCF2[0],b2->R,&temp_fb.f2[0]);
+<           dMULTIPLY1_331 (&relCT2[0],b2->R,&temp_fb.t2[0]);
+< 		  if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) {
+<             // check if the force is to high
+<             for (int i = 0; i < 3; i++) {
+<               if (relCF2[i] > jBI->b2MaxF[i]) {
+<                 jBI->flags |= dJOINT_BROKEN;
+<                 goto doneCheckingBreaks;
+<               }
+<             }
+< 		  }
+< 		  if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) {
+< 		  // check if the torque is to high
+<             for (int i = 0; i < 3; i++) {
+<               if (relCT2[i] > jBI->b2MaxT[i]) {
+<                 jBI->flags |= dJOINT_BROKEN;
+<                 goto doneCheckingBreaks;
+<               }
+<             }
+< 		  }
+<         }
+< 		doneCheckingBreaks:
+< 		;
+---
+>       if (fb) {
+> 	// the user has requested feedback on the amount of force that this
+> 	// joint is applying to the bodies. we use a slightly slower
+> 	// computation that splits out the force components and puts them
+> 	// in the feedback structure.
+> 	dReal data1[8],data2[8];
+> 	Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m);
+> 	dReal *cf1 = cforce + 8*b1->tag;
+> 	cf1[0] += (fb->f1[0] = data1[0]);
+> 	cf1[1] += (fb->f1[1] = data1[1]);
+> 	cf1[2] += (fb->f1[2] = data1[2]);
+> 	cf1[4] += (fb->t1[0] = data1[4]);
+> 	cf1[5] += (fb->t1[1] = data1[5]);
+> 	cf1[6] += (fb->t1[2] = data1[6]);
+> 	if (b2){
+> 	  Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
+> 	  dReal *cf2 = cforce + 8*b2->tag;
+> 	  cf2[0] += (fb->f2[0] = data2[0]);
+> 	  cf2[1] += (fb->f2[1] = data2[1]);
+> 	  cf2[2] += (fb->f2[2] = data2[2]);
+> 	  cf2[4] += (fb->t2[0] = data2[4]);
+> 	  cf2[5] += (fb->t2[1] = data2[5]);
+> 	  cf2[6] += (fb->t2[2] = data2[6]);
+> 	}
+1068,1069d990
+<     }
+< /*************************************************************************/
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/stepfast.cpp.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/stepfast.cpp.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/stepfast.cpp.diff	(revision 216)
@@ -0,0 +1,143 @@
+587,598c587,593
+< /******************** breakable joint contribution ***********************/
+< 	// this saves us a few dereferences
+<     dxJointBreakInfo *jBI = joint->breakInfo;
+<     // we need joint feedback if the joint is breakable or if the user
+<     // requested feedback.
+< 	if (jBI||fb) {
+< 		// we need feedback on the amount of force that this joint is
+< 		// applying to the bodies. we use a slightly slower computation
+< 		// that splits out the force components and puts them in the
+< 		// feedback structure.
+< 		dJointFeedback temp_fb; // temporary storage for joint feedback
+< 		dReal data1[8],data2[8];
+---
+> 	if (fb)
+> 	{
+> 		// the user has requested feedback on the amount of force that this
+> 		// joint is applying to the bodies. we use a slightly slower
+> 		// computation that splits out the force components and puts them
+> 		// in the feedback structure.
+> 		dReal data1[8], data2[8];
+603,608c598,603
+< 			cf1[0] = (temp_fb.f1[0] = data1[0]);
+< 			cf1[1] = (temp_fb.f1[1] = data1[1]);
+< 			cf1[2] = (temp_fb.f1[2] = data1[2]);
+< 			cf1[4] = (temp_fb.t1[0] = data1[4]);
+< 			cf1[5] = (temp_fb.t1[1] = data1[5]);
+< 			cf1[6] = (temp_fb.t1[2] = data1[6]);
+---
+> 			cf1[0] = (fb->f1[0] = data1[0]);
+> 			cf1[1] = (fb->f1[1] = data1[1]);
+> 			cf1[2] = (fb->f1[2] = data1[2]);
+> 			cf1[4] = (fb->t1[0] = data1[4]);
+> 			cf1[5] = (fb->t1[1] = data1[5]);
+> 			cf1[6] = (fb->t1[2] = data1[6]);
+614,691c609,614
+< 			cf2[0] = (temp_fb.f2[0] = data2[0]);
+< 			cf2[1] = (temp_fb.f2[1] = data2[1]);
+< 			cf2[2] = (temp_fb.f2[2] = data2[2]);
+< 			cf2[4] = (temp_fb.t2[0] = data2[4]);
+< 			cf2[5] = (temp_fb.t2[1] = data2[5]);
+< 			cf2[6] = (temp_fb.t2[2] = data2[6]);
+< 		}
+< 		// if the user requested so we must copy the feedback information to
+< 		// the feedback struct that the user suplied.
+< 		if (fb) {
+< 			// copy temp_fb to fb
+< 			fb->f1[0] = temp_fb.f1[0];
+< 			fb->f1[1] = temp_fb.f1[1];
+< 			fb->f1[2] = temp_fb.f1[2];
+< 			fb->t1[0] = temp_fb.t1[0];
+< 			fb->t1[1] = temp_fb.t1[1];
+< 			fb->t1[2] = temp_fb.t1[2];
+< 			if (body[1]) {
+< 				fb->f2[0] = temp_fb.f2[0];
+< 				fb->f2[1] = temp_fb.f2[1];
+< 				fb->f2[2] = temp_fb.f2[2];
+< 				fb->t2[0] = temp_fb.t2[0];
+< 				fb->t2[1] = temp_fb.t2[1];
+< 				fb->t2[2] = temp_fb.t2[2];
+< 			}
+< 		}
+< 		// if the joint is breakable we need to check the breaking conditions
+< 		if (jBI) {
+< 			dReal relCF1[3];
+< 			dReal relCT1[3];
+< 			// multiply the force and torque vectors by the rotation matrix of body 1
+< 			dMULTIPLY1_331 (&relCF1[0],body[0]->R,&temp_fb.f1[0]);
+< 			dMULTIPLY1_331 (&relCT1[0],body[0]->R,&temp_fb.t1[0]);
+< 			if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) {
+< 				// check if the force is to high
+< 				for (int i = 0; i < 3; i++) {
+< 					if (relCF1[i] > jBI->b1MaxF[i]) {
+< 						jBI->flags |= dJOINT_BROKEN;
+< 						goto doneCheckingBreaks;
+< 					}
+< 				}
+< 			}
+< 			if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) {
+< 				// check if the torque is to high
+< 				for (int i = 0; i < 3; i++) {
+< 					if (relCT1[i] > jBI->b1MaxT[i]) {
+< 						jBI->flags |= dJOINT_BROKEN;
+< 						goto doneCheckingBreaks;
+< 					}
+< 				}
+< 			}
+< 			if (body[1]) {
+< 				dReal relCF2[3];
+< 				dReal relCT2[3];
+< 				// multiply the force and torque vectors by the rotation matrix of body 2
+< 				dMULTIPLY1_331 (&relCF2[0],body[1]->R,&temp_fb.f2[0]);
+< 				dMULTIPLY1_331 (&relCT2[0],body[1]->R,&temp_fb.t2[0]);
+< 				if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) {
+< 					// check if the force is to high
+< 					for (int i = 0; i < 3; i++) {
+< 						if (relCF2[i] > jBI->b2MaxF[i]) {
+< 							jBI->flags |= dJOINT_BROKEN;
+< 							goto doneCheckingBreaks;
+< 						}
+< 					}
+< 				}
+< 				if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) {
+< 					// check if the torque is to high
+< 					for (int i = 0; i < 3; i++) {
+< 						if (relCT2[i] > jBI->b2MaxT[i]) {
+< 							jBI->flags |= dJOINT_BROKEN;
+< 							goto doneCheckingBreaks;
+< 						}
+< 					}
+< 				}
+< 			}
+< 			doneCheckingBreaks:
+< 			;
+---
+> 			cf2[0] = (fb->f2[0] = data2[0]);
+> 			cf2[1] = (fb->f2[1] = data2[1]);
+> 			cf2[2] = (fb->f2[2] = data2[2]);
+> 			cf2[4] = (fb->t2[0] = data2[4]);
+> 			cf2[5] = (fb->t2[1] = data2[5]);
+> 			cf2[6] = (fb->t2[2] = data2[6]);
+694d616
+< /*************************************************************************/
+1178,1196d1099
+<   /******************** breakable joint contribution ***********************/
+<   dxJoint* nextJ;
+<   if (!world->firstjoint)
+<     nextJ = 0;
+<   else
+<     nextJ = (dxJoint*)world->firstjoint->next;
+<   for (j=world->firstjoint; j; j=nextJ) {
+<   	nextJ = (dxJoint*)j->next;
+< 	// check if joint is breakable and broken
+<     if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) {
+< 		// detach (break) the joint
+<         dJointAttach (j, 0, 0);
+< 		// call the callback function if it is set
+< 		if (j->breakInfo->callback) j->breakInfo->callback (j);
+< 		// finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set
+< 		if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j);
+<       }
+<   }
+<   /*************************************************************************/
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/test_buggy.cpp.diff
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/test_buggy.cpp.diff	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/diff/test_buggy.cpp.diff	(revision 216)
@@ -0,0 +1,16 @@
+266,270d265
+< 
+<     // breakable joints contribution
+< 		dJointSetBreakable (joint[i], 1);
+< 		dJointSetBreakMode (joint[i], dJOINT_BREAK_AT_FORCE);
+< 		dJointSetBreakForce (joint[i], 0.5);
+298c293
+<   ground_box = dCreateBox (space,2,1.5,5);
+---
+>   ground_box = dCreateBox (space,2,1.5,1);
+300,301c295,296
+<   dRFromAxisAndAngle (R,0,1,0,-0.85);
+<   dGeomSetPosition (ground_box,5,0,-1);
+---
+>   dRFromAxisAndAngle (R,0,1,0,-0.15);
+>   dGeomSetPosition (ground_box,2,0,-0.34);
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/joint.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/joint.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/joint.cpp	(revision 216)
@@ -0,0 +1,2803 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+design note: the general principle for giving a joint the option of connecting
+to the static environment (i.e. the absolute frame) is to check the second
+body (joint->node[1].body), and if it is zero then behave as if its body
+transform is the identity.
+
+*/
+
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/matrix.h>
+#include "joint.h"
+
+//****************************************************************************
+// externs
+
+extern "C" void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz);
+extern "C" void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz);
+
+//****************************************************************************
+// utility
+
+// set three "ball-and-socket" rows in the constraint equation, and the
+// corresponding right hand side.
+
+static inline void setBall (dxJoint *joint, dxJoint::Info2 *info,
+			    dVector3 anchor1, dVector3 anchor2)
+{
+  // anchor points in global coordinates with respect to body PORs.
+  dVector3 a1,a2;
+
+  int s = info->rowskip;
+
+  // set jacobian
+  info->J1l[0] = 1;
+  info->J1l[s+1] = 1;
+  info->J1l[2*s+2] = 1;
+  dMULTIPLY0_331 (a1,joint->node[0].body->R,anchor1);
+  dCROSSMAT (info->J1a,a1,s,-,+);
+  if (joint->node[1].body) {
+    info->J2l[0] = -1;
+    info->J2l[s+1] = -1;
+    info->J2l[2*s+2] = -1;
+    dMULTIPLY0_331 (a2,joint->node[1].body->R,anchor2);
+    dCROSSMAT (info->J2a,a2,s,+,-);
+  }
+
+  // set right hand side
+  dReal k = info->fps * info->erp;
+  if (joint->node[1].body) {
+    for (int j=0; j<3; j++) {
+      info->c[j] = k * (a2[j] + joint->node[1].body->pos[j] -
+			a1[j] - joint->node[0].body->pos[j]);
+    }
+  }
+  else {
+    for (int j=0; j<3; j++) {
+      info->c[j] = k * (anchor2[j] - a1[j] -
+			joint->node[0].body->pos[j]);
+    }
+  }
+}
+
+
+// this is like setBall(), except that `axis' is a unit length vector
+// (in global coordinates) that should be used for the first jacobian
+// position row (the other two row vectors will be derived from this).
+// `erp1' is the erp value to use along the axis.
+
+static inline void setBall2 (dxJoint *joint, dxJoint::Info2 *info,
+			    dVector3 anchor1, dVector3 anchor2,
+			    dVector3 axis, dReal erp1)
+{
+  // anchor points in global coordinates with respect to body PORs.
+  dVector3 a1,a2;
+
+  int i,s = info->rowskip;
+
+  // get vectors normal to the axis. in setBall() axis,q1,q2 is [1 0 0],
+  // [0 1 0] and [0 0 1], which makes everything much easier.
+  dVector3 q1,q2;
+  dPlaneSpace (axis,q1,q2);
+
+  // set jacobian
+  for (i=0; i<3; i++) info->J1l[i] = axis[i];
+  for (i=0; i<3; i++) info->J1l[s+i] = q1[i];
+  for (i=0; i<3; i++) info->J1l[2*s+i] = q2[i];
+  dMULTIPLY0_331 (a1,joint->node[0].body->R,anchor1);
+  dCROSS (info->J1a,=,a1,axis);
+  dCROSS (info->J1a+s,=,a1,q1);
+  dCROSS (info->J1a+2*s,=,a1,q2);
+  if (joint->node[1].body) {
+    for (i=0; i<3; i++) info->J2l[i] = -axis[i];
+    for (i=0; i<3; i++) info->J2l[s+i] = -q1[i];
+    for (i=0; i<3; i++) info->J2l[2*s+i] = -q2[i];
+    dMULTIPLY0_331 (a2,joint->node[1].body->R,anchor2);
+    dCROSS (info->J2a,= -,a2,axis);
+    dCROSS (info->J2a+s,= -,a2,q1);
+    dCROSS (info->J2a+2*s,= -,a2,q2);
+  }
+
+  // set right hand side - measure error along (axis,q1,q2)
+  dReal k1 = info->fps * erp1;
+  dReal k = info->fps * info->erp;
+
+  for (i=0; i<3; i++) a1[i] += joint->node[0].body->pos[i];
+  if (joint->node[1].body) {
+    for (i=0; i<3; i++) a2[i] += joint->node[1].body->pos[i];
+    info->c[0] = k1 * (dDOT(axis,a2) - dDOT(axis,a1));
+    info->c[1] = k * (dDOT(q1,a2) - dDOT(q1,a1));
+    info->c[2] = k * (dDOT(q2,a2) - dDOT(q2,a1));
+  }
+  else {
+    info->c[0] = k1 * (dDOT(axis,anchor2) - dDOT(axis,a1));
+    info->c[1] = k * (dDOT(q1,anchor2) - dDOT(q1,a1));
+    info->c[2] = k * (dDOT(q2,anchor2) - dDOT(q2,a1));
+  }
+}
+
+
+// set three orientation rows in the constraint equation, and the
+// corresponding right hand side.
+
+static void setFixedOrientation(dxJoint *joint, dxJoint::Info2 *info, dQuaternion qrel, int start_row)
+{
+  int s = info->rowskip;
+  int start_index = start_row * s;
+
+  // 3 rows to make body rotations equal
+  info->J1a[start_index] = 1;
+  info->J1a[start_index + s + 1] = 1;
+  info->J1a[start_index + s*2+2] = 1;
+  if (joint->node[1].body) {
+    info->J2a[start_index] = -1;
+    info->J2a[start_index + s+1] = -1;
+    info->J2a[start_index + s*2+2] = -1;
+  }
+
+  // compute the right hand side. the first three elements will result in
+  // relative angular velocity of the two bodies - this is set to bring them
+  // back into alignment. the correcting angular velocity is
+  //   |angular_velocity| = angle/time = erp*theta / stepsize
+  //                      = (erp*fps) * theta
+  //    angular_velocity  = |angular_velocity| * u
+  //                      = (erp*fps) * theta * u
+  // where rotation along unit length axis u by theta brings body 2's frame
+  // to qrel with respect to body 1's frame. using a small angle approximation
+  // for sin(), this gives
+  //    angular_velocity  = (erp*fps) * 2 * v
+  // where the quaternion of the relative rotation between the two bodies is
+  //    q = [cos(theta/2) sin(theta/2)*u] = [s v]
+
+  // get qerr = relative rotation (rotation error) between two bodies
+  dQuaternion qerr,e;
+  if (joint->node[1].body) {
+    dQuaternion qq;
+    dQMultiply1 (qq,joint->node[0].body->q,joint->node[1].body->q);
+    dQMultiply2 (qerr,qq,qrel);
+  }
+  else {
+    dQMultiply3 (qerr,joint->node[0].body->q,qrel);
+  }
+  if (qerr[0] < 0) {
+    qerr[1] = -qerr[1];		// adjust sign of qerr to make theta small
+    qerr[2] = -qerr[2];
+    qerr[3] = -qerr[3];
+  }
+  dMULTIPLY0_331 (e,joint->node[0].body->R,qerr+1); // @@@ bad SIMD padding!
+  dReal k = info->fps * info->erp;
+  info->c[start_row] = 2*k * e[0];
+  info->c[start_row+1] = 2*k * e[1];
+  info->c[start_row+2] = 2*k * e[2];
+}
+
+
+// compute anchor points relative to bodies
+
+static void setAnchors (dxJoint *j, dReal x, dReal y, dReal z,
+			dVector3 anchor1, dVector3 anchor2)
+{
+  if (j->node[0].body) {
+    dReal q[4];
+    q[0] = x - j->node[0].body->pos[0];
+    q[1] = y - j->node[0].body->pos[1];
+    q[2] = z - j->node[0].body->pos[2];
+    q[3] = 0;
+    dMULTIPLY1_331 (anchor1,j->node[0].body->R,q);
+    if (j->node[1].body) {
+      q[0] = x - j->node[1].body->pos[0];
+      q[1] = y - j->node[1].body->pos[1];
+      q[2] = z - j->node[1].body->pos[2];
+      q[3] = 0;
+      dMULTIPLY1_331 (anchor2,j->node[1].body->R,q);
+    }
+    else {
+      anchor2[0] = x;
+      anchor2[1] = y;
+      anchor2[2] = z;
+    }
+  }
+  anchor1[3] = 0;
+  anchor2[3] = 0;
+}
+
+
+// compute axes relative to bodies. either axis1 or axis2 can be 0.
+
+static void setAxes (dxJoint *j, dReal x, dReal y, dReal z,
+		     dVector3 axis1, dVector3 axis2)
+{
+  if (j->node[0].body) {
+    dReal q[4];
+    q[0] = x;
+    q[1] = y;
+    q[2] = z;
+    q[3] = 0;
+    dNormalize3 (q);
+    if (axis1) {
+      dMULTIPLY1_331 (axis1,j->node[0].body->R,q);
+      axis1[3] = 0;
+    }
+    if (axis2) {
+      if (j->node[1].body) {
+	dMULTIPLY1_331 (axis2,j->node[1].body->R,q);
+      }
+      else {
+	axis2[0] = x;
+	axis2[1] = y;
+	axis2[2] = z;
+      }
+      axis2[3] = 0;
+    }
+  }
+}
+
+
+static void getAnchor (dxJoint *j, dVector3 result, dVector3 anchor1)
+{
+  if (j->node[0].body) {
+    dMULTIPLY0_331 (result,j->node[0].body->R,anchor1);
+    result[0] += j->node[0].body->pos[0];
+    result[1] += j->node[0].body->pos[1];
+    result[2] += j->node[0].body->pos[2];
+  }
+}
+
+
+static void getAnchor2 (dxJoint *j, dVector3 result, dVector3 anchor2)
+{
+  if (j->node[1].body) {
+    dMULTIPLY0_331 (result,j->node[1].body->R,anchor2);
+    result[0] += j->node[1].body->pos[0];
+    result[1] += j->node[1].body->pos[1];
+    result[2] += j->node[1].body->pos[2];
+  }
+  else {
+    result[0] = anchor2[0];
+    result[1] = anchor2[1];
+    result[2] = anchor2[2];
+  }
+}
+
+
+static void getAxis (dxJoint *j, dVector3 result, dVector3 axis1)
+{
+  if (j->node[0].body) {
+    dMULTIPLY0_331 (result,j->node[0].body->R,axis1);
+  }
+}
+
+
+static void getAxis2 (dxJoint *j, dVector3 result, dVector3 axis2)
+{
+  if (j->node[1].body) {
+    dMULTIPLY0_331 (result,j->node[1].body->R,axis2);
+  }
+  else {
+    result[0] = axis2[0];
+    result[1] = axis2[1];
+    result[2] = axis2[2];
+  }
+}
+
+
+static dReal getHingeAngleFromRelativeQuat (dQuaternion qrel, dVector3 axis)
+{
+  // the angle between the two bodies is extracted from the quaternion that
+  // represents the relative rotation between them. recall that a quaternion
+  // q is:
+  //    [s,v] = [ cos(theta/2) , sin(theta/2) * u ]
+  // where s is a scalar and v is a 3-vector. u is a unit length axis and
+  // theta is a rotation along that axis. we can get theta/2 by:
+  //    theta/2 = atan2 ( sin(theta/2) , cos(theta/2) )
+  // but we can't get sin(theta/2) directly, only its absolute value, i.e.:
+  //    |v| = |sin(theta/2)| * |u|
+  //        = |sin(theta/2)|
+  // using this value will have a strange effect. recall that there are two
+  // quaternion representations of a given rotation, q and -q. typically as
+  // a body rotates along the axis it will go through a complete cycle using
+  // one representation and then the next cycle will use the other
+  // representation. this corresponds to u pointing in the direction of the
+  // hinge axis and then in the opposite direction. the result is that theta
+  // will appear to go "backwards" every other cycle. here is a fix: if u
+  // points "away" from the direction of the hinge (motor) axis (i.e. more
+  // than 90 degrees) then use -q instead of q. this represents the same
+  // rotation, but results in the cos(theta/2) value being sign inverted.
+
+  // extract the angle from the quaternion. cost2 = cos(theta/2),
+  // sint2 = |sin(theta/2)|
+  dReal cost2 = qrel[0];
+  dReal sint2 = dSqrt (qrel[1]*qrel[1]+qrel[2]*qrel[2]+qrel[3]*qrel[3]);
+  dReal theta = (dDOT(qrel+1,axis) >= 0) ?	// @@@ padding assumptions
+    (2 * dAtan2(sint2,cost2)) :		// if u points in direction of axis
+    (2 * dAtan2(sint2,-cost2));		// if u points in opposite direction
+
+  // the angle we get will be between 0..2*pi, but we want to return angles
+  // between -pi..pi
+  if (theta > M_PI) theta -= 2*M_PI;
+
+  // the angle we've just extracted has the wrong sign
+  theta = -theta;
+
+  return theta;
+}
+
+
+// given two bodies (body1,body2), the hinge axis that they are connected by
+// w.r.t. body1 (axis), and the initial relative orientation between them
+// (q_initial), return the relative rotation angle. the initial relative
+// orientation corresponds to an angle of zero. if body2 is 0 then measure the
+// angle between body1 and the static frame.
+//
+// this will not return the correct angle if the bodies rotate along any axis
+// other than the given hinge axis.
+
+static dReal getHingeAngle (dxBody *body1, dxBody *body2, dVector3 axis,
+			    dQuaternion q_initial)
+{
+  // get qrel = relative rotation between the two bodies
+  dQuaternion qrel;
+  if (body2) {
+    dQuaternion qq;
+    dQMultiply1 (qq,body1->q,body2->q);
+    dQMultiply2 (qrel,qq,q_initial);
+  }
+  else {
+    // pretend body2->q is the identity
+    dQMultiply3 (qrel,body1->q,q_initial);
+  }
+
+  return getHingeAngleFromRelativeQuat (qrel,axis);
+}
+
+//****************************************************************************
+// dxJointLimitMotor
+
+void dxJointLimitMotor::init (dxWorld *world)
+{
+  vel = 0;
+  fmax = 0;
+  lostop = -dInfinity;
+  histop = dInfinity;
+  fudge_factor = 1;
+  normal_cfm = world->global_cfm;
+  stop_erp = world->global_erp;
+  stop_cfm = world->global_cfm;
+  bounce = 0;
+  limit = 0;
+  limit_err = 0;
+}
+
+
+void dxJointLimitMotor::set (int num, dReal value)
+{
+  switch (num) {
+  case dParamLoStop:
+    if (value <= histop) lostop = value;
+    break;
+  case dParamHiStop:
+    if (value >= lostop) histop = value;
+    break;
+  case dParamVel:
+    vel = value;
+    break;
+  case dParamFMax:
+    if (value >= 0) fmax = value;
+    break;
+  case dParamFudgeFactor:
+    if (value >= 0 && value <= 1) fudge_factor = value;
+    break;
+  case dParamBounce:
+    bounce = value;
+    break;
+  case dParamCFM:
+    normal_cfm = value;
+    break;
+  case dParamStopERP:
+    stop_erp = value;
+    break;
+  case dParamStopCFM:
+    stop_cfm = value;
+    break;
+  }
+}
+
+
+dReal dxJointLimitMotor::get (int num)
+{
+  switch (num) {
+  case dParamLoStop: return lostop;
+  case dParamHiStop: return histop;
+  case dParamVel: return vel;
+  case dParamFMax: return fmax;
+  case dParamFudgeFactor: return fudge_factor;
+  case dParamBounce: return bounce;
+  case dParamCFM: return normal_cfm;
+  case dParamStopERP: return stop_erp;
+  case dParamStopCFM: return stop_cfm;
+  default: return 0;
+  }
+}
+
+
+int dxJointLimitMotor::testRotationalLimit (dReal angle)
+{
+  if (angle <= lostop) {
+    limit = 1;
+    limit_err = angle - lostop;
+    return 1;
+  }
+  else if (angle >= histop) {
+    limit = 2;
+    limit_err = angle - histop;
+    return 1;
+  }
+  else {
+    limit = 0;
+    return 0;
+  }
+}
+
+
+int dxJointLimitMotor::addLimot (dxJoint *joint,
+				 dxJoint::Info2 *info, int row,
+				 dVector3 ax1, int rotational)
+{
+  int srow = row * info->rowskip;
+
+  // if the joint is powered, or has joint limits, add in the extra row
+  int powered = fmax > 0;
+  if (powered || limit) {
+    dReal *J1 = rotational ? info->J1a : info->J1l;
+    dReal *J2 = rotational ? info->J2a : info->J2l;
+
+    J1[srow+0] = ax1[0];
+    J1[srow+1] = ax1[1];
+    J1[srow+2] = ax1[2];
+    if (joint->node[1].body) {
+      J2[srow+0] = -ax1[0];
+      J2[srow+1] = -ax1[1];
+      J2[srow+2] = -ax1[2];
+    }
+
+    // linear limot torque decoupling step:
+    //
+    // if this is a linear limot (e.g. from a slider), we have to be careful
+    // that the linear constraint forces (+/- ax1) applied to the two bodies
+    // do not create a torque couple. in other words, the points that the
+    // constraint force is applied at must lie along the same ax1 axis.
+    // a torque couple will result in powered or limited slider-jointed free
+    // bodies from gaining angular momentum.
+    // the solution used here is to apply the constraint forces at the point
+    // halfway between the body centers. there is no penalty (other than an
+    // extra tiny bit of computation) in doing this adjustment. note that we
+    // only need to do this if the constraint connects two bodies.
+
+    dVector3 ltd;	// Linear Torque Decoupling vector (a torque)
+    if (!rotational && joint->node[1].body) {
+      dVector3 c;
+      c[0]=REAL(0.5)*(joint->node[1].body->pos[0]-joint->node[0].body->pos[0]);
+      c[1]=REAL(0.5)*(joint->node[1].body->pos[1]-joint->node[0].body->pos[1]);
+      c[2]=REAL(0.5)*(joint->node[1].body->pos[2]-joint->node[0].body->pos[2]);
+      dCROSS (ltd,=,c,ax1);
+      info->J1a[srow+0] = ltd[0];
+      info->J1a[srow+1] = ltd[1];
+      info->J1a[srow+2] = ltd[2];
+      info->J2a[srow+0] = ltd[0];
+      info->J2a[srow+1] = ltd[1];
+      info->J2a[srow+2] = ltd[2];
+    }
+
+    // if we're limited low and high simultaneously, the joint motor is
+    // ineffective
+    if (limit && (lostop == histop)) powered = 0;
+
+    if (powered) {
+      info->cfm[row] = normal_cfm;
+      if (! limit) {
+	info->c[row] = vel;
+	info->lo[row] = -fmax;
+	info->hi[row] = fmax;
+      }
+      else {
+	// the joint is at a limit, AND is being powered. if the joint is
+	// being powered into the limit then we apply the maximum motor force
+	// in that direction, because the motor is working against the
+	// immovable limit. if the joint is being powered away from the limit
+	// then we have problems because actually we need *two* lcp
+	// constraints to handle this case. so we fake it and apply some
+	// fraction of the maximum force. the fraction to use can be set as
+	// a fudge factor.
+
+	dReal fm = fmax;
+	if (vel > 0) fm = -fm;
+
+	// if we're powering away from the limit, apply the fudge factor
+	if ((limit==1 && vel > 0) || (limit==2 && vel < 0)) fm *= fudge_factor;
+
+	if (rotational) {
+	  dBodyAddTorque (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],
+			  -fm*ax1[2]);
+	  if (joint->node[1].body)
+	    dBodyAddTorque (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]);
+	}
+	else {
+	  dBodyAddForce (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],-fm*ax1[2]);
+	  if (joint->node[1].body) {
+	    dBodyAddForce (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]);
+
+	    // linear limot torque decoupling step: refer to above discussion
+	    dBodyAddTorque (joint->node[0].body,-fm*ltd[0],-fm*ltd[1],
+			    -fm*ltd[2]);
+	    dBodyAddTorque (joint->node[1].body,-fm*ltd[0],-fm*ltd[1],
+			    -fm*ltd[2]);
+	  }
+	}
+      }
+    }
+
+    if (limit) {
+      dReal k = info->fps * stop_erp;
+      info->c[row] = -k * limit_err;
+      info->cfm[row] = stop_cfm;
+
+      if (lostop == histop) {
+	// limited low and high simultaneously
+	info->lo[row] = -dInfinity;
+	info->hi[row] = dInfinity;
+      }
+      else {
+	if (limit == 1) {
+	  // low limit
+	  info->lo[row] = 0;
+	  info->hi[row] = dInfinity;
+	}
+	else {
+	  // high limit
+	  info->lo[row] = -dInfinity;
+	  info->hi[row] = 0;
+	}
+
+	// deal with bounce
+	if (bounce > 0) {
+	  // calculate joint velocity
+	  dReal vel;
+	  if (rotational) {
+	    vel = dDOT(joint->node[0].body->avel,ax1);
+	    if (joint->node[1].body)
+	      vel -= dDOT(joint->node[1].body->avel,ax1);
+	  }
+	  else {
+	    vel = dDOT(joint->node[0].body->lvel,ax1);
+	    if (joint->node[1].body)
+	      vel -= dDOT(joint->node[1].body->lvel,ax1);
+	  }
+
+	  // only apply bounce if the velocity is incoming, and if the
+	  // resulting c[] exceeds what we already have.
+	  if (limit == 1) {
+	    // low limit
+	    if (vel < 0) {
+	      dReal newc = -bounce * vel;
+	      if (newc > info->c[row]) info->c[row] = newc;
+	    }
+	  }
+	  else {
+	    // high limit - all those computations are reversed
+	    if (vel > 0) {
+	      dReal newc = -bounce * vel;
+	      if (newc < info->c[row]) info->c[row] = newc;
+	    }
+	  }
+	}
+      }
+    }
+    return 1;
+  }
+  else return 0;
+}
+
+//****************************************************************************
+// ball and socket
+
+static void ballInit (dxJointBall *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+}
+
+
+static void ballGetInfo1 (dxJointBall *j, dxJoint::Info1 *info)
+{
+  info->m = 3;
+  info->nub = 3;
+}
+
+
+static void ballGetInfo2 (dxJointBall *joint, dxJoint::Info2 *info)
+{
+  setBall (joint,info,joint->anchor1,joint->anchor2);
+}
+
+
+extern "C" void dJointSetBallAnchor (dxJointBall *joint,
+				     dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+}
+
+
+extern "C" void dJointGetBallAnchor (dxJointBall *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+extern "C" void dJointGetBallAnchor2 (dxJointBall *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+dxJoint::Vtable __dball_vtable = {
+  sizeof(dxJointBall),
+  (dxJoint::init_fn*) ballInit,
+  (dxJoint::getInfo1_fn*) ballGetInfo1,
+  (dxJoint::getInfo2_fn*) ballGetInfo2,
+  dJointTypeBall};
+
+//****************************************************************************
+// hinge
+
+static void hingeInit (dxJointHinge *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->axis2,4);
+  j->axis2[0] = 1;
+  dSetZero (j->qrel,4);
+  j->limot.init (j->world);
+}
+
+
+static void hingeGetInfo1 (dxJointHinge *j, dxJoint::Info1 *info)
+{
+  info->nub = 5;
+
+  // see if joint is powered
+  if (j->limot.fmax > 0)
+    info->m = 6;	// powered hinge needs an extra constraint row
+  else info->m = 5;
+
+  // see if we're at a joint limit.
+  if ((j->limot.lostop >= -M_PI || j->limot.histop <= M_PI) &&
+       j->limot.lostop <= j->limot.histop) {
+    dReal angle = getHingeAngle (j->node[0].body,j->node[1].body,j->axis1,
+				 j->qrel);
+    if (j->limot.testRotationalLimit (angle)) info->m = 6;
+  }
+}
+
+
+static void hingeGetInfo2 (dxJointHinge *joint, dxJoint::Info2 *info)
+{
+  // set the three ball-and-socket rows
+  setBall (joint,info,joint->anchor1,joint->anchor2);
+
+  // set the two hinge rows. the hinge axis should be the only unconstrained
+  // rotational axis, the angular velocity of the two bodies perpendicular to
+  // the hinge axis should be equal. thus the constraint equations are
+  //    p*w1 - p*w2 = 0
+  //    q*w1 - q*w2 = 0
+  // where p and q are unit vectors normal to the hinge axis, and w1 and w2
+  // are the angular velocity vectors of the two bodies.
+
+  dVector3 ax1;  // length 1 joint axis in global coordinates, from 1st body
+  dVector3 p,q;  // plane space vectors for ax1
+  dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1);
+  dPlaneSpace (ax1,p,q);
+
+  int s3=3*info->rowskip;
+  int s4=4*info->rowskip;
+
+  info->J1a[s3+0] = p[0];
+  info->J1a[s3+1] = p[1];
+  info->J1a[s3+2] = p[2];
+  info->J1a[s4+0] = q[0];
+  info->J1a[s4+1] = q[1];
+  info->J1a[s4+2] = q[2];
+
+  if (joint->node[1].body) {
+    info->J2a[s3+0] = -p[0];
+    info->J2a[s3+1] = -p[1];
+    info->J2a[s3+2] = -p[2];
+    info->J2a[s4+0] = -q[0];
+    info->J2a[s4+1] = -q[1];
+    info->J2a[s4+2] = -q[2];
+  }
+
+  // compute the right hand side of the constraint equation. set relative
+  // body velocities along p and q to bring the hinge back into alignment.
+  // if ax1,ax2 are the unit length hinge axes as computed from body1 and
+  // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
+  // if `theta' is the angle between ax1 and ax2, we need an angular velocity
+  // along u to cover angle erp*theta in one step :
+  //   |angular_velocity| = angle/time = erp*theta / stepsize
+  //                      = (erp*fps) * theta
+  //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+  //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+  // ...as ax1 and ax2 are unit length. if theta is smallish,
+  // theta ~= sin(theta), so
+  //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+  // ax1 x ax2 is in the plane space of ax1, so we project the angular
+  // velocity to p and q to find the right hand side.
+
+  dVector3 ax2,b;
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2);
+  }
+  else {
+    ax2[0] = joint->axis2[0];
+    ax2[1] = joint->axis2[1];
+    ax2[2] = joint->axis2[2];
+  }
+  dCROSS (b,=,ax1,ax2);
+  dReal k = info->fps * info->erp;
+  info->c[3] = k * dDOT(b,p);
+  info->c[4] = k * dDOT(b,q);
+
+  // if the hinge is powered, or has joint limits, add in the stuff
+  joint->limot.addLimot (joint,info,5,ax1,1);
+}
+
+
+// compute initial relative rotation body1 -> body2, or env -> body1
+
+static void hingeComputeInitialRelativeRotation (dxJointHinge *joint)
+{
+  if (joint->node[0].body) {
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+    }
+    else {
+      // set joint->qrel to the transpose of the first body q
+      joint->qrel[0] = joint->node[0].body->q[0];
+      for (int i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+    }
+  }
+}
+
+
+extern "C" void dJointSetHingeAnchor (dxJointHinge *joint,
+				      dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+  hingeComputeInitialRelativeRotation (joint);
+}
+
+
+extern "C" void dJointSetHingeAxis (dxJointHinge *joint,
+				    dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  setAxes (joint,x,y,z,joint->axis1,joint->axis2);
+  hingeComputeInitialRelativeRotation (joint);
+}
+
+
+extern "C" void dJointGetHingeAnchor (dxJointHinge *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+extern "C" void dJointGetHingeAnchor2 (dxJointHinge *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+extern "C" void dJointGetHingeAxis (dxJointHinge *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  getAxis (joint,result,joint->axis1);
+}
+
+
+extern "C" void dJointSetHingeParam (dxJointHinge *joint,
+				     int parameter, dReal value)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  joint->limot.set (parameter,value);
+}
+
+
+extern "C" dReal dJointGetHingeParam (dxJointHinge *joint, int parameter)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  return joint->limot.get (parameter);
+}
+
+
+extern "C" dReal dJointGetHingeAngle (dxJointHinge *joint)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  if (joint->node[0].body) {
+    dReal ang = getHingeAngle (joint->node[0].body,joint->node[1].body,joint->axis1,
+			  joint->qrel);
+	if (joint->flags & dJOINT_REVERSE)
+	   return -ang;
+	else
+	   return ang;
+  }
+  else return 0;
+}
+
+
+extern "C" dReal dJointGetHingeAngleRate (dxJointHinge *joint)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge");
+  if (joint->node[0].body) {
+    dVector3 axis;
+    dMULTIPLY0_331 (axis,joint->node[0].body->R,joint->axis1);
+    dReal rate = dDOT(axis,joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
+    if (joint->flags & dJOINT_REVERSE) rate = - rate;
+    return rate;
+  }
+  else return 0;
+}
+
+
+extern "C" void dJointAddHingeTorque (dxJointHinge *joint, dReal torque)
+{
+  dVector3 axis;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge");
+
+  if (joint->flags & dJOINT_REVERSE)
+    torque = -torque;
+
+  getAxis (joint,axis,joint->axis1);
+  axis[0] *= torque;
+  axis[1] *= torque;
+  axis[2] *= torque;
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
+}
+
+
+dxJoint::Vtable __dhinge_vtable = {
+  sizeof(dxJointHinge),
+  (dxJoint::init_fn*) hingeInit,
+  (dxJoint::getInfo1_fn*) hingeGetInfo1,
+  (dxJoint::getInfo2_fn*) hingeGetInfo2,
+  dJointTypeHinge};
+
+//****************************************************************************
+// slider
+
+static void sliderInit (dxJointSlider *j)
+{
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->qrel,4);
+  dSetZero (j->offset,4);
+  j->limot.init (j->world);
+}
+
+
+extern "C" dReal dJointGetSliderPosition (dxJointSlider *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+
+  // get axis1 in global coordinates
+  dVector3 ax1,q;
+  dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1);
+
+  if (joint->node[1].body) {
+    // get body2 + offset point in global coordinates
+    dMULTIPLY0_331 (q,joint->node[1].body->R,joint->offset);
+    for (int i=0; i<3; i++) q[i] = joint->node[0].body->pos[i] - q[i] -
+			      joint->node[1].body->pos[i];
+  }
+  else {
+    for (int i=0; i<3; i++) q[i] = joint->node[0].body->pos[i] -
+			      joint->offset[i];
+
+  }
+  return dDOT(ax1,q);
+}
+
+
+extern "C" dReal dJointGetSliderPositionRate (dxJointSlider *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+
+  // get axis1 in global coordinates
+  dVector3 ax1;
+  dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1);
+
+  if (joint->node[1].body) {
+    return dDOT(ax1,joint->node[0].body->lvel) -
+      dDOT(ax1,joint->node[1].body->lvel);
+  }
+  else {
+    return dDOT(ax1,joint->node[0].body->lvel);
+  }
+}
+
+
+static void sliderGetInfo1 (dxJointSlider *j, dxJoint::Info1 *info)
+{
+  info->nub = 5;
+
+  // see if joint is powered
+  if (j->limot.fmax > 0)
+    info->m = 6;	// powered slider needs an extra constraint row
+  else info->m = 5;
+
+  // see if we're at a joint limit.
+  j->limot.limit = 0;
+  if ((j->limot.lostop > -dInfinity || j->limot.histop < dInfinity) &&
+      j->limot.lostop <= j->limot.histop) {
+    // measure joint position
+    dReal pos = dJointGetSliderPosition (j);
+    if (pos <= j->limot.lostop) {
+      j->limot.limit = 1;
+      j->limot.limit_err = pos - j->limot.lostop;
+      info->m = 6;
+    }
+    else if (pos >= j->limot.histop) {
+      j->limot.limit = 2;
+      j->limot.limit_err = pos - j->limot.histop;
+      info->m = 6;
+    }
+  }
+}
+
+
+static void sliderGetInfo2 (dxJointSlider *joint, dxJoint::Info2 *info)
+{
+  int i,s = info->rowskip;
+  int s2=2*s,s3=3*s,s4=4*s;
+
+  // pull out pos and R for both bodies. also get the `connection'
+  // vector pos2-pos1.
+
+  dReal *pos1,*pos2,*R1,*R2;
+  dVector3 c;
+  pos1 = joint->node[0].body->pos;
+  R1 = joint->node[0].body->R;
+  if (joint->node[1].body) {
+    pos2 = joint->node[1].body->pos;
+    R2 = joint->node[1].body->R;
+    for (i=0; i<3; i++) c[i] = pos2[i] - pos1[i];
+  }
+  else {
+    pos2 = 0;
+    R2 = 0;
+  }
+
+  // 3 rows to make body rotations equal
+  setFixedOrientation(joint, info, joint->qrel, 0);
+
+  // remaining two rows. we want: vel2 = vel1 + w1 x c ... but this would
+  // result in three equations, so we project along the planespace vectors
+  // so that sliding along the slider axis is disregarded. for symmetry we
+  // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2.
+
+  dVector3 ax1;	// joint axis in global coordinates (unit length)
+  dVector3 p,q;	// plane space of ax1
+  dMULTIPLY0_331 (ax1,R1,joint->axis1);
+  dPlaneSpace (ax1,p,q);
+  if (joint->node[1].body) {
+    dVector3 tmp;
+    dCROSS (tmp, = REAL(0.5) * ,c,p);
+    for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i];
+    for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i];
+    dCROSS (tmp, = REAL(0.5) * ,c,q);
+    for (i=0; i<3; i++) info->J2a[s4+i] = tmp[i];
+    for (i=0; i<3; i++) info->J2a[s4+i] = tmp[i];
+    for (i=0; i<3; i++) info->J2l[s3+i] = -p[i];
+    for (i=0; i<3; i++) info->J2l[s4+i] = -q[i];
+  }
+  for (i=0; i<3; i++) info->J1l[s3+i] = p[i];
+  for (i=0; i<3; i++) info->J1l[s4+i] = q[i];
+
+  // compute last two elements of right hand side. we want to align the offset
+  // point (in body 2's frame) with the center of body 1.
+  dReal k = info->fps * info->erp;
+  if (joint->node[1].body) {
+    dVector3 ofs;		// offset point in global coordinates
+    dMULTIPLY0_331 (ofs,R2,joint->offset);
+    for (i=0; i<3; i++) c[i] += ofs[i];
+    info->c[3] = k * dDOT(p,c);
+    info->c[4] = k * dDOT(q,c);
+  }
+  else {
+    dVector3 ofs;		// offset point in global coordinates
+    for (i=0; i<3; i++) ofs[i] = joint->offset[i] - pos1[i];
+    info->c[3] = k * dDOT(p,ofs);
+    info->c[4] = k * dDOT(q,ofs);
+  }
+
+  // if the slider is powered, or has joint limits, add in the extra row
+  joint->limot.addLimot (joint,info,5,ax1,0);
+}
+
+
+extern "C" void dJointSetSliderAxis (dxJointSlider *joint,
+				     dReal x, dReal y, dReal z)
+{
+  int i;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  setAxes (joint,x,y,z,joint->axis1,0);
+
+  // compute initial relative rotation body1 -> body2, or env -> body1
+  // also compute center of body1 w.r.t body 2
+  if (joint->node[1].body) {
+    dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+    dVector3 c;
+    for (i=0; i<3; i++)
+      c[i] = joint->node[0].body->pos[i] - joint->node[1].body->pos[i];
+    dMULTIPLY1_331 (joint->offset,joint->node[1].body->R,c);
+  }
+  else {
+    // set joint->qrel to the transpose of the first body's q
+    joint->qrel[0] = joint->node[0].body->q[0];
+    for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+    for (i=0; i<3; i++) joint->offset[i] = joint->node[0].body->pos[i];
+  }
+}
+
+
+extern "C" void dJointGetSliderAxis (dxJointSlider *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  getAxis (joint,result,joint->axis1);
+}
+
+
+extern "C" void dJointSetSliderParam (dxJointSlider *joint,
+				      int parameter, dReal value)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  joint->limot.set (parameter,value);
+}
+
+
+extern "C" dReal dJointGetSliderParam (dxJointSlider *joint, int parameter)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  return joint->limot.get (parameter);
+}
+
+
+extern "C" void dJointAddSliderForce (dxJointSlider *joint, dReal force)
+{
+  dVector3 axis;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+
+  if (joint->flags & dJOINT_REVERSE)
+    force -= force;
+
+  getAxis (joint,axis,joint->axis1);
+  axis[0] *= force;
+  axis[1] *= force;
+  axis[2] *= force;
+
+  if (joint->node[0].body != 0)
+    dBodyAddForce (joint->node[0].body,axis[0],axis[1],axis[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddForce(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
+}
+
+
+dxJoint::Vtable __dslider_vtable = {
+  sizeof(dxJointSlider),
+  (dxJoint::init_fn*) sliderInit,
+  (dxJoint::getInfo1_fn*) sliderGetInfo1,
+  (dxJoint::getInfo2_fn*) sliderGetInfo2,
+  dJointTypeSlider};
+
+//****************************************************************************
+// contact
+
+static void contactInit (dxJointContact *j)
+{
+  // default frictionless contact. hmmm, this info gets overwritten straight
+  // away anyway, so why bother?
+#if 0 /* so don't bother ;) */
+  j->contact.surface.mode = 0;
+  j->contact.surface.mu = 0;
+  dSetZero (j->contact.geom.pos,4);
+  dSetZero (j->contact.geom.normal,4);
+  j->contact.geom.depth = 0;
+#endif
+}
+
+
+static void contactGetInfo1 (dxJointContact *j, dxJoint::Info1 *info)
+{
+  // make sure mu's >= 0, then calculate number of constraint rows and number
+  // of unbounded rows.
+  int m = 1, nub=0;
+  if (j->contact.surface.mu < 0) j->contact.surface.mu = 0;
+  if (j->contact.surface.mode & dContactMu2) {
+    if (j->contact.surface.mu > 0) m++;
+    if (j->contact.surface.mu2 < 0) j->contact.surface.mu2 = 0;
+    if (j->contact.surface.mu2 > 0) m++;
+    if (j->contact.surface.mu  == dInfinity) nub ++;
+    if (j->contact.surface.mu2 == dInfinity) nub ++;
+  }
+  else {
+    if (j->contact.surface.mu > 0) m += 2;
+    if (j->contact.surface.mu == dInfinity) nub += 2;
+  }
+
+  j->the_m = m;
+  info->m = m;
+  info->nub = nub;
+}
+
+
+static void contactGetInfo2 (dxJointContact *j, dxJoint::Info2 *info)
+{
+  int i,s = info->rowskip;
+  int s2 = 2*s;
+
+  // get normal, with sign adjusted for body1/body2 polarity
+  dVector3 normal;
+  if (j->flags & dJOINT_REVERSE) {
+    normal[0] = - j->contact.geom.normal[0];
+    normal[1] = - j->contact.geom.normal[1];
+    normal[2] = - j->contact.geom.normal[2];
+  }
+  else {
+    normal[0] = j->contact.geom.normal[0];
+    normal[1] = j->contact.geom.normal[1];
+    normal[2] = j->contact.geom.normal[2];
+  }
+  normal[3] = 0;	// @@@ hmmm
+
+  // c1,c2 = contact points with respect to body PORs
+  dVector3 c1,c2;
+  for (i=0; i<3; i++) c1[i] = j->contact.geom.pos[i] - j->node[0].body->pos[i];
+
+  // set jacobian for normal
+  info->J1l[0] = normal[0];
+  info->J1l[1] = normal[1];
+  info->J1l[2] = normal[2];
+  dCROSS (info->J1a,=,c1,normal);
+  if (j->node[1].body) {
+    for (i=0; i<3; i++) c2[i] = j->contact.geom.pos[i] -
+			  j->node[1].body->pos[i];
+    info->J2l[0] = -normal[0];
+    info->J2l[1] = -normal[1];
+    info->J2l[2] = -normal[2];
+    dCROSS (info->J2a,= -,c2,normal);
+  }
+
+  // set right hand side and cfm value for normal
+  dReal erp = info->erp;
+  if (j->contact.surface.mode & dContactSoftERP)
+    erp = j->contact.surface.soft_erp;
+  dReal k = info->fps * erp;
+  info->c[0] = k*j->contact.geom.depth;
+  if (j->contact.surface.mode & dContactSoftCFM)
+    info->cfm[0] = j->contact.surface.soft_cfm;
+
+  // deal with bounce
+  if (j->contact.surface.mode & dContactBounce) {
+    // calculate outgoing velocity (-ve for incoming contact)
+    dReal outgoing = dDOT(info->J1l,j->node[0].body->lvel) +
+      dDOT(info->J1a,j->node[0].body->avel);
+    if (j->node[1].body) {
+      outgoing += dDOT(info->J2l,j->node[1].body->lvel) +
+	dDOT(info->J2a,j->node[1].body->avel);
+    }
+    // only apply bounce if the outgoing velocity is greater than the
+    // threshold, and if the resulting c[0] exceeds what we already have.
+    if (j->contact.surface.bounce_vel >= 0 &&
+	(-outgoing) > j->contact.surface.bounce_vel) {
+      dReal newc = - j->contact.surface.bounce * outgoing;
+      if (newc > info->c[0]) info->c[0] = newc;
+    }
+  }
+
+  // set LCP limits for normal
+  info->lo[0] = 0;
+  info->hi[0] = dInfinity;
+
+  // now do jacobian for tangential forces
+  dVector3 t1,t2;	// two vectors tangential to normal
+
+  // first friction direction
+  if (j->the_m >= 2) {
+    if (j->contact.surface.mode & dContactFDir1) {	// use fdir1 ?
+      t1[0] = j->contact.fdir1[0];
+      t1[1] = j->contact.fdir1[1];
+      t1[2] = j->contact.fdir1[2];
+      dCROSS (t2,=,normal,t1);
+    }
+    else {
+      dPlaneSpace (normal,t1,t2);
+    }
+    info->J1l[s+0] = t1[0];
+    info->J1l[s+1] = t1[1];
+    info->J1l[s+2] = t1[2];
+    dCROSS (info->J1a+s,=,c1,t1);
+    if (j->node[1].body) {
+      info->J2l[s+0] = -t1[0];
+      info->J2l[s+1] = -t1[1];
+      info->J2l[s+2] = -t1[2];
+      dCROSS (info->J2a+s,= -,c2,t1);
+    }
+    // set right hand side
+    if (j->contact.surface.mode & dContactMotion1) {
+      info->c[1] = j->contact.surface.motion1;
+    }
+    // set LCP bounds and friction index. this depends on the approximation
+    // mode
+    info->lo[1] = -j->contact.surface.mu;
+    info->hi[1] = j->contact.surface.mu;
+    if (j->contact.surface.mode & dContactApprox1_1) info->findex[1] = 0;
+
+    // set slip (constraint force mixing)
+    if (j->contact.surface.mode & dContactSlip1)
+      info->cfm[1] = j->contact.surface.slip1;
+  }
+
+  // second friction direction
+  if (j->the_m >= 3) {
+    info->J1l[s2+0] = t2[0];
+    info->J1l[s2+1] = t2[1];
+    info->J1l[s2+2] = t2[2];
+    dCROSS (info->J1a+s2,=,c1,t2);
+    if (j->node[1].body) {
+      info->J2l[s2+0] = -t2[0];
+      info->J2l[s2+1] = -t2[1];
+      info->J2l[s2+2] = -t2[2];
+      dCROSS (info->J2a+s2,= -,c2,t2);
+    }
+    // set right hand side
+    if (j->contact.surface.mode & dContactMotion2) {
+      info->c[2] = j->contact.surface.motion2;
+    }
+    // set LCP bounds and friction index. this depends on the approximation
+    // mode
+    if (j->contact.surface.mode & dContactMu2) {
+      info->lo[2] = -j->contact.surface.mu2;
+      info->hi[2] = j->contact.surface.mu2;
+    }
+    else {
+      info->lo[2] = -j->contact.surface.mu;
+      info->hi[2] = j->contact.surface.mu;
+    }
+    if (j->contact.surface.mode & dContactApprox1_2) info->findex[2] = 0;
+
+    // set slip (constraint force mixing)
+    if (j->contact.surface.mode & dContactSlip2)
+      info->cfm[2] = j->contact.surface.slip2;
+  }
+}
+
+
+dxJoint::Vtable __dcontact_vtable = {
+  sizeof(dxJointContact),
+  (dxJoint::init_fn*) contactInit,
+  (dxJoint::getInfo1_fn*) contactGetInfo1,
+  (dxJoint::getInfo2_fn*) contactGetInfo2,
+  dJointTypeContact};
+
+//****************************************************************************
+// hinge 2. note that this joint must be attached to two bodies for it to work
+
+static dReal measureHinge2Angle (dxJointHinge2 *joint)
+{
+  dVector3 a1,a2;
+  dMULTIPLY0_331 (a1,joint->node[1].body->R,joint->axis2);
+  dMULTIPLY1_331 (a2,joint->node[0].body->R,a1);
+  dReal x = dDOT(joint->v1,a2);
+  dReal y = dDOT(joint->v2,a2);
+  return -dAtan2 (y,x);
+}
+
+
+static void hinge2Init (dxJointHinge2 *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->axis2,4);
+  j->axis2[1] = 1;
+  j->c0 = 0;
+  j->s0 = 0;
+
+  dSetZero (j->v1,4);
+  j->v1[0] = 1;
+  dSetZero (j->v2,4);
+  j->v2[1] = 1;
+
+  j->limot1.init (j->world);
+  j->limot2.init (j->world);
+
+  j->susp_erp = j->world->global_erp;
+  j->susp_cfm = j->world->global_cfm;
+
+  j->flags |= dJOINT_TWOBODIES;
+}
+
+
+static void hinge2GetInfo1 (dxJointHinge2 *j, dxJoint::Info1 *info)
+{
+  info->m = 4;
+  info->nub = 4;
+
+  // see if we're powered or at a joint limit for axis 1
+  int atlimit=0;
+  if ((j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) &&
+      j->limot1.lostop <= j->limot1.histop) {
+    dReal angle = measureHinge2Angle (j);
+    if (j->limot1.testRotationalLimit (angle)) atlimit = 1;
+  }
+  if (atlimit || j->limot1.fmax > 0) info->m++;
+
+  // see if we're powering axis 2 (we currently never limit this axis)
+  j->limot2.limit = 0;
+  if (j->limot2.fmax > 0) info->m++;
+}
+
+
+// macro that computes ax1,ax2 = axis 1 and 2 in global coordinates (they are
+// relative to body 1 and 2 initially) and then computes the constrained
+// rotational axis as the cross product of ax1 and ax2.
+// the sin and cos of the angle between axis 1 and 2 is computed, this comes
+// from dot and cross product rules.
+
+#define HINGE2_GET_AXIS_INFO(axis,sin_angle,cos_angle) \
+  dVector3 ax1,ax2; \
+  dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1); \
+  dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2); \
+  dCROSS (axis,=,ax1,ax2); \
+  sin_angle = dSqrt (axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); \
+  cos_angle = dDOT (ax1,ax2);
+
+
+static void hinge2GetInfo2 (dxJointHinge2 *joint, dxJoint::Info2 *info)
+{
+  // get information we need to set the hinge row
+  dReal s,c;
+  dVector3 q;
+  HINGE2_GET_AXIS_INFO (q,s,c);
+  dNormalize3 (q);		// @@@ quicker: divide q by s ?
+
+  // set the three ball-and-socket rows (aligned to the suspension axis ax1)
+  setBall2 (joint,info,joint->anchor1,joint->anchor2,ax1,joint->susp_erp);
+
+  // set the hinge row
+  int s3=3*info->rowskip;
+  info->J1a[s3+0] = q[0];
+  info->J1a[s3+1] = q[1];
+  info->J1a[s3+2] = q[2];
+  if (joint->node[1].body) {
+    info->J2a[s3+0] = -q[0];
+    info->J2a[s3+1] = -q[1];
+    info->J2a[s3+2] = -q[2];
+  }
+
+  // compute the right hand side for the constrained rotational DOF.
+  // axis 1 and axis 2 are separated by an angle `theta'. the desired
+  // separation angle is theta0. sin(theta0) and cos(theta0) are recorded
+  // in the joint structure. the correcting angular velocity is:
+  //   |angular_velocity| = angle/time = erp*(theta0-theta) / stepsize
+  //                      = (erp*fps) * (theta0-theta)
+  // (theta0-theta) can be computed using the following small-angle-difference
+  // approximation:
+  //   theta0-theta ~= tan(theta0-theta)
+  //                 = sin(theta0-theta)/cos(theta0-theta)
+  //                 = (c*s0 - s*c0) / (c*c0 + s*s0)
+  //                 = c*s0 - s*c0         assuming c*c0 + s*s0 ~= 1
+  // where c = cos(theta), s = sin(theta)
+  //       c0 = cos(theta0), s0 = sin(theta0)
+
+  dReal k = info->fps * info->erp;
+  info->c[3] = k * (joint->c0 * s - joint->s0 * c);
+
+  // if the axis1 hinge is powered, or has joint limits, add in more stuff
+  int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1);
+
+  // if the axis2 hinge is powered, add in more stuff
+  joint->limot2.addLimot (joint,info,row,ax2,1);
+
+  // set parameter for the suspension
+  info->cfm[0] = joint->susp_cfm;
+}
+
+
+// compute vectors v1 and v2 (embedded in body1), used to measure angle
+// between body 1 and body 2
+
+static void makeHinge2V1andV2 (dxJointHinge2 *joint)
+{
+  if (joint->node[0].body) {
+    // get axis 1 and 2 in global coords
+    dVector3 ax1,ax2,v;
+    dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1);
+    dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2);
+
+    // don't do anything if the axis1 or axis2 vectors are zero or the same
+    if ((ax1[0]==0 && ax1[1]==0 && ax1[2]==0) ||
+	(ax2[0]==0 && ax2[1]==0 && ax2[2]==0) ||
+	(ax1[0]==ax2[0] && ax1[1]==ax2[1] && ax1[2]==ax2[2])) return;
+
+    // modify axis 2 so it's perpendicular to axis 1
+    dReal k = dDOT(ax1,ax2);
+    for (int i=0; i<3; i++) ax2[i] -= k*ax1[i];
+    dNormalize3 (ax2);
+
+    // make v1 = modified axis2, v2 = axis1 x (modified axis2)
+    dCROSS (v,=,ax1,ax2);
+    dMULTIPLY1_331 (joint->v1,joint->node[0].body->R,ax2);
+    dMULTIPLY1_331 (joint->v2,joint->node[0].body->R,v);
+  }
+}
+
+
+extern "C" void dJointSetHinge2Anchor (dxJointHinge2 *joint,
+				       dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+  makeHinge2V1andV2 (joint);
+}
+
+
+extern "C" void dJointSetHinge2Axis1 (dxJointHinge2 *joint,
+				      dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) {
+    dReal q[4];
+    q[0] = x;
+    q[1] = y;
+    q[2] = z;
+    q[3] = 0;
+    dNormalize3 (q);
+    dMULTIPLY1_331 (joint->axis1,joint->node[0].body->R,q);
+    joint->axis1[3] = 0;
+
+    // compute the sin and cos of the angle between axis 1 and axis 2
+    dVector3 ax;
+    HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0);
+  }
+  makeHinge2V1andV2 (joint);
+}
+
+
+extern "C" void dJointSetHinge2Axis2 (dxJointHinge2 *joint,
+				      dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[1].body) {
+    dReal q[4];
+    q[0] = x;
+    q[1] = y;
+    q[2] = z;
+    q[3] = 0;
+    dNormalize3 (q);
+    dMULTIPLY1_331 (joint->axis2,joint->node[1].body->R,q);
+    joint->axis1[3] = 0;
+
+    // compute the sin and cos of the angle between axis 1 and axis 2
+    dVector3 ax;
+    HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0);
+  }
+  makeHinge2V1andV2 (joint);
+}
+
+
+extern "C" void dJointSetHinge2Param (dxJointHinge2 *joint,
+				      int parameter, dReal value)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if ((parameter & 0xff00) == 0x100) {
+    joint->limot2.set (parameter & 0xff,value);
+  }
+  else {
+    if (parameter == dParamSuspensionERP) joint->susp_erp = value;
+    else if (parameter == dParamSuspensionCFM) joint->susp_cfm = value;
+    else joint->limot1.set (parameter,value);
+  }
+}
+
+
+extern "C" void dJointGetHinge2Anchor (dxJointHinge2 *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+extern "C" void dJointGetHinge2Anchor2 (dxJointHinge2 *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+extern "C" void dJointGetHinge2Axis1 (dxJointHinge2 *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) {
+    dMULTIPLY0_331 (result,joint->node[0].body->R,joint->axis1);
+  }
+}
+
+
+extern "C" void dJointGetHinge2Axis2 (dxJointHinge2 *joint, dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (result,joint->node[1].body->R,joint->axis2);
+  }
+}
+
+
+extern "C" dReal dJointGetHinge2Param (dxJointHinge2 *joint, int parameter)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if ((parameter & 0xff00) == 0x100) {
+    return joint->limot2.get (parameter & 0xff);
+  }
+  else {
+    if (parameter == dParamSuspensionERP) return joint->susp_erp;
+    else if (parameter == dParamSuspensionCFM) return joint->susp_cfm;
+    else return joint->limot1.get (parameter);
+  }
+}
+
+
+extern "C" dReal dJointGetHinge2Angle1 (dxJointHinge2 *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) return measureHinge2Angle (joint);
+  else return 0;
+}
+
+
+extern "C" dReal dJointGetHinge2Angle1Rate (dxJointHinge2 *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) {
+    dVector3 axis;
+    dMULTIPLY0_331 (axis,joint->node[0].body->R,joint->axis1);
+    dReal rate = dDOT(axis,joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
+    return rate;
+  }
+  else return 0;
+}
+
+
+extern "C" dReal dJointGetHinge2Angle2Rate (dxJointHinge2 *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body && joint->node[1].body) {
+    dVector3 axis;
+    dMULTIPLY0_331 (axis,joint->node[1].body->R,joint->axis2);
+    dReal rate = dDOT(axis,joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
+    return rate;
+  }
+  else return 0;
+}
+
+
+extern "C" void dJointAddHinge2Torques (dxJointHinge2 *joint, dReal torque1, dReal torque2)
+{
+  dVector3 axis1, axis2;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+
+  if (joint->node[0].body && joint->node[1].body) {
+    dMULTIPLY0_331 (axis1,joint->node[0].body->R,joint->axis1);
+    dMULTIPLY0_331 (axis2,joint->node[1].body->R,joint->axis2);
+    axis1[0] = axis1[0] * torque1 + axis2[0] * torque2;
+    axis1[1] = axis1[1] * torque1 + axis2[1] * torque2;
+    axis1[2] = axis1[2] * torque1 + axis2[2] * torque2;
+    dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]);
+    dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]);
+  }
+}
+
+
+dxJoint::Vtable __dhinge2_vtable = {
+  sizeof(dxJointHinge2),
+  (dxJoint::init_fn*) hinge2Init,
+  (dxJoint::getInfo1_fn*) hinge2GetInfo1,
+  (dxJoint::getInfo2_fn*) hinge2GetInfo2,
+  dJointTypeHinge2};
+
+//****************************************************************************
+// universal
+
+// I just realized that the universal joint is equivalent to a hinge 2 joint with
+// perfectly stiff suspension.  By comparing the hinge 2 implementation to
+// the universal implementation, you may be able to improve this
+// implementation (or, less likely, the hinge2 implementation).
+
+static void universalInit (dxJointUniversal *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->axis2,4);
+  j->axis2[1] = 1;
+  dSetZero(j->qrel1,4);
+  dSetZero(j->qrel2,4);
+  j->limot1.init (j->world);
+  j->limot2.init (j->world);
+}
+
+
+static void getUniversalAxes(dxJointUniversal *joint, dVector3 ax1, dVector3 ax2)
+{
+  // This says "ax1 = joint->node[0].body->R * joint->axis1"
+  dMULTIPLY0_331 (ax1,joint->node[0].body->R,joint->axis1);
+
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (ax2,joint->node[1].body->R,joint->axis2);
+  }
+  else {
+    ax2[0] = joint->axis2[0];
+    ax2[1] = joint->axis2[1];
+    ax2[2] = joint->axis2[2];
+  }
+}
+
+
+static dReal getUniversalAngle1(dxJointUniversal *joint)
+{
+  if (joint->node[0].body) {
+    // length 1 joint axis in global coordinates, from each body
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross, qq, qrel;
+
+    getUniversalAxes (joint,ax1,ax2);
+
+    // It should be possible to get both angles without explicitly
+    // constructing the rotation matrix of the cross.  Basically,
+    // orientation of the cross about axis1 comes from body 2,
+    // about axis 2 comes from body 1, and the perpendicular
+    // axis can come from the two bodies somehow.  (We don't really
+    // want to assume it's 90 degrees, because in general the
+    // constraints won't be perfectly satisfied, or even very well
+    // satisfied.)
+    //
+    // However, we'd need a version of getHingeAngleFromRElativeQuat()
+    // that CAN handle when its relative quat is rotated along a direction
+    // other than the given axis.  What I have here works,
+    // although it's probably much slower than need be.
+
+    dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
+    dRtoQ (R,qcross);
+
+    // This code is essential the same as getHingeAngle(), see the comments
+    // there for details.
+
+    // get qrel = relative rotation between node[0] and the cross
+    dQMultiply1 (qq,joint->node[0].body->q,qcross);
+    dQMultiply2 (qrel,qq,joint->qrel1);
+
+    return getHingeAngleFromRelativeQuat(qrel, joint->axis1);
+  }
+  return 0;
+}
+
+
+static dReal getUniversalAngle2(dxJointUniversal *joint)
+{
+  if (joint->node[0].body) {
+    // length 1 joint axis in global coordinates, from each body
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross, qq, qrel;
+
+    getUniversalAxes (joint,ax1,ax2);
+
+    // It should be possible to get both angles without explicitly
+    // constructing the rotation matrix of the cross.  Basically,
+    // orientation of the cross about axis1 comes from body 2,
+    // about axis 2 comes from body 1, and the perpendicular
+    // axis can come from the two bodies somehow.  (We don't really
+    // want to assume it's 90 degrees, because in general the
+    // constraints won't be perfectly satisfied, or even very well
+    // satisfied.)
+    //
+    // However, we'd need a version of getHingeAngleFromRElativeQuat()
+    // that CAN handle when its relative quat is rotated along a direction
+    // other than the given axis.  What I have here works,
+    // although it's probably much slower than need be.
+
+    dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
+    dRtoQ(R, qcross);
+
+    if (joint->node[1].body) {
+      dQMultiply1 (qq, joint->node[1].body->q, qcross);
+      dQMultiply2 (qrel,qq,joint->qrel2);
+    }
+    else {
+      // pretend joint->node[1].body->q is the identity
+      dQMultiply2 (qrel,qcross, joint->qrel2);
+    }
+
+    return - getHingeAngleFromRelativeQuat(qrel, joint->axis2);
+  }
+  return 0;
+}
+
+
+static void universalGetInfo1 (dxJointUniversal *j, dxJoint::Info1 *info)
+{
+  info->nub = 4;
+  info->m = 4;
+
+  // see if we're powered or at a joint limit.
+  bool constraint1 = j->limot1.fmax > 0;
+  bool constraint2 = j->limot2.fmax > 0;
+
+  bool limiting1 = (j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) &&
+       j->limot1.lostop <= j->limot1.histop;
+  bool limiting2 = (j->limot2.lostop >= -M_PI || j->limot2.histop <= M_PI) &&
+       j->limot2.lostop <= j->limot2.histop;
+
+  // We need to call testRotationLimit() even if we're motored, since it
+  // records the result.
+  if (limiting1 || limiting2) {
+    dReal angle1, angle2;
+    angle1 = getUniversalAngle1(j);
+    angle2 = getUniversalAngle2(j);
+    if (limiting1 && j->limot1.testRotationalLimit (angle1)) constraint1 = true;
+    if (limiting2 && j->limot2.testRotationalLimit (angle2)) constraint2 = true;
+  }
+  if (constraint1)
+    info->m++;
+  if (constraint2)
+    info->m++;
+}
+
+
+static void universalGetInfo2 (dxJointUniversal *joint, dxJoint::Info2 *info)
+{
+  // set the three ball-and-socket rows
+  setBall (joint,info,joint->anchor1,joint->anchor2);
+
+  // set the universal joint row. the angular velocity about an axis
+  // perpendicular to both joint axes should be equal. thus the constraint
+  // equation is
+  //    p*w1 - p*w2 = 0
+  // where p is a vector normal to both joint axes, and w1 and w2
+  // are the angular velocity vectors of the two bodies.
+
+  // length 1 joint axis in global coordinates, from each body
+  dVector3 ax1, ax2;
+  dVector3 ax2_temp;
+  // length 1 vector perpendicular to ax1 and ax2. Neither body can rotate
+  // about this.
+  dVector3 p;
+  dReal k;
+
+  getUniversalAxes(joint, ax1, ax2);
+  k = dDOT(ax1, ax2);
+  ax2_temp[0] = ax2[0] - k*ax1[0];
+  ax2_temp[1] = ax2[1] - k*ax1[1];
+  ax2_temp[2] = ax2[2] - k*ax1[2];
+  dCROSS(p, =, ax1, ax2_temp);
+  dNormalize3(p);
+
+  int s3=3*info->rowskip;
+
+  info->J1a[s3+0] = p[0];
+  info->J1a[s3+1] = p[1];
+  info->J1a[s3+2] = p[2];
+
+  if (joint->node[1].body) {
+    info->J2a[s3+0] = -p[0];
+    info->J2a[s3+1] = -p[1];
+    info->J2a[s3+2] = -p[2];
+  }
+
+  // compute the right hand side of the constraint equation. set relative
+  // body velocities along p to bring the axes back to perpendicular.
+  // If ax1, ax2 are unit length joint axes as computed from body1 and
+  // body2, we need to rotate both bodies along the axis p.  If theta
+  // is the angle between ax1 and ax2, we need an angular velocity
+  // along p to cover the angle erp * (theta - Pi/2) in one step:
+  //
+  //   |angular_velocity| = angle/time = erp*(theta - Pi/2) / stepsize
+  //                      = (erp*fps) * (theta - Pi/2)
+  //
+  // if theta is close to Pi/2,
+  // theta - Pi/2 ~= cos(theta), so
+  //    |angular_velocity|  ~= (erp*fps) * (ax1 dot ax2)
+
+  info->c[3] = info->fps * info->erp * - dDOT(ax1, ax2);
+
+  // if the first angle is powered, or has joint limits, add in the stuff
+  int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1);
+
+  // if the second angle is powered, or has joint limits, add in more stuff
+  joint->limot2.addLimot (joint,info,row,ax2,1);
+}
+
+
+static void universalComputeInitialRelativeRotations (dxJointUniversal *joint)
+{
+  if (joint->node[0].body) {
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross;
+
+    getUniversalAxes(joint, ax1, ax2);
+
+    // Axis 1.
+    dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
+    dRtoQ(R, qcross);
+    dQMultiply1 (joint->qrel1, joint->node[0].body->q, qcross);
+
+    // Axis 2.
+    dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
+    dRtoQ(R, qcross);
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel2, joint->node[1].body->q, qcross);
+    }
+    else {
+      // set joint->qrel to qcross
+      for (int i=0; i<4; i++) joint->qrel2[i] = qcross[i];
+    }
+  }
+}
+
+
+extern "C" void dJointSetUniversalAnchor (dxJointUniversal *joint,
+					  dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+  universalComputeInitialRelativeRotations(joint);
+}
+
+
+extern "C" void dJointSetUniversalAxis1 (dxJointUniversal *joint,
+					 dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    setAxes (joint,x,y,z,NULL,joint->axis2);
+  else
+    setAxes (joint,x,y,z,joint->axis1,NULL);
+  universalComputeInitialRelativeRotations(joint);
+}
+
+
+extern "C" void dJointSetUniversalAxis2 (dxJointUniversal *joint,
+					 dReal x, dReal y, dReal z)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    setAxes (joint,x,y,z,joint->axis1,NULL);
+  else
+    setAxes (joint,x,y,z,NULL,joint->axis2);
+  universalComputeInitialRelativeRotations(joint);
+}
+
+
+extern "C" void dJointGetUniversalAnchor (dxJointUniversal *joint,
+					  dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+extern "C" void dJointGetUniversalAnchor2 (dxJointUniversal *joint,
+					  dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+extern "C" void dJointGetUniversalAxis1 (dxJointUniversal *joint,
+					 dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAxis2 (joint,result,joint->axis2);
+  else
+    getAxis (joint,result,joint->axis1);
+}
+
+
+extern "C" void dJointGetUniversalAxis2 (dxJointUniversal *joint,
+					 dVector3 result)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAxis (joint,result,joint->axis1);
+  else
+    getAxis2 (joint,result,joint->axis2);
+}
+
+
+extern "C" void dJointSetUniversalParam (dxJointUniversal *joint,
+				     int parameter, dReal value)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if ((parameter & 0xff00) == 0x100) {
+    joint->limot2.set (parameter & 0xff,value);
+  }
+  else {
+    joint->limot1.set (parameter,value);
+  }
+}
+
+
+extern "C" dReal dJointGetUniversalParam (dxJointUniversal *joint, int parameter)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if ((parameter & 0xff00) == 0x100) {
+    return joint->limot2.get (parameter & 0xff);
+  }
+  else {
+    return joint->limot1.get (parameter);
+  }
+}
+
+
+extern "C" dReal dJointGetUniversalAngle1 (dxJointUniversal *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    return getUniversalAngle2 (joint);
+  else
+    return getUniversalAngle1 (joint);
+}
+
+
+extern "C" dReal dJointGetUniversalAngle2 (dxJointUniversal *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    return getUniversalAngle1 (joint);
+  else
+    return getUniversalAngle2 (joint);
+}
+
+
+extern "C" dReal dJointGetUniversalAngle1Rate (dxJointUniversal *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+
+  if (joint->node[0].body) {
+    dVector3 axis;
+
+    if (joint->flags & dJOINT_REVERSE)
+      getAxis2 (joint,axis,joint->axis2);
+    else
+      getAxis (joint,axis,joint->axis1);
+
+    dReal rate = dDOT(axis, joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel);
+    return rate;
+  }
+  return 0;
+}
+
+
+extern "C" dReal dJointGetUniversalAngle2Rate (dxJointUniversal *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+
+  if (joint->node[0].body) {
+    dVector3 axis;
+
+    if (joint->flags & dJOINT_REVERSE)
+      getAxis (joint,axis,joint->axis1);
+    else
+      getAxis2 (joint,axis,joint->axis2);
+
+    dReal rate = dDOT(axis, joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel);
+    return rate;
+  }
+  return 0;
+}
+
+
+extern "C" void dJointAddUniversalTorques (dxJointUniversal *joint, dReal torque1, dReal torque2)
+{
+  dVector3 axis1, axis2;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+
+  if (joint->flags & dJOINT_REVERSE) {
+    dReal temp = torque1;
+    torque1 = - torque2;
+    torque2 = - temp;
+  }
+
+  getAxis (joint,axis1,joint->axis1);
+  getAxis2 (joint,axis2,joint->axis2);
+  axis1[0] = axis1[0] * torque1 + axis2[0] * torque2;
+  axis1[1] = axis1[1] * torque1 + axis2[1] * torque2;
+  axis1[2] = axis1[2] * torque1 + axis2[2] * torque2;
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]);
+}
+
+
+
+
+
+dxJoint::Vtable __duniversal_vtable = {
+  sizeof(dxJointUniversal),
+  (dxJoint::init_fn*) universalInit,
+  (dxJoint::getInfo1_fn*) universalGetInfo1,
+  (dxJoint::getInfo2_fn*) universalGetInfo2,
+  dJointTypeUniversal};
+
+//****************************************************************************
+// angular motor
+
+static void amotorInit (dxJointAMotor *j)
+{
+  int i;
+  j->num = 0;
+  j->mode = dAMotorUser;
+  for (i=0; i<3; i++) {
+    j->rel[i] = 0;
+    dSetZero (j->axis[i],4);
+    j->limot[i].init (j->world);
+    j->angle[i] = 0;
+  }
+  dSetZero (j->reference1,4);
+  dSetZero (j->reference2,4);
+
+  j->flags |= dJOINT_TWOBODIES;
+}
+
+
+// compute the 3 axes in global coordinates
+
+static void amotorComputeGlobalAxes (dxJointAMotor *joint, dVector3 ax[3])
+{
+  if (joint->mode == dAMotorEuler) {
+    // special handling for euler mode
+    dMULTIPLY0_331 (ax[0],joint->node[0].body->R,joint->axis[0]);
+    dMULTIPLY0_331 (ax[2],joint->node[1].body->R,joint->axis[2]);
+    dCROSS (ax[1],=,ax[2],ax[0]);
+    dNormalize3 (ax[1]);
+  }
+  else {
+    for (int i=0; i < joint->num; i++) {
+      if (joint->rel[i] == 1) {
+	// relative to b1
+	dMULTIPLY0_331 (ax[i],joint->node[0].body->R,joint->axis[i]);
+      }
+      if (joint->rel[i] == 2) {
+	// relative to b2
+	dMULTIPLY0_331 (ax[i],joint->node[1].body->R,joint->axis[i]);
+      }
+      else {
+	// global - just copy it
+	ax[i][0] = joint->axis[i][0];
+	ax[i][1] = joint->axis[i][1];
+	ax[i][2] = joint->axis[i][2];
+      }
+    }
+  }
+}
+
+
+static void amotorComputeEulerAngles (dxJointAMotor *joint, dVector3 ax[3])
+{
+  // assumptions:
+  //   global axes already calculated --> ax
+  //   axis[0] is relative to body 1 --> global ax[0]
+  //   axis[2] is relative to body 2 --> global ax[2]
+  //   ax[1] = ax[2] x ax[0]
+  //   original ax[0] and ax[2] are perpendicular
+  //   reference1 is perpendicular to ax[0] (in body 1 frame)
+  //   reference2 is perpendicular to ax[2] (in body 2 frame)
+  //   all ax[] and reference vectors are unit length
+
+  // calculate references in global frame
+  dVector3 ref1,ref2;
+  dMULTIPLY0_331 (ref1,joint->node[0].body->R,joint->reference1);
+  dMULTIPLY0_331 (ref2,joint->node[1].body->R,joint->reference2);
+
+  // get q perpendicular to both ax[0] and ref1, get first euler angle
+  dVector3 q;
+  dCROSS (q,=,ax[0],ref1);
+  joint->angle[0] = -dAtan2 (dDOT(ax[2],q),dDOT(ax[2],ref1));
+
+  // get q perpendicular to both ax[0] and ax[1], get second euler angle
+  dCROSS (q,=,ax[0],ax[1]);
+  joint->angle[1] = -dAtan2 (dDOT(ax[2],ax[0]),dDOT(ax[2],q));
+
+  // get q perpendicular to both ax[1] and ax[2], get third euler angle
+  dCROSS (q,=,ax[1],ax[2]);
+  joint->angle[2] = -dAtan2 (dDOT(ref2,ax[1]), dDOT(ref2,q));
+}
+
+
+// set the reference vectors as follows:
+//   * reference1 = current axis[2] relative to body 1
+//   * reference2 = current axis[0] relative to body 2
+// this assumes that:
+//    * axis[0] is relative to body 1
+//    * axis[2] is relative to body 2
+
+static void amotorSetEulerReferenceVectors (dxJointAMotor *j)
+{
+  if (j->node[0].body && j->node[1].body) {
+    dVector3 r;		// axis[2] and axis[0] in global coordinates
+    dMULTIPLY0_331 (r,j->node[1].body->R,j->axis[2]);
+    dMULTIPLY1_331 (j->reference1,j->node[0].body->R,r);
+    dMULTIPLY0_331 (r,j->node[0].body->R,j->axis[0]);
+    dMULTIPLY1_331 (j->reference2,j->node[1].body->R,r);
+  }
+}
+
+
+static void amotorGetInfo1 (dxJointAMotor *j, dxJoint::Info1 *info)
+{
+  info->m = 0;
+  info->nub = 0;
+
+  // compute the axes and angles, if in euler mode
+  if (j->mode == dAMotorEuler) {
+    dVector3 ax[3];
+    amotorComputeGlobalAxes (j,ax);
+    amotorComputeEulerAngles (j,ax);
+  }
+
+  // see if we're powered or at a joint limit for each axis
+  for (int i=0; i < j->num; i++) {
+    if (j->limot[i].testRotationalLimit (j->angle[i]) ||
+	j->limot[i].fmax > 0) {
+      info->m++;
+    }
+  }
+}
+
+
+static void amotorGetInfo2 (dxJointAMotor *joint, dxJoint::Info2 *info)
+{
+  int i;
+
+  // compute the axes (if not global)
+  dVector3 ax[3];
+  amotorComputeGlobalAxes (joint,ax);
+
+  // in euler angle mode we do not actually constrain the angular velocity
+  // along the axes axis[0] and axis[2] (although we do use axis[1]) :
+  //
+  //    to get			constrain w2-w1 along		...not
+  //    ------			---------------------		------
+  //    d(angle[0])/dt = 0	ax[1] x ax[2]			ax[0]
+  //    d(angle[1])/dt = 0	ax[1]
+  //    d(angle[2])/dt = 0	ax[0] x ax[1]			ax[2]
+  //
+  // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+  // to prove the result for angle[0], write the expression for angle[0] from
+  // GetInfo1 then take the derivative. to prove this for angle[2] it is
+  // easier to take the euler rate expression for d(angle[2])/dt with respect
+  // to the components of w and set that to 0.
+
+  dVector3 *axptr[3];
+  axptr[0] = &ax[0];
+  axptr[1] = &ax[1];
+  axptr[2] = &ax[2];
+
+  dVector3 ax0_cross_ax1;
+  dVector3 ax1_cross_ax2;
+  if (joint->mode == dAMotorEuler) {
+    dCROSS (ax0_cross_ax1,=,ax[0],ax[1]);
+    axptr[2] = &ax0_cross_ax1;
+    dCROSS (ax1_cross_ax2,=,ax[1],ax[2]);
+    axptr[0] = &ax1_cross_ax2;
+  }
+
+  int row=0;
+  for (i=0; i < joint->num; i++) {
+    row += joint->limot[i].addLimot (joint,info,row,*(axptr[i]),1);
+  }
+}
+
+
+extern "C" void dJointSetAMotorNumAxes (dxJointAMotor *joint, int num)
+{
+  dAASSERT(joint && num >= 0 && num <= 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (joint->mode == dAMotorEuler) {
+    joint->num = 3;
+  }
+  else {
+    if (num < 0) num = 0;
+    if (num > 3) num = 3;
+    joint->num = num;
+  }
+}
+
+
+extern "C" void dJointSetAMotorAxis (dxJointAMotor *joint, int anum, int rel,
+				     dReal x, dReal y, dReal z)
+{
+  dAASSERT(joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  joint->rel[anum] = rel;
+
+  // x,y,z is always in global coordinates regardless of rel, so we may have
+  // to convert it to be relative to a body
+  dVector3 r;
+  r[0] = x;
+  r[1] = y;
+  r[2] = z;
+  r[3] = 0;
+  if (rel > 0) {
+    if (rel==1) {
+      dMULTIPLY1_331 (joint->axis[anum],joint->node[0].body->R,r);
+    }
+    else {
+      dMULTIPLY1_331 (joint->axis[anum],joint->node[1].body->R,r);
+    }
+  }
+  else {
+    joint->axis[anum][0] = r[0];
+    joint->axis[anum][1] = r[1];
+    joint->axis[anum][2] = r[2];
+  }
+  dNormalize3 (joint->axis[anum]);
+  if (joint->mode == dAMotorEuler) amotorSetEulerReferenceVectors (joint);
+}
+
+
+extern "C" void dJointSetAMotorAngle (dxJointAMotor *joint, int anum,
+				      dReal angle)
+{
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (joint->mode == dAMotorUser) {
+    if (anum < 0) anum = 0;
+    if (anum > 3) anum = 3;
+    joint->angle[anum] = angle;
+  }
+}
+
+
+extern "C" void dJointSetAMotorParam (dxJointAMotor *joint, int parameter,
+				      dReal value)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  int anum = parameter >> 8;
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  parameter &= 0xff;
+  joint->limot[anum].set (parameter, value);
+}
+
+
+extern "C" void dJointSetAMotorMode (dxJointAMotor *joint, int mode)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  joint->mode = mode;
+  if (joint->mode == dAMotorEuler) {
+    joint->num = 3;
+    amotorSetEulerReferenceVectors (joint);
+  }
+}
+
+
+extern "C" int dJointGetAMotorNumAxes (dxJointAMotor *joint)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  return joint->num;
+}
+
+
+extern "C" void dJointGetAMotorAxis (dxJointAMotor *joint, int anum,
+				     dVector3 result)
+{
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  if (joint->rel[anum] > 0) {
+    if (joint->rel[anum]==1) {
+      dMULTIPLY0_331 (result,joint->node[0].body->R,joint->axis[anum]);
+    }
+    else {
+      dMULTIPLY0_331 (result,joint->node[1].body->R,joint->axis[anum]);
+    }
+  }
+  else {
+    result[0] = joint->axis[anum][0];
+    result[1] = joint->axis[anum][1];
+    result[2] = joint->axis[anum][2];
+  }
+}
+
+
+extern "C" int dJointGetAMotorAxisRel (dxJointAMotor *joint, int anum)
+{
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  return joint->rel[anum];
+}
+
+
+extern "C" dReal dJointGetAMotorAngle (dxJointAMotor *joint, int anum)
+{
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 3) anum = 3;
+  return joint->angle[anum];
+}
+
+
+extern "C" dReal dJointGetAMotorAngleRate (dxJointAMotor *joint, int anum)
+{
+  // @@@
+  dDebug (0,"not yet implemented");
+  return 0;
+}
+
+
+extern "C" dReal dJointGetAMotorParam (dxJointAMotor *joint, int parameter)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  int anum = parameter >> 8;
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  parameter &= 0xff;
+  return joint->limot[anum].get (parameter);
+}
+
+
+extern "C" int dJointGetAMotorMode (dxJointAMotor *joint)
+{
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  return joint->mode;
+}
+
+
+extern "C" void dJointAddAMotorTorques (dxJointAMotor *joint, dReal torque1, dReal torque2, dReal torque3)
+{
+  dVector3 axes[3];
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+
+  if (joint->num == 0)
+    return;
+  dUASSERT((joint->flags & dJOINT_REVERSE) == 0, "dJointAddAMotorTorques not yet implemented for reverse AMotor joints");
+
+  amotorComputeGlobalAxes (joint,axes);
+  axes[0][0] *= torque1;
+  axes[0][1] *= torque1;
+  axes[0][2] *= torque1;
+  if (joint->num >= 2) {
+    axes[0][0] += axes[1][0] * torque2;
+    axes[0][1] += axes[1][0] * torque2;
+    axes[0][2] += axes[1][0] * torque2;
+    if (joint->num >= 3) {
+      axes[0][0] += axes[2][0] * torque3;
+      axes[0][1] += axes[2][0] * torque3;
+      axes[0][2] += axes[2][0] * torque3;
+    }
+  }
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body,axes[0][0],axes[0][1],axes[0][2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axes[0][0], -axes[0][1], -axes[0][2]);
+}
+
+
+dxJoint::Vtable __damotor_vtable = {
+  sizeof(dxJointAMotor),
+  (dxJoint::init_fn*) amotorInit,
+  (dxJoint::getInfo1_fn*) amotorGetInfo1,
+  (dxJoint::getInfo2_fn*) amotorGetInfo2,
+  dJointTypeAMotor};
+
+//****************************************************************************
+// fixed joint
+
+static void fixedInit (dxJointFixed *j)
+{
+  dSetZero (j->offset,4);
+  dSetZero (j->qrel,4);
+}
+
+
+static void fixedGetInfo1 (dxJointFixed *j, dxJoint::Info1 *info)
+{
+  info->m = 6;
+  info->nub = 6;
+}
+
+
+static void fixedGetInfo2 (dxJointFixed *joint, dxJoint::Info2 *info)
+{
+  int s = info->rowskip;
+
+  // Three rows for orientation
+  setFixedOrientation(joint, info, joint->qrel, 3);
+
+  // Three rows for position.
+  // set jacobian
+  info->J1l[0] = 1;
+  info->J1l[s+1] = 1;
+  info->J1l[2*s+2] = 1;
+
+  dVector3 ofs;
+  dMULTIPLY0_331 (ofs,joint->node[0].body->R,joint->offset);
+  if (joint->node[1].body) {
+    dCROSSMAT (info->J1a,ofs,s,+,-);
+    info->J2l[0] = -1;
+    info->J2l[s+1] = -1;
+    info->J2l[2*s+2] = -1;
+  }
+
+  // set right hand side for the first three rows (linear)
+  dReal k = info->fps * info->erp;
+  if (joint->node[1].body) {
+    for (int j=0; j<3; j++)
+      info->c[j] = k * (joint->node[1].body->pos[j] -
+			joint->node[0].body->pos[j] + ofs[j]);
+  }
+  else {
+    for (int j=0; j<3; j++)
+      info->c[j] = k * (joint->offset[j] - joint->node[0].body->pos[j]);
+  }
+}
+
+
+extern "C" void dJointSetFixed (dxJointFixed *joint)
+{
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not fixed");
+  int i;
+
+  // This code is taken from sJointSetSliderAxis(), we should really put the
+  // common code in its own function.
+  // compute the offset between the bodies
+  if (joint->node[0].body) {
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+      dReal ofs[4];
+      for (i=0; i<4; i++) ofs[i] = joint->node[0].body->pos[i];
+      for (i=0; i<4; i++) ofs[i] -= joint->node[1].body->pos[i];
+      dMULTIPLY1_331 (joint->offset,joint->node[0].body->R,ofs);
+    }
+    else {
+      // set joint->qrel to the transpose of the first body's q
+      joint->qrel[0] = joint->node[0].body->q[0];
+      for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+      for (i=0; i<4; i++) joint->offset[i] = joint->node[0].body->pos[i];
+    }
+  }
+}
+
+
+dxJoint::Vtable __dfixed_vtable = {
+  sizeof(dxJointFixed),
+  (dxJoint::init_fn*) fixedInit,
+  (dxJoint::getInfo1_fn*) fixedGetInfo1,
+  (dxJoint::getInfo2_fn*) fixedGetInfo2,
+  dJointTypeFixed};
+
+//****************************************************************************
+// null joint
+
+static void nullGetInfo1 (dxJointNull *j, dxJoint::Info1 *info)
+{
+  info->m = 0;
+  info->nub = 0;
+}
+
+
+static void nullGetInfo2 (dxJointNull *joint, dxJoint::Info2 *info)
+{
+  dDebug (0,"this should never get called");
+}
+
+
+dxJoint::Vtable __dnull_vtable = {
+  sizeof(dxJointNull),
+  (dxJoint::init_fn*) 0,
+  (dxJoint::getInfo1_fn*) nullGetInfo1,
+  (dxJoint::getInfo2_fn*) nullGetInfo2,
+  dJointTypeNull};
+
+/******************** breakable joint contribution ***********************/
+extern "C" void dJointSetBreakable (dxJoint *joint, int b) {
+  dAASSERT(joint);
+  if (b) {
+    // we want this joint to be breakable but we must first check if it
+    // was already breakable
+    if (!joint->breakInfo) {
+      // allocate a dxJointBreakInfo struct
+      joint->breakInfo = new dxJointBreakInfo;
+      joint->breakInfo->flags = 0;
+      for (int i = 0; i < 3; i++) {
+        joint->breakInfo->b1MaxF[0] = 0;
+        joint->breakInfo->b1MaxT[0] = 0;
+        joint->breakInfo->b2MaxF[0] = 0;
+        joint->breakInfo->b2MaxT[0] = 0;
+      }
+	  joint->breakInfo->callback = 0;
+    }
+    else {
+      // the joint was already breakable
+      return;
+    }
+  }
+  else {
+    // we want this joint to be unbreakable mut we must first check if
+    // it is alreay unbreakable
+    if (joint->breakInfo) {
+      // deallocate the dxJointBreakInfo struct
+      delete joint->breakInfo;
+      joint->breakInfo = 0;
+    }
+    else {
+      // the joint was already unbreakable
+      return;
+    }
+  }
+}
+
+extern "C" void dJointSetBreakCallback (dxJoint *joint, dJointBreakCallback *callbackFunc) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+    dDebug (0, "dJointSetBreakCallback called on unbreakable joint");
+  }
+# endif
+  joint->breakInfo->callback = callbackFunc;
+}
+
+extern "C" void dJointSetBreakMode (dxJoint *joint, int mode) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+    dDebug (0, "dJointSetBreakMode called on unbreakable joint");
+  }
+# endif
+  joint->breakInfo->flags = mode;
+}
+
+extern "C" int dJointGetBreakMode (dxJoint *joint) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+    dDebug (0, "dJointGetBreakMode called on unbreakable joint");
+  }
+# endif
+  return joint->breakInfo->flags;
+}
+
+extern "C" void dJointSetBreakForce (dxJoint *joint, int body, dReal x, dReal y, dReal z) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+  dDebug (0, "dJointSetBreakForce called on unbreakable joint");
+  }
+# endif
+  if (body) {
+	joint->breakInfo->b2MaxF[0] = x;
+	joint->breakInfo->b2MaxF[1] = y;
+	joint->breakInfo->b2MaxF[2] = z;
+  }
+  else {
+	joint->breakInfo->b1MaxF[0] = x;
+	joint->breakInfo->b1MaxF[1] = y;
+	joint->breakInfo->b1MaxF[2] = z;
+  }
+}
+
+extern "C" void dJointSetBreakTorque (dxJoint *joint, int body, dReal x, dReal y, dReal z) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+  dDebug (0, "dJointSetBreakTorque called on unbreakable joint");
+  }
+# endif
+  if (body) {
+	joint->breakInfo->b2MaxT[0] = x;
+	joint->breakInfo->b2MaxT[1] = y;
+	joint->breakInfo->b2MaxT[2] = z;
+  }
+  else {
+	joint->breakInfo->b1MaxT[0] = x;
+	joint->breakInfo->b1MaxT[1] = y;
+	joint->breakInfo->b1MaxT[2] = z;
+  }
+}
+
+extern "C" int dJointIsBreakable (dxJoint *joint) {
+  dAASSERT(joint);
+  return joint->breakInfo != 0;
+}
+
+extern "C" void dJointGetBreakForce (dxJoint *joint, int body, dReal *force) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+    dDebug (0, "dJointGetBreakForce called on unbreakable joint");
+  }
+# endif
+  if (body)
+    for (int i=0; i<3; i++) force[i]=joint->breakInfo->b2MaxF[i];
+  else
+    for (int i=0; i<3; i++) force[i]=joint->breakInfo->b1MaxF[i];
+}
+
+extern "C" void dJointGetBreakTorque (dxJoint *joint, int body, dReal *torque) {
+  dAASSERT(joint);
+# ifndef dNODEBUG
+  // only works for a breakable joint
+  if (!joint->breakInfo) {
+    dDebug (0, "dJointGetBreakTorque called on unbreakable joint");
+  }
+# endif
+  if (body)
+    for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b2MaxT[i];
+  else
+    for (int i=0; i<3; i++) torque[i]=joint->breakInfo->b1MaxT[i];
+}
+/*************************************************************************/
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/joint.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/joint.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/joint.h	(revision 216)
@@ -0,0 +1,282 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_JOINT_H_
+#define _ODE_JOINT_H_
+
+
+#include "objects.h"
+#include <ode/contact.h>
+#include "obstack.h"
+
+
+// joint flags
+enum {
+  // if this flag is set, the joint was allocated in a joint group
+  dJOINT_INGROUP = 1,
+
+  // if this flag is set, the joint was attached with arguments (0,body).
+  // our convention is to treat all attaches as (body,0), i.e. so node[0].body
+  // is always nonzero, so this flag records the fact that the arguments were
+  // swapped.
+  dJOINT_REVERSE = 2,
+
+  // if this flag is set, the joint can not have just one body attached to it,
+  // it must have either zero or two bodies attached.
+  dJOINT_TWOBODIES = 4
+};
+
+
+// there are two of these nodes in the joint, one for each connection to a
+// body. these are node of a linked list kept by each body of it's connecting
+// joints. but note that the body pointer in each node points to the body that
+// makes use of the *other* node, not this node. this trick makes it a bit
+// easier to traverse the body/joint graph.
+
+struct dxJointNode {
+  dxJoint *joint;		// pointer to enclosing dxJoint object
+  dxBody *body;			// *other* body this joint is connected to
+  dxJointNode *next;		// next node in body's list of connected joints
+};
+
+/******************** breakable joint contribution ***********************/
+struct dxJointBreakInfo : public dBase {
+	int flags;
+	dReal b1MaxF[3]; // maximum force on body 1
+	dReal b1MaxT[3]; // maximum torque on body 1
+	dReal b2MaxF[3]; // maximum force on body 2
+	dReal b2MaxT[3]; // maximum torque on body 2
+	dJointBreakCallback *callback; // function that is called when this joint breaks
+};
+/*************************************************************************/
+
+struct dxJoint : public dObject {
+  // naming convention: the "first" body this is connected to is node[0].body,
+  // and the "second" body is node[1].body. if this joint is only connected
+  // to one body then the second body is 0.
+
+  // info returned by getInfo1 function. the constraint dimension is m (<=6).
+  // i.e. that is the total number of rows in the jacobian. `nub' is the
+  // number of unbounded variables (which have lo,hi = -/+ infinity).
+
+  struct Info1 {
+    int m,nub;
+  };
+
+  // info returned by getInfo2 function
+
+  struct Info2 {
+    // integrator parameters: frames per second (1/stepsize), default error
+    // reduction parameter (0..1).
+    dReal fps,erp;
+
+    // for the first and second body, pointers to two (linear and angular)
+    // n*3 jacobian sub matrices, stored by rows. these matrices will have
+    // been initialized to 0 on entry. if the second body is zero then the
+    // J2xx pointers may be 0.
+    dReal *J1l,*J1a,*J2l,*J2a;
+
+    // elements to jump from one row to the next in J's
+    int rowskip;
+
+    // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+    // "constraint force mixing" vector. c is set to zero on entry, cfm is
+    // set to a constant value (typically very small or zero) value on entry.
+    dReal *c,*cfm;
+
+    // lo and hi limits for variables (set to -/+ infinity on entry).
+    dReal *lo,*hi;
+
+    // findex vector for variables. see the LCP solver interface for a
+    // description of what this does. this is set to -1 on entry.
+    // note that the returned indexes are relative to the first index of
+    // the constraint.
+    int *findex;
+  };
+
+  // virtual function table: size of the joint structure, function pointers.
+  // we do it this way instead of using C++ virtual functions because
+  // sometimes we need to allocate joints ourself within a memory pool.
+
+  typedef void init_fn (dxJoint *joint);
+  typedef void getInfo1_fn (dxJoint *joint, Info1 *info);
+  typedef void getInfo2_fn (dxJoint *joint, Info2 *info);
+  struct Vtable {
+    int size;
+    init_fn *init;
+    getInfo1_fn *getInfo1;
+    getInfo2_fn *getInfo2;
+    int typenum;		// a dJointTypeXXX type number
+  };
+
+  Vtable *vtable;		// virtual function table
+  int flags;			// dJOINT_xxx flags
+  dxJointNode node[2];		// connections to bodies. node[1].body can be 0
+  dJointFeedback *feedback;	// optional feedback structure
+  
+  /******************** breakable joint contribution ***********************/
+  // optional break info structure. if this is not NULL the the joint is
+  // breakable.
+  dxJointBreakInfo *breakInfo;
+  /*************************************************************************/
+};
+
+
+// joint group. NOTE: any joints in the group that have their world destroyed
+// will have their world pointer set to 0.
+
+struct dxJointGroup : public dBase {
+  int num;		// number of joints on the stack
+  dObStack stack;	// a stack of (possibly differently sized) dxJoint
+};			// objects.
+
+
+// common limit and motor information for a single joint axis of movement
+struct dxJointLimitMotor {
+  dReal vel,fmax;		// powered joint: velocity, max force
+  dReal lostop,histop;		// joint limits, relative to initial position
+  dReal fudge_factor;		// when powering away from joint limits
+  dReal normal_cfm;		// cfm to use when not at a stop
+  dReal stop_erp,stop_cfm;	// erp and cfm for when at joint limit
+  dReal bounce;			// restitution factor
+  // variables used between getInfo1() and getInfo2()
+  int limit;			// 0=free, 1=at lo limit, 2=at hi limit
+  dReal limit_err;		// if at limit, amount over limit
+
+  void init (dxWorld *);
+  void set (int num, dReal value);
+  dReal get (int num);
+  int testRotationalLimit (dReal angle);
+  int addLimot (dxJoint *joint, dxJoint::Info2 *info, int row,
+		dVector3 ax1, int rotational);
+};
+
+
+// ball and socket
+
+struct dxJointBall : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+};
+extern struct dxJoint::Vtable __dball_vtable;
+
+
+// hinge
+
+struct dxJointHinge : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dVector3 axis1;		// axis w.r.t first body
+  dVector3 axis2;		// axis w.r.t second body
+  dQuaternion qrel;		// initial relative rotation body1 -> body2
+  dxJointLimitMotor limot;	// limit and motor information
+};
+extern struct dxJoint::Vtable __dhinge_vtable;
+
+
+// universal
+
+struct dxJointUniversal : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dVector3 axis1;		// axis w.r.t first body
+  dVector3 axis2;		// axis w.r.t second body
+  dQuaternion qrel1;	// initial relative rotation body1 -> virtual cross piece
+  dQuaternion qrel2;    // initial relative rotation virtual cross piece -> body2
+  dxJointLimitMotor limot1;	// limit and motor information for axis1
+  dxJointLimitMotor limot2;	// limit and motor information for axis2
+};
+extern struct dxJoint::Vtable __duniversal_vtable;
+
+
+// slider. if body2 is 0 then qrel is the absolute rotation of body1 and
+// offset is the position of body1 center along axis1.
+
+struct dxJointSlider : public dxJoint {
+  dVector3 axis1;		// axis w.r.t first body
+  dQuaternion qrel;		// initial relative rotation body1 -> body2
+  dVector3 offset;		// point relative to body2 that should be
+				// aligned with body1 center along axis1
+  dxJointLimitMotor limot;	// limit and motor information
+};
+extern struct dxJoint::Vtable __dslider_vtable;
+
+
+// contact
+
+struct dxJointContact : public dxJoint {
+  int the_m;			// number of rows computed by getInfo1
+  dContact contact;
+};
+extern struct dxJoint::Vtable __dcontact_vtable;
+
+
+// hinge 2
+
+struct dxJointHinge2 : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dVector3 axis1;		// axis 1 w.r.t first body
+  dVector3 axis2;		// axis 2 w.r.t second body
+  dReal c0,s0;			// cos,sin of desired angle between axis 1,2
+  dVector3 v1,v2;		// angle ref vectors embedded in first body
+  dxJointLimitMotor limot1;	// limit+motor info for axis 1
+  dxJointLimitMotor limot2;	// limit+motor info for axis 2
+  dReal susp_erp,susp_cfm;	// suspension parameters (erp,cfm)
+};
+extern struct dxJoint::Vtable __dhinge2_vtable;
+
+
+// angular motor
+
+struct dxJointAMotor : public dxJoint {
+  int num;			// number of axes (0..3)
+  int mode;			// a dAMotorXXX constant
+  int rel[3];			// what the axes are relative to (global,b1,b2)
+  dVector3 axis[3];		// three axes
+  dxJointLimitMotor limot[3];	// limit+motor info for axes
+  dReal angle[3];		// user-supplied angles for axes
+  // these vectors are used for calculating euler angles
+  dVector3 reference1;		// original axis[2], relative to body 1
+  dVector3 reference2;		// original axis[0], relative to body 2
+};
+extern struct dxJoint::Vtable __damotor_vtable;
+
+
+// fixed
+
+struct dxJointFixed : public dxJoint {
+  dQuaternion qrel;		// initial relative rotation body1 -> body2
+  dVector3 offset;		// relative offset between the bodies
+};
+extern struct dxJoint::Vtable __dfixed_vtable;
+
+
+// null joint, for testing only
+
+struct dxJointNull : public dxJoint {
+};
+extern struct dxJoint::Vtable __dnull_vtable;
+
+
+
+#endif
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/objects.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/objects.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/objects.h	(revision 216)
@@ -0,0 +1,252 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_OBJECTS_H_
+#define _ODE_OBJECTS_H_
+
+#include <ode/common.h>
+#include <ode/mass.h>
+#include <ode/contact.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* world */
+
+dWorldID dWorldCreate();
+void dWorldDestroy (dWorldID);
+
+void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z);
+void dWorldGetGravity (dWorldID, dVector3 gravity);
+void dWorldSetERP (dWorldID, dReal erp);
+dReal dWorldGetERP (dWorldID);
+void dWorldSetCFM (dWorldID, dReal cfm);
+dReal dWorldGetCFM (dWorldID);
+void dWorldStep (dWorldID, dReal stepsize);
+void dWorldImpulseToForce (dWorldID, dReal stepsize,
+			   dReal ix, dReal iy, dReal iz, dVector3 force);
+
+/* StepFast1 functions */
+
+void dWorldStepFast1(dWorldID, dReal stepsize, int maxiterations);
+void dWorldSetAutoEnableDepthSF1(dWorldID, int autoEnableDepth);
+
+int dWorldGetAutoEnableDepthSF1(dWorldID);
+
+void dBodySetAutoDisableThresholdSF1(dBodyID, dReal autoDisableThreshold);
+
+/* These functions are not yet implemented by ODE. */
+/*
+dReal dBodyGetAutoDisableThresholdSF1(dBodyID);
+
+void dBodySetAutoDisableStepsSF1(dBodyID, int AutoDisableSteps);
+
+int dBodyGetAutoDisableStepsSF1(dBodyID);
+
+void dBodySetAutoDisableSF1(dBodyID, int doAutoDisable);
+
+int dBodyGetAutoDisableSF1(dBodyID);
+*/
+
+/* bodies */
+
+dBodyID dBodyCreate (dWorldID);
+void dBodyDestroy (dBodyID);
+
+void  dBodySetData (dBodyID, void *data);
+void *dBodyGetData (dBodyID);
+
+void dBodySetPosition   (dBodyID, dReal x, dReal y, dReal z);
+void dBodySetRotation   (dBodyID, const dMatrix3 R);
+void dBodySetQuaternion (dBodyID, const dQuaternion q);
+void dBodySetLinearVel  (dBodyID, dReal x, dReal y, dReal z);
+void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z);
+const dReal * dBodyGetPosition   (dBodyID);
+const dReal * dBodyGetRotation   (dBodyID);	/* ptr to 4x3 rot matrix */
+const dReal * dBodyGetQuaternion (dBodyID);
+const dReal * dBodyGetLinearVel  (dBodyID);
+const dReal * dBodyGetAngularVel (dBodyID);
+
+void dBodySetMass (dBodyID, const dMass *mass);
+void dBodyGetMass (dBodyID, dMass *mass);
+
+void dBodyAddForce            (dBodyID, dReal fx, dReal fy, dReal fz);
+void dBodyAddTorque           (dBodyID, dReal fx, dReal fy, dReal fz);
+void dBodyAddRelForce         (dBodyID, dReal fx, dReal fy, dReal fz);
+void dBodyAddRelTorque        (dBodyID, dReal fx, dReal fy, dReal fz);
+void dBodyAddForceAtPos       (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+void dBodyAddForceAtRelPos    (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+void dBodyAddRelForceAtPos    (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+
+const dReal * dBodyGetForce   (dBodyID);
+const dReal * dBodyGetTorque  (dBodyID);
+void dBodySetForce  (dBodyID b, dReal x, dReal y, dReal z);
+void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z);
+
+void dBodyGetRelPointPos    (dBodyID, dReal px, dReal py, dReal pz,
+			     dVector3 result);
+void dBodyGetRelPointVel    (dBodyID, dReal px, dReal py, dReal pz,
+			     dVector3 result);
+void dBodyGetPointVel       (dBodyID, dReal px, dReal py, dReal pz,
+			     dVector3 result);
+void dBodyGetPosRelPoint    (dBodyID, dReal px, dReal py, dReal pz,
+			     dVector3 result);
+void dBodyVectorToWorld     (dBodyID, dReal px, dReal py, dReal pz,
+			     dVector3 result);
+void dBodyVectorFromWorld   (dBodyID, dReal px, dReal py, dReal pz,
+			     dVector3 result);
+
+void dBodySetFiniteRotationMode (dBodyID, int mode);
+void dBodySetFiniteRotationAxis (dBodyID, dReal x, dReal y, dReal z);
+
+int dBodyGetFiniteRotationMode (dBodyID);
+void dBodyGetFiniteRotationAxis (dBodyID, dVector3 result);
+
+int dBodyGetNumJoints (dBodyID b);
+dJointID dBodyGetJoint (dBodyID, int index);
+
+void dBodyEnable (dBodyID);
+void dBodyDisable (dBodyID);
+int dBodyIsEnabled (dBodyID);
+
+void dBodySetGravityMode (dBodyID b, int mode);
+int dBodyGetGravityMode (dBodyID b);
+
+
+/* joints */
+
+dJointID dJointCreateBall (dWorldID, dJointGroupID);
+dJointID dJointCreateHinge (dWorldID, dJointGroupID);
+dJointID dJointCreateSlider (dWorldID, dJointGroupID);
+dJointID dJointCreateContact (dWorldID, dJointGroupID, const dContact *);
+dJointID dJointCreateHinge2 (dWorldID, dJointGroupID);
+dJointID dJointCreateUniversal (dWorldID, dJointGroupID);
+dJointID dJointCreateFixed (dWorldID, dJointGroupID);
+dJointID dJointCreateNull (dWorldID, dJointGroupID);
+dJointID dJointCreateAMotor (dWorldID, dJointGroupID);
+
+void dJointDestroy (dJointID);
+
+dJointGroupID dJointGroupCreate (int max_size);
+void dJointGroupDestroy (dJointGroupID);
+void dJointGroupEmpty (dJointGroupID);
+
+void dJointAttach (dJointID, dBodyID body1, dBodyID body2);
+void dJointSetData (dJointID, void *data);
+void *dJointGetData (dJointID);
+int dJointGetType (dJointID);
+dBodyID dJointGetBody (dJointID, int index);
+
+void dJointSetFeedback (dJointID, dJointFeedback *);
+dJointFeedback *dJointGetFeedback (dJointID);
+
+/******************** breakable joint contribution ***********************/
+void dJointSetBreakable (dJointID, int b);
+void dJointSetBreakCallback (dJointID, dJointBreakCallback *callbackFunc);
+void dJointSetBreakMode (dJointID, int mode);
+int dJointGetBreakMode (dJointID);
+void dJointSetBreakForce (dJointID, int body, dReal x, dReal y, dReal z);
+void dJointSetBreakTorque (dJointID, int body, dReal x, dReal y, dReal z);
+int dJointIsBreakable (dJointID);
+void dJointGetBreakForce (dJointID, int body, dReal *force);
+void dJointGetBreakTorque (dJointID, int body, dReal *torque);
+/*************************************************************************/
+
+void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z);
+void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z);
+void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z);
+void dJointSetHingeParam (dJointID, int parameter, dReal value);
+void dJointAddHingeTorque(dJointID joint, dReal torque);
+void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z);
+void dJointSetSliderParam (dJointID, int parameter, dReal value);
+void dJointAddSliderForce(dJointID joint, dReal force);
+void dJointSetHinge2Anchor (dJointID, dReal x, dReal y, dReal z);
+void dJointSetHinge2Axis1 (dJointID, dReal x, dReal y, dReal z);
+void dJointSetHinge2Axis2 (dJointID, dReal x, dReal y, dReal z);
+void dJointSetHinge2Param (dJointID, int parameter, dReal value);
+void dJointAddHinge2Torques(dJointID joint, dReal torque1, dReal torque2);
+void dJointSetUniversalAnchor (dJointID, dReal x, dReal y, dReal z);
+void dJointSetUniversalAxis1 (dJointID, dReal x, dReal y, dReal z);
+void dJointSetUniversalAxis2 (dJointID, dReal x, dReal y, dReal z);
+void dJointSetUniversalParam (dJointID, int parameter, dReal value);
+void dJointAddUniversalTorques(dJointID joint, dReal torque1, dReal torque2);
+void dJointSetFixed (dJointID);
+void dJointSetAMotorNumAxes (dJointID, int num);
+void dJointSetAMotorAxis (dJointID, int anum, int rel,
+			  dReal x, dReal y, dReal z);
+void dJointSetAMotorAngle (dJointID, int anum, dReal angle);
+void dJointSetAMotorParam (dJointID, int parameter, dReal value);
+void dJointSetAMotorMode (dJointID, int mode);
+void dJointAddAMotorTorques (dJointID, dReal torque1, dReal torque2, dReal torque3);
+
+void dJointGetBallAnchor (dJointID, dVector3 result);
+void dJointGetBallAnchor2 (dJointID, dVector3 result);
+void dJointGetHingeAnchor (dJointID, dVector3 result);
+void dJointGetHingeAnchor2 (dJointID, dVector3 result);
+void dJointGetHingeAxis (dJointID, dVector3 result);
+dReal dJointGetHingeParam (dJointID, int parameter);
+dReal dJointGetHingeAngle (dJointID);
+dReal dJointGetHingeAngleRate (dJointID);
+dReal dJointGetSliderPosition (dJointID);
+dReal dJointGetSliderPositionRate (dJointID);
+void dJointGetSliderAxis (dJointID, dVector3 result);
+dReal dJointGetSliderParam (dJointID, int parameter);
+void dJointGetHinge2Anchor (dJointID, dVector3 result);
+void dJointGetHinge2Anchor2 (dJointID, dVector3 result);
+void dJointGetHinge2Axis1 (dJointID, dVector3 result);
+void dJointGetHinge2Axis2 (dJointID, dVector3 result);
+dReal dJointGetHinge2Param (dJointID, int parameter);
+dReal dJointGetHinge2Angle1 (dJointID);
+dReal dJointGetHinge2Angle1Rate (dJointID);
+dReal dJointGetHinge2Angle2Rate (dJointID);
+void dJointGetUniversalAnchor (dJointID, dVector3 result);
+void dJointGetUniversalAnchor2 (dJointID, dVector3 result);
+void dJointGetUniversalAxis1 (dJointID, dVector3 result);
+void dJointGetUniversalAxis2 (dJointID, dVector3 result);
+dReal dJointGetUniversalParam (dJointID, int parameter);
+dReal dJointGetUniversalAngle1 (dJointID);
+dReal dJointGetUniversalAngle2 (dJointID);
+dReal dJointGetUniversalAngle1Rate (dJointID);
+dReal dJointGetUniversalAngle2Rate (dJointID);
+int dJointGetAMotorNumAxes (dJointID);
+void dJointGetAMotorAxis (dJointID, int anum, dVector3 result);
+int dJointGetAMotorAxisRel (dJointID, int anum);
+dReal dJointGetAMotorAngle (dJointID, int anum);
+dReal dJointGetAMotorAngleRate (dJointID, int anum);
+dReal dJointGetAMotorParam (dJointID, int parameter);
+int dJointGetAMotorMode (dJointID);
+
+int dAreConnected (dBodyID, dBodyID);
+int dAreConnectedExcluding (dBodyID, dBodyID, int joint_type);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/ode.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/ode.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/ode.cpp	(revision 216)
@@ -0,0 +1,1404 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+// this source file is mostly concerned with the data structures, not the
+// numerics.
+
+#include "objects.h"
+#include <ode/ode.h>
+#include "joint.h"
+#include <ode/odemath.h>
+#include <ode/matrix.h>
+#include "step.h"
+#include <ode/memory.h>
+#include <ode/error.h>
+
+// misc defines
+#define ALLOCA dALLOCA16
+
+//****************************************************************************
+// utility
+
+static inline void initObject (dObject *obj, dxWorld *w)
+{
+  obj->world = w;
+  obj->next = 0;
+  obj->tome = 0;
+  obj->userdata = 0;
+  obj->tag = 0;
+}
+
+
+// add an object `obj' to the list who's head pointer is pointed to by `first'.
+
+static inline void addObjectToList (dObject *obj, dObject **first)
+{
+  obj->next = *first;
+  obj->tome = first;
+  if (*first) (*first)->tome = &obj->next;
+  (*first) = obj;
+}
+
+
+// remove the object from the linked list
+
+static inline void removeObjectFromList (dObject *obj)
+{
+  if (obj->next) obj->next->tome = obj->tome;
+  *(obj->tome) = obj->next;
+  // safeguard
+  obj->next = 0;
+  obj->tome = 0;
+}
+
+
+// remove the joint from neighbour lists of all connected bodies
+
+static void removeJointReferencesFromAttachedBodies (dxJoint *j)
+{
+  for (int i=0; i<2; i++) {
+    dxBody *body = j->node[i].body;
+    if (body) {
+      dxJointNode *n = body->firstjoint;
+      dxJointNode *last = 0;
+      while (n) {
+	if (n->joint == j) {
+	  if (last) last->next = n->next;
+	  else body->firstjoint = n->next;
+	  break;
+	}
+	last = n;
+	n = n->next;
+      }
+    }
+  }
+  j->node[0].body = 0;
+  j->node[0].next = 0;
+  j->node[1].body = 0;
+  j->node[1].next = 0;
+}
+
+//****************************************************************************
+// island processing
+
+// this groups all joints and bodies in a world into islands. all objects
+// in an island are reachable by going through connected bodies and joints.
+// each island can be simulated separately.
+// note that joints that are not attached to anything will not be included
+// in any island, an so they do not affect the simulation.
+//
+// this function starts new island from unvisited bodies. however, it will
+// never start a new islands from a disabled body. thus islands of disabled
+// bodies will not be included in the simulation. disabled bodies are
+// re-enabled if they are found to be part of an active island.
+
+static void processIslands (dxWorld *world, dReal stepsize)
+{
+  dxBody *b,*bb,**body;
+  dxJoint *j,**joint;
+
+  // nothing to do if no bodies
+  if (world->nb <= 0) return;
+
+  // make arrays for body and joint lists (for a single island) to go into
+  body = (dxBody**) ALLOCA (world->nb * sizeof(dxBody*));
+  joint = (dxJoint**) ALLOCA (world->nj * sizeof(dxJoint*));
+  int bcount = 0;	// number of bodies in `body'
+  int jcount = 0;	// number of joints in `joint'
+
+  // set all body/joint tags to 0
+  for (b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0;
+  for (j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0;
+
+  // allocate a stack of unvisited bodies in the island. the maximum size of
+  // the stack can be the lesser of the number of bodies or joints, because
+  // new bodies are only ever added to the stack by going through untagged
+  // joints. all the bodies in the stack must be tagged!
+  int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
+  dxBody **stack = (dxBody**) ALLOCA (stackalloc * sizeof(dxBody*));
+
+  for (bb=world->firstbody; bb; bb=(dxBody*)bb->next) {
+    // get bb = the next enabled, untagged body, and tag it
+    if (bb->tag || (bb->flags & dxBodyDisabled)) continue;
+    bb->tag = 1;
+
+    // tag all bodies and joints starting from bb.
+    int stacksize = 0;
+    b = bb;
+    body[0] = bb;
+    bcount = 1;
+    jcount = 0;
+    goto quickstart;
+    while (stacksize > 0) {
+      b = stack[--stacksize];	// pop body off stack
+      body[bcount++] = b;	// put body on body list
+      quickstart:
+
+      // traverse and tag all body's joints, add untagged connected bodies
+      // to stack
+      for (dxJointNode *n=b->firstjoint; n; n=n->next) {
+	if (!n->joint->tag) {
+	  n->joint->tag = 1;
+	  joint[jcount++] = n->joint;
+	  if (n->body && !n->body->tag) {
+	    n->body->tag = 1;
+	    stack[stacksize++] = n->body;
+	  }
+	}
+      }
+      dIASSERT(stacksize <= world->nb);
+      dIASSERT(stacksize <= world->nj);
+    }
+
+    // now do something with body and joint lists
+    dInternalStepIsland (world,body,bcount,joint,jcount,stepsize);
+
+    // what we've just done may have altered the body/joint tag values.
+    // we must make sure that these tags are nonzero.
+    // also make sure all bodies are in the enabled state.
+    int i;
+    for (i=0; i<bcount; i++) {
+      body[i]->tag = 1;
+      body[i]->flags &= ~dxBodyDisabled;
+    }
+    for (i=0; i<jcount; i++) joint[i]->tag = 1;
+  }
+
+  // if debugging, check that all objects (except for disabled bodies,
+  // unconnected joints, and joints that are connected to disabled bodies)
+  // were tagged.
+# ifndef dNODEBUG
+  for (b=world->firstbody; b; b=(dxBody*)b->next) {
+    if (b->flags & dxBodyDisabled) {
+      if (b->tag) dDebug (0,"disabled body tagged");
+    }
+    else {
+      if (!b->tag) dDebug (0,"enabled body not tagged");
+    }
+  }
+  for (j=world->firstjoint; j; j=(dxJoint*)j->next) {
+    if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0) ||
+	(j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0)) {
+      if (!j->tag) dDebug (0,"attached enabled joint not tagged");
+    }
+    else {
+      if (j->tag) dDebug (0,"unattached or disabled joint tagged");
+    }
+  }
+# endif
+  /******************** breakable joint contribution ***********************/
+  dxJoint* nextJ;
+  if (!world->firstjoint)
+    nextJ = 0;
+  else
+    nextJ = (dxJoint*)world->firstjoint->next;
+  for (j=world->firstjoint; j; j=nextJ) {
+  	nextJ = (dxJoint*)j->next;
+	// check if joint is breakable and broken
+    if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) {
+		// detach (break) the joint
+        dJointAttach (j, 0, 0);
+		// call the callback function if it is set
+		if (j->breakInfo->callback) j->breakInfo->callback (j);
+		// finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set
+		if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j);
+      }
+  }
+  /*************************************************************************/
+}
+
+//****************************************************************************
+// debugging
+
+// see if an object list loops on itself (if so, it's bad).
+
+static int listHasLoops (dObject *first)
+{
+  if (first==0 || first->next==0) return 0;
+  dObject *a=first,*b=first->next;
+  int skip=0;
+  while (b) {
+    if (a==b) return 1;
+    b = b->next;
+    if (skip) a = a->next;
+    skip ^= 1;
+  }
+  return 0;
+}
+
+
+// check the validity of the world data structures
+
+static void checkWorld (dxWorld *w)
+{
+  dxBody *b;
+  dxJoint *j;
+
+  // check there are no loops
+  if (listHasLoops (w->firstbody)) dDebug (0,"body list has loops");
+  if (listHasLoops (w->firstjoint)) dDebug (0,"joint list has loops");
+
+  // check lists are well formed (check `tome' pointers)
+  for (b=w->firstbody; b; b=(dxBody*)b->next) {
+    if (b->next && b->next->tome != &b->next)
+      dDebug (0,"bad tome pointer in body list");
+  }
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    if (j->next && j->next->tome != &j->next)
+      dDebug (0,"bad tome pointer in joint list");
+  }
+
+  // check counts
+  int n = 0;
+  for (b=w->firstbody; b; b=(dxBody*)b->next) n++;
+  if (w->nb != n) dDebug (0,"body count incorrect");
+  n = 0;
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) n++;
+  if (w->nj != n) dDebug (0,"joint count incorrect");
+
+  // set all tag values to a known value
+  static int count = 0;
+  count++;
+  for (b=w->firstbody; b; b=(dxBody*)b->next) b->tag = count;
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) j->tag = count;
+
+  // check all body/joint world pointers are ok
+  for (b=w->firstbody; b; b=(dxBody*)b->next) if (b->world != w)
+    dDebug (0,"bad world pointer in body list");
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) if (j->world != w)
+    dDebug (0,"bad world pointer in joint list");
+
+  /*
+  // check for half-connected joints - actually now these are valid
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    if (j->node[0].body || j->node[1].body) {
+      if (!(j->node[0].body && j->node[1].body))
+	dDebug (0,"half connected joint found");
+    }
+  }
+  */
+
+  // check that every joint node appears in the joint lists of both bodies it
+  // attaches
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    for (int i=0; i<2; i++) {
+      if (j->node[i].body) {
+	int ok = 0;
+	for (dxJointNode *n=j->node[i].body->firstjoint; n; n=n->next) {
+	  if (n->joint == j) ok = 1;
+	}
+	if (ok==0) dDebug (0,"joint not in joint list of attached body");
+      }
+    }
+  }
+
+  // check all body joint lists (correct body ptrs)
+  for (b=w->firstbody; b; b=(dxBody*)b->next) {
+    for (dxJointNode *n=b->firstjoint; n; n=n->next) {
+      if (&n->joint->node[0] == n) {
+	if (n->joint->node[1].body != b)
+	  dDebug (0,"bad body pointer in joint node of body list (1)");
+      }
+      else {
+	if (n->joint->node[0].body != b)
+	  dDebug (0,"bad body pointer in joint node of body list (2)");
+      }
+      if (n->joint->tag != count) dDebug (0,"bad joint node pointer in body");
+    }
+  }
+
+  // check all body pointers in joints, check they are distinct
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    if (j->node[0].body && (j->node[0].body == j->node[1].body))
+      dDebug (0,"non-distinct body pointers in joint");
+    if ((j->node[0].body && j->node[0].body->tag != count) ||
+	(j->node[1].body && j->node[1].body->tag != count))
+      dDebug (0,"bad body pointer in joint");
+  }
+}
+
+
+void dWorldCheck (dxWorld *w)
+{
+  checkWorld (w);
+}
+
+//****************************************************************************
+// body
+
+dxBody *dBodyCreate (dxWorld *w)
+{
+  dAASSERT (w);
+  dxBody *b = new dxBody;
+  initObject (b,w);
+  b->firstjoint = 0;
+  b->flags = 0;
+  b->geom = 0;
+  dMassSetParameters (&b->mass,1,0,0,0,1,1,1,0,0,0);
+  dSetZero (b->invI,4*3);
+  b->invI[0] = 1;
+  b->invI[5] = 1;
+  b->invI[10] = 1;
+  b->invMass = 1;
+  dSetZero (b->pos,4);
+  dSetZero (b->q,4);
+  b->q[0] = 1;
+  dRSetIdentity (b->R);
+  dSetZero (b->lvel,4);
+  dSetZero (b->avel,4);
+  dSetZero (b->facc,4);
+  dSetZero (b->tacc,4);
+  dSetZero (b->finite_rot_axis,4);
+  addObjectToList (b,(dObject **) &w->firstbody);
+  w->nb++;
+  return b;
+}
+
+
+void dBodyDestroy (dxBody *b)
+{
+  dAASSERT (b);
+
+  // all geoms that link to this body must be notified that the body is about
+  // to disappear. note that the call to dGeomSetBody(geom,0) will result in
+  // dGeomGetBodyNext() returning 0 for the body, so we must get the next body
+  // before setting the body to 0.
+  dxGeom *next_geom = 0;
+  for (dxGeom *geom = b->geom; geom; geom = next_geom) {
+    next_geom = dGeomGetBodyNext (geom);
+    dGeomSetBody (geom,0);
+  }
+
+  // detach all neighbouring joints, then delete this body.
+  dxJointNode *n = b->firstjoint;
+  while (n) {
+    // sneaky trick to speed up removal of joint references (black magic)
+    n->joint->node[(n == n->joint->node)].body = 0;
+
+    dxJointNode *next = n->next;
+    n->next = 0;
+    removeJointReferencesFromAttachedBodies (n->joint);
+    n = next;
+  }
+  removeObjectFromList (b);
+  b->world->nb--;
+  delete b;
+}
+
+
+void dBodySetData (dBodyID b, void *data)
+{
+  dAASSERT (b);
+  b->userdata = data;
+}
+
+
+void *dBodyGetData (dBodyID b)
+{
+  dAASSERT (b);
+  return b->userdata;
+}
+
+
+void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->pos[0] = x;
+  b->pos[1] = y;
+  b->pos[2] = z;
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+
+void dBodySetRotation (dBodyID b, const dMatrix3 R)
+{
+  dAASSERT (b && R);
+  dQuaternion q;
+  dRtoQ (R,q);
+  dNormalize4 (q);
+  b->q[0] = q[0];
+  b->q[1] = q[1];
+  b->q[2] = q[2];
+  b->q[3] = q[3];
+  dQtoR (b->q,b->R);
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+
+void dBodySetQuaternion (dBodyID b, const dQuaternion q)
+{
+  dAASSERT (b && q);
+  b->q[0] = q[0];
+  b->q[1] = q[1];
+  b->q[2] = q[2];
+  b->q[3] = q[3];
+  dNormalize4 (b->q);
+  dQtoR (b->q,b->R);
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+
+void dBodySetLinearVel  (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->lvel[0] = x;
+  b->lvel[1] = y;
+  b->lvel[2] = z;
+}
+
+
+void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->avel[0] = x;
+  b->avel[1] = y;
+  b->avel[2] = z;
+}
+
+
+const dReal * dBodyGetPosition (dBodyID b)
+{
+  dAASSERT (b);
+  return b->pos;
+}
+
+
+const dReal * dBodyGetRotation (dBodyID b)
+{
+  dAASSERT (b);
+  return b->R;
+}
+
+
+const dReal * dBodyGetQuaternion (dBodyID b)
+{
+  dAASSERT (b);
+  return b->q;
+}
+
+
+const dReal * dBodyGetLinearVel (dBodyID b)
+{
+  dAASSERT (b);
+  return b->lvel;
+}
+
+
+const dReal * dBodyGetAngularVel (dBodyID b)
+{
+  dAASSERT (b);
+  return b->avel;
+}
+
+
+void dBodySetMass (dBodyID b, const dMass *mass)
+{
+  dAASSERT (b && mass);
+  memcpy (&b->mass,mass,sizeof(dMass));
+  if (dInvertPDMatrix (b->mass.I,b->invI,3)==0) {
+    dDEBUGMSG ("inertia must be positive definite");
+    dRSetIdentity (b->invI);
+  }
+  b->invMass = dRecip(b->mass.mass);
+}
+
+
+void dBodyGetMass (dBodyID b, dMass *mass)
+{
+  dAASSERT (b && mass);
+  memcpy (mass,&b->mass,sizeof(dMass));
+}
+
+
+void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  b->facc[0] += fx;
+  b->facc[1] += fy;
+  b->facc[2] += fz;
+}
+
+
+void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  b->tacc[0] += fx;
+  b->tacc[1] += fy;
+  b->tacc[2] += fz;
+}
+
+
+void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  dVector3 t1,t2;
+  t1[0] = fx;
+  t1[1] = fy;
+  t1[2] = fz;
+  t1[3] = 0;
+  dMULTIPLY0_331 (t2,b->R,t1);
+  b->facc[0] += t2[0];
+  b->facc[1] += t2[1];
+  b->facc[2] += t2[2];
+}
+
+
+void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  dVector3 t1,t2;
+  t1[0] = fx;
+  t1[1] = fy;
+  t1[2] = fz;
+  t1[3] = 0;
+  dMULTIPLY0_331 (t2,b->R,t1);
+  b->tacc[0] += t2[0];
+  b->tacc[1] += t2[1];
+  b->tacc[2] += t2[2];
+}
+
+
+void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			 dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  b->facc[0] += fx;
+  b->facc[1] += fy;
+  b->facc[2] += fz;
+  dVector3 f,q;
+  f[0] = fx;
+  f[1] = fy;
+  f[2] = fz;
+  q[0] = px - b->pos[0];
+  q[1] = py - b->pos[1];
+  q[2] = pz - b->pos[2];
+  dCROSS (b->tacc,+=,q,f);
+}
+
+
+void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			    dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  dVector3 prel,f,p;
+  f[0] = fx;
+  f[1] = fy;
+  f[2] = fz;
+  f[3] = 0;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (p,b->R,prel);
+  b->facc[0] += f[0];
+  b->facc[1] += f[1];
+  b->facc[2] += f[2];
+  dCROSS (b->tacc,+=,p,f);
+}
+
+
+void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			    dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  dVector3 frel,f;
+  frel[0] = fx;
+  frel[1] = fy;
+  frel[2] = fz;
+  frel[3] = 0;
+  dMULTIPLY0_331 (f,b->R,frel);
+  b->facc[0] += f[0];
+  b->facc[1] += f[1];
+  b->facc[2] += f[2];
+  dVector3 q;
+  q[0] = px - b->pos[0];
+  q[1] = py - b->pos[1];
+  q[2] = pz - b->pos[2];
+  dCROSS (b->tacc,+=,q,f);
+}
+
+
+void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			       dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  dVector3 frel,prel,f,p;
+  frel[0] = fx;
+  frel[1] = fy;
+  frel[2] = fz;
+  frel[3] = 0;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (f,b->R,frel);
+  dMULTIPLY0_331 (p,b->R,prel);
+  b->facc[0] += f[0];
+  b->facc[1] += f[1];
+  b->facc[2] += f[2];
+  dCROSS (b->tacc,+=,p,f);
+}
+
+
+const dReal * dBodyGetForce (dBodyID b)
+{
+  dAASSERT (b);
+  return b->facc;
+}
+
+
+const dReal * dBodyGetTorque (dBodyID b)
+{
+  dAASSERT (b);
+  return b->tacc;
+}
+
+
+void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->facc[0] = x;
+  b->facc[1] = y;
+  b->facc[2] = z;
+}
+
+
+void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->tacc[0] = x;
+  b->tacc[1] = y;
+  b->tacc[2] = z;
+}
+
+
+void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz,
+			  dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 prel,p;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (p,b->R,prel);
+  result[0] = p[0] + b->pos[0];
+  result[1] = p[1] + b->pos[1];
+  result[2] = p[2] + b->pos[2];
+}
+
+
+void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz,
+			  dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 prel,p;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (p,b->R,prel);
+  result[0] = b->lvel[0];
+  result[1] = b->lvel[1];
+  result[2] = b->lvel[2];
+  dCROSS (result,+=,b->avel,p);
+}
+
+
+void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz,
+		       dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 p;
+  p[0] = px - b->pos[0];
+  p[1] = py - b->pos[1];
+  p[2] = pz - b->pos[2];
+  p[3] = 0;
+  result[0] = b->lvel[0];
+  result[1] = b->lvel[1];
+  result[2] = b->lvel[2];
+  dCROSS (result,+=,b->avel,p);
+}
+
+
+void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz,
+			  dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 prel;
+  prel[0] = px - b->pos[0];
+  prel[1] = py - b->pos[1];
+  prel[2] = pz - b->pos[2];
+  prel[3] = 0;
+  dMULTIPLY1_331 (result,b->R,prel);
+}
+
+
+void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz,
+			 dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 p;
+  p[0] = px;
+  p[1] = py;
+  p[2] = pz;
+  p[3] = 0;
+  dMULTIPLY0_331 (result,b->R,p);
+}
+
+
+void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz,
+			   dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 p;
+  p[0] = px;
+  p[1] = py;
+  p[2] = pz;
+  p[3] = 0;
+  dMULTIPLY1_331 (result,b->R,p);
+}
+
+
+void dBodySetFiniteRotationMode (dBodyID b, int mode)
+{
+  dAASSERT (b);
+  b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis);
+  if (mode) {
+    b->flags |= dxBodyFlagFiniteRotation;
+    if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 ||
+	b->finite_rot_axis[2] != 0) {
+      b->flags |= dxBodyFlagFiniteRotationAxis;
+    }
+  }
+}
+
+
+void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->finite_rot_axis[0] = x;
+  b->finite_rot_axis[1] = y;
+  b->finite_rot_axis[2] = z;
+  if (x != 0 || y != 0 || z != 0) {
+    dNormalize3 (b->finite_rot_axis);
+    b->flags |= dxBodyFlagFiniteRotationAxis;
+  }
+  else {
+    b->flags &= ~dxBodyFlagFiniteRotationAxis;
+  }
+}
+
+
+int dBodyGetFiniteRotationMode (dBodyID b)
+{
+  dAASSERT (b);
+  return ((b->flags & dxBodyFlagFiniteRotation) != 0);
+}
+
+
+void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result)
+{
+  dAASSERT (b);
+  result[0] = b->finite_rot_axis[0];
+  result[1] = b->finite_rot_axis[1];
+  result[2] = b->finite_rot_axis[2];
+}
+
+
+int dBodyGetNumJoints (dBodyID b)
+{
+  dAASSERT (b);
+  int count=0;
+  for (dxJointNode *n=b->firstjoint; n; n=n->next, count++);
+  return count;
+}
+
+
+dJointID dBodyGetJoint (dBodyID b, int index)
+{
+  dAASSERT (b);
+  int i=0;
+  for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) {
+    if (i == index) return n->joint;
+  }
+  return 0;
+}
+
+
+void dBodyEnable (dBodyID b)
+{
+  dAASSERT (b);
+  b->flags &= ~dxBodyDisabled;
+}
+
+
+void dBodyDisable (dBodyID b)
+{
+  dAASSERT (b);
+  b->flags |= dxBodyDisabled;
+}
+
+
+int dBodyIsEnabled (dBodyID b)
+{
+  dAASSERT (b);
+  return ((b->flags & dxBodyDisabled) == 0);
+}
+
+
+void dBodySetGravityMode (dBodyID b, int mode)
+{
+  dAASSERT (b);
+  if (mode) b->flags &= ~dxBodyNoGravity;
+  else b->flags |= dxBodyNoGravity;
+}
+
+
+int dBodyGetGravityMode (dBodyID b)
+{
+  dAASSERT (b);
+  return ((b->flags & dxBodyNoGravity) == 0);
+}
+
+//****************************************************************************
+// joints
+
+static void dJointInit (dxWorld *w, dxJoint *j)
+{
+  dIASSERT (w && j);
+  initObject (j,w);
+  j->vtable = 0;
+  j->flags = 0;
+  j->node[0].joint = j;
+  j->node[0].body = 0;
+  j->node[0].next = 0;
+  j->node[1].joint = j;
+  j->node[1].body = 0;
+  j->node[1].next = 0;
+  addObjectToList (j,(dObject **) &w->firstjoint);
+  w->nj++;
+}
+
+
+static dxJoint *createJoint (dWorldID w, dJointGroupID group,
+			     dxJoint::Vtable *vtable)
+{
+  dIASSERT (w && vtable);
+  dxJoint *j;
+  if (group) {
+    j = (dxJoint*) group->stack.alloc (vtable->size);
+    group->num++;
+  }
+  else j = (dxJoint*) dAlloc (vtable->size);
+  dJointInit (w,j);
+  j->vtable = vtable;
+  if (group) j->flags |= dJOINT_INGROUP;
+  if (vtable->init) vtable->init (j);
+  j->feedback = 0;
+  /******************** breakable joint contribution ***********************/
+  j->breakInfo = 0;
+  /*************************************************************************/
+  return j;
+}
+
+
+dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dball_vtable);
+}
+
+
+dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dhinge_vtable);
+}
+
+
+dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dslider_vtable);
+}
+
+
+dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group,
+			       const dContact *c)
+{
+  dAASSERT (w && c);
+  dxJointContact *j = (dxJointContact *)
+    createJoint (w,group,&__dcontact_vtable);
+  j->contact = *c;
+  return j;
+}
+
+
+dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dhinge2_vtable);
+}
+
+
+dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__duniversal_vtable);
+}
+
+
+dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dfixed_vtable);
+}
+
+
+dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dnull_vtable);
+}
+
+
+dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__damotor_vtable);
+}
+
+
+void dJointDestroy (dxJoint *j)
+{
+  dAASSERT (j);
+  if (j->flags & dJOINT_INGROUP) return;
+  removeJointReferencesFromAttachedBodies (j);
+  removeObjectFromList (j);
+  /******************** breakable joint contribution ***********************/
+  if (j->breakInfo) delete j->breakInfo;
+  /*************************************************************************/
+  j->world->nj--;
+  dFree (j,j->vtable->size);
+}
+
+
+dJointGroupID dJointGroupCreate (int max_size)
+{
+  // not any more ... dUASSERT (max_size > 0,"max size must be > 0");
+  dxJointGroup *group = new dxJointGroup;
+  group->num = 0;
+  return group;
+}
+
+
+void dJointGroupDestroy (dJointGroupID group)
+{
+  dAASSERT (group);
+  dJointGroupEmpty (group);
+  delete group;
+}
+
+
+void dJointGroupEmpty (dJointGroupID group)
+{
+  // the joints in this group are detached starting from the most recently
+  // added (at the top of the stack). this helps ensure that the various
+  // linked lists are not traversed too much, as the joints will hopefully
+  // be at the start of those lists.
+  // if any group joints have their world pointer set to 0, their world was
+  // previously destroyed. no special handling is required for these joints.
+
+  dAASSERT (group);
+  int i;
+  dxJoint **jlist = (dxJoint**) ALLOCA (group->num * sizeof(dxJoint*));
+  dxJoint *j = (dxJoint*) group->stack.rewind();
+  for (i=0; i < group->num; i++) {
+    jlist[i] = j;
+    j = (dxJoint*) (group->stack.next (j->vtable->size));
+  }
+  for (i=group->num-1; i >= 0; i--) {
+    if (jlist[i]->world) {
+      removeJointReferencesFromAttachedBodies (jlist[i]);
+      removeObjectFromList (jlist[i]);
+      jlist[i]->world->nj--;
+    }
+  }
+  group->num = 0;
+  group->stack.freeAll();
+}
+
+
+void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2)
+{
+  // check arguments
+  dUASSERT (joint,"bad joint argument");
+  dUASSERT (body1 == 0 || body1 != body2,"can't have body1==body2");
+  dxWorld *world = joint->world;
+  dUASSERT ( (!body1 || body1->world == world) &&
+	     (!body2 || body2->world == world),
+	     "joint and bodies must be in same world");
+
+  // check if the joint can not be attached to just one body
+  dUASSERT (!((joint->flags & dJOINT_TWOBODIES) &&
+	      ((body1 != 0) ^ (body2 != 0))),
+	    "joint can not be attached to just one body");
+
+  // remove any existing body attachments
+  if (joint->node[0].body || joint->node[1].body) {
+    removeJointReferencesFromAttachedBodies (joint);
+  }
+
+  // if a body is zero, make sure that it is body2, so 0 --> node[1].body
+  if (body1==0) {
+    body1 = body2;
+    body2 = 0;
+    joint->flags |= dJOINT_REVERSE;
+  }
+  else {
+    joint->flags &= (~dJOINT_REVERSE);
+  }
+
+  // attach to new bodies
+  joint->node[0].body = body1;
+  joint->node[1].body = body2;
+  if (body1) {
+    joint->node[1].next = body1->firstjoint;
+    body1->firstjoint = &joint->node[1];
+  }
+  else joint->node[1].next = 0;
+  if (body2) {
+    joint->node[0].next = body2->firstjoint;
+    body2->firstjoint = &joint->node[0];
+  }
+  else {
+    joint->node[0].next = 0;
+  }
+}
+
+
+void dJointSetData (dxJoint *joint, void *data)
+{
+  dAASSERT (joint);
+  joint->userdata = data;
+}
+
+
+void *dJointGetData (dxJoint *joint)
+{
+  dAASSERT (joint);
+  return joint->userdata;
+}
+
+
+int dJointGetType (dxJoint *joint)
+{
+  dAASSERT (joint);
+  return joint->vtable->typenum;
+}
+
+
+dBodyID dJointGetBody (dxJoint *joint, int index)
+{
+  dAASSERT (joint);
+  if (index >= 0 && index < 2) return joint->node[index].body;
+  else return 0;
+}
+
+
+void dJointSetFeedback (dxJoint *joint, dJointFeedback *f)
+{
+  dAASSERT (joint);
+  joint->feedback = f;
+}
+
+
+dJointFeedback *dJointGetFeedback (dxJoint *joint)
+{
+  dAASSERT (joint);
+  return joint->feedback;
+}
+
+
+int dAreConnected (dBodyID b1, dBodyID b2)
+{
+  dAASSERT (b1 && b2);
+  // look through b1's neighbour list for b2
+  for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
+    if (n->body == b2) return 1;
+  }
+  return 0;
+}
+
+
+int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type)
+{
+  dAASSERT (b1 && b2);
+  // look through b1's neighbour list for b2
+  for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
+    if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1;
+  }
+  return 0;
+}
+
+//****************************************************************************
+// world
+
+dxWorld * dWorldCreate()
+{
+  dxWorld *w = new dxWorld;
+  w->firstbody = 0;
+  w->firstjoint = 0;
+  w->nb = 0;
+  w->nj = 0;
+  dSetZero (w->gravity,4);
+  w->global_erp = REAL(0.2);
+#if defined(dSINGLE)
+  w->global_cfm = 1e-5f;
+#elif defined(dDOUBLE)
+  w->global_cfm = 1e-10;
+#else
+  #error dSINGLE or dDOUBLE must be defined
+#endif
+  return w;
+}
+
+
+void dWorldDestroy (dxWorld *w)
+{
+  // delete all bodies and joints
+  dAASSERT (w);
+  dxBody *nextb, *b = w->firstbody;
+  while (b) {
+    nextb = (dxBody*) b->next;
+    delete b;
+    b = nextb;
+  }
+  dxJoint *nextj, *j = w->firstjoint;
+  while (j) {
+    nextj = (dxJoint*)j->next;
+    if (j->flags & dJOINT_INGROUP) {
+      // the joint is part of a group, so "deactivate" it instead
+      j->world = 0;
+      j->node[0].body = 0;
+      j->node[0].next = 0;
+      j->node[1].body = 0;
+      j->node[1].next = 0;
+      dMessage (0,"warning: destroying world containing grouped joints");
+    }
+    else {
+      dFree (j,j->vtable->size);
+    }
+    j = nextj;
+  }
+  delete w;
+}
+
+
+void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z)
+{
+  dAASSERT (w);
+  w->gravity[0] = x;
+  w->gravity[1] = y;
+  w->gravity[2] = z;
+}
+
+
+void dWorldGetGravity (dWorldID w, dVector3 g)
+{
+  dAASSERT (w);
+  g[0] = w->gravity[0];
+  g[1] = w->gravity[1];
+  g[2] = w->gravity[2];
+}
+
+
+void dWorldSetERP (dWorldID w, dReal erp)
+{
+  dAASSERT (w);
+  w->global_erp = erp;
+}
+
+
+dReal dWorldGetERP (dWorldID w)
+{
+  dAASSERT (w);
+  return w->global_erp;
+}
+
+
+void dWorldSetCFM (dWorldID w, dReal cfm)
+{
+  dAASSERT (w);
+  w->global_cfm = cfm;
+}
+
+
+dReal dWorldGetCFM (dWorldID w)
+{
+  dAASSERT (w);
+  return w->global_cfm;
+}
+
+
+void dWorldStep (dWorldID w, dReal stepsize)
+{
+  dUASSERT (w,"bad world argument");
+  dUASSERT (stepsize > 0,"stepsize must be > 0");
+  processIslands (w,stepsize);
+}
+
+
+void dWorldImpulseToForce (dWorldID w, dReal stepsize,
+			   dReal ix, dReal iy, dReal iz,
+			   dVector3 force)
+{
+  dAASSERT (w);
+  stepsize = dRecip(stepsize);
+  force[0] = stepsize * ix;
+  force[1] = stepsize * iy;
+  force[2] = stepsize * iz;
+  // @@@ force[3] = 0;
+}
+
+//****************************************************************************
+// testing
+
+#define NUM 100
+
+#define DO(x)
+
+
+extern "C" void dTestDataStructures()
+{
+  int i;
+  DO(printf ("testDynamicsStuff()\n"));
+
+  dBodyID body [NUM];
+  int nb = 0;
+  dJointID joint [NUM];
+  int nj = 0;
+
+  for (i=0; i<NUM; i++) body[i] = 0;
+  for (i=0; i<NUM; i++) joint[i] = 0;
+
+  DO(printf ("creating world\n"));
+  dWorldID w = dWorldCreate();
+  checkWorld (w);
+
+  for (;;) {
+    if (nb < NUM && dRandReal() > 0.5) {
+      DO(printf ("creating body\n"));
+      body[nb] = dBodyCreate (w);
+      DO(printf ("\t--> %p\n",body[nb]));
+      nb++;
+      checkWorld (w);
+      DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+    }
+    if (nj < NUM && nb > 2 && dRandReal() > 0.5) {
+      dBodyID b1 = body [dRand() % nb];
+      dBodyID b2 = body [dRand() % nb];
+      if (b1 != b2) {
+	DO(printf ("creating joint, attaching to %p,%p\n",b1,b2));
+	joint[nj] = dJointCreateBall (w,0);
+	DO(printf ("\t-->%p\n",joint[nj]));
+	checkWorld (w);
+	dJointAttach (joint[nj],b1,b2);
+	nj++;
+	checkWorld (w);
+	DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+      }
+    }
+    if (nj > 0 && nb > 2 && dRandReal() > 0.5) {
+      dBodyID b1 = body [dRand() % nb];
+      dBodyID b2 = body [dRand() % nb];
+      if (b1 != b2) {
+	int k = dRand() % nj;
+	DO(printf ("reattaching joint %p\n",joint[k]));
+	dJointAttach (joint[k],b1,b2);
+	checkWorld (w);
+	DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+      }
+    }
+    if (nb > 0 && dRandReal() > 0.5) {
+      int k = dRand() % nb;
+      DO(printf ("destroying body %p\n",body[k]));
+      dBodyDestroy (body[k]);
+      checkWorld (w);
+      for (; k < (NUM-1); k++) body[k] = body[k+1];
+      nb--;
+      DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+    }
+    if (nj > 0 && dRandReal() > 0.5) {
+      int k = dRand() % nj;
+      DO(printf ("destroying joint %p\n",joint[k]));
+      dJointDestroy (joint[k]);
+      checkWorld (w);
+      for (; k < (NUM-1); k++) joint[k] = joint[k+1];
+      nj--;
+      DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+    }
+  }
+
+  /*
+  printf ("creating world\n");
+  dWorldID w = dWorldCreate();
+  checkWorld (w);
+  printf ("creating body\n");
+  dBodyID b1 = dBodyCreate (w);
+  checkWorld (w);
+  printf ("creating body\n");
+  dBodyID b2 = dBodyCreate (w);
+  checkWorld (w);
+  printf ("creating joint\n");
+  dJointID j = dJointCreateBall (w);
+  checkWorld (w);
+  printf ("attaching joint\n");
+  dJointAttach (j,b1,b2);
+  checkWorld (w);
+  printf ("destroying joint\n");
+  dJointDestroy (j);
+  checkWorld (w);
+  printf ("destroying body\n");
+  dBodyDestroy (b1);
+  checkWorld (w);
+  printf ("destroying body\n");
+  dBodyDestroy (b2);
+  checkWorld (w);
+  printf ("destroying world\n");
+  dWorldDestroy (w);
+  */
+}
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/step.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/step.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/step.cpp	(revision 216)
@@ -0,0 +1,1170 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include "objects.h"
+#include "joint.h"
+#include <ode/config.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/timer.h>
+#include <ode/error.h>
+#include <ode/matrix.h>
+#include "lcp.h"
+
+//****************************************************************************
+// misc defines
+
+#define FAST_FACTOR
+//#define TIMING
+
+#define ALLOCA dALLOCA16
+
+//****************************************************************************
+// debugging - comparison of various vectors and matrices produced by the
+// slow and fast versions of the stepper.
+
+//#define COMPARE_METHODS
+
+#ifdef COMPARE_METHODS
+#include "testing.h"
+dMatrixComparison comparator;
+#endif
+
+//****************************************************************************
+// special matrix multipliers
+
+// this assumes the 4th and 8th rows of B and C are zero.
+
+static void Multiply2_p8r (dReal *A, dReal *B, dReal *C,
+			   int p, int r, int Askip)
+{
+  int i,j;
+  dReal sum,*bb,*cc;
+  dIASSERT (p>0 && r>0 && A && B && C);
+  bb = B;
+  for (i=p; i; i--) {
+    cc = C;
+    for (j=r; j; j--) {
+      sum = bb[0]*cc[0];
+      sum += bb[1]*cc[1];
+      sum += bb[2]*cc[2];
+      sum += bb[4]*cc[4];
+      sum += bb[5]*cc[5];
+      sum += bb[6]*cc[6];
+      *(A++) = sum; 
+      cc += 8;
+    }
+    A += Askip - r;
+    bb += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B and C are zero.
+
+static void MultiplyAdd2_p8r (dReal *A, dReal *B, dReal *C,
+			      int p, int r, int Askip)
+{
+  int i,j;
+  dReal sum,*bb,*cc;
+  dIASSERT (p>0 && r>0 && A && B && C);
+  bb = B;
+  for (i=p; i; i--) {
+    cc = C;
+    for (j=r; j; j--) {
+      sum = bb[0]*cc[0];
+      sum += bb[1]*cc[1];
+      sum += bb[2]*cc[2];
+      sum += bb[4]*cc[4];
+      sum += bb[5]*cc[5];
+      sum += bb[6]*cc[6];
+      *(A++) += sum; 
+      cc += 8;
+    }
+    A += Askip - r;
+    bb += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void Multiply0_p81 (dReal *A, dReal *B, dReal *C, int p)
+{
+  int i;
+  dIASSERT (p>0 && A && B && C);
+  dReal sum;
+  for (i=p; i; i--) {
+    sum =  B[0]*C[0];
+    sum += B[1]*C[1];
+    sum += B[2]*C[2];
+    sum += B[4]*C[4];
+    sum += B[5]*C[5];
+    sum += B[6]*C[6];
+    *(A++) = sum;
+    B += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void MultiplyAdd0_p81 (dReal *A, dReal *B, dReal *C, int p)
+{
+  int i;
+  dIASSERT (p>0 && A && B && C);
+  dReal sum;
+  for (i=p; i; i--) {
+    sum =  B[0]*C[0];
+    sum += B[1]*C[1];
+    sum += B[2]*C[2];
+    sum += B[4]*C[4];
+    sum += B[5]*C[5];
+    sum += B[6]*C[6];
+    *(A++) += sum;
+    B += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void MultiplyAdd1_8q1 (dReal *A, dReal *B, dReal *C, int q)
+{
+  int k;
+  dReal sum;
+  dIASSERT (q>0 && A && B && C);
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[k*8] * C[k];
+  A[0] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[1+k*8] * C[k];
+  A[1] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[2+k*8] * C[k];
+  A[2] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[4+k*8] * C[k];
+  A[4] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[5+k*8] * C[k];
+  A[5] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[6+k*8] * C[k];
+  A[6] += sum;
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void Multiply1_8q1 (dReal *A, dReal *B, dReal *C, int q)
+{
+  int k;
+  dReal sum;
+  dIASSERT (q>0 && A && B && C);
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[k*8] * C[k];
+  A[0] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[1+k*8] * C[k];
+  A[1] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[2+k*8] * C[k];
+  A[2] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[4+k*8] * C[k];
+  A[4] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[5+k*8] * C[k];
+  A[5] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[6+k*8] * C[k];
+  A[6] = sum;
+}
+
+//****************************************************************************
+// body rotation
+
+// return sin(x)/x. this has a singularity at 0 so special handling is needed
+// for small arguments.
+
+static inline dReal sinc (dReal x)
+{
+  // if |x| < 1e-4 then use a taylor series expansion. this two term expansion
+  // is actually accurate to one LS bit within this range if double precision
+  // is being used - so don't worry!
+  if (dFabs(x) < 1.0e-4) return REAL(1.0) - x*x*REAL(0.166666666666666666667);
+  else return dSin(x)/x;
+}
+
+
+// given a body b, apply its linear and angular rotation over the time
+// interval h, thereby adjusting its position and orientation.
+
+static inline void moveAndRotateBody (dxBody *b, dReal h)
+{
+  int j;
+
+  // handle linear velocity
+  for (j=0; j<3; j++) b->pos[j] += h * b->lvel[j];
+
+  if (b->flags & dxBodyFlagFiniteRotation) {
+    dVector3 irv;	// infitesimal rotation vector
+    dQuaternion q;	// quaternion for finite rotation
+
+    if (b->flags & dxBodyFlagFiniteRotationAxis) {
+      // split the angular velocity vector into a component along the finite
+      // rotation axis, and a component orthogonal to it.
+      dVector3 frv,irv;		// finite rotation vector
+      dReal k = dDOT (b->finite_rot_axis,b->avel);
+      frv[0] = b->finite_rot_axis[0] * k;
+      frv[1] = b->finite_rot_axis[1] * k;
+      frv[2] = b->finite_rot_axis[2] * k;
+      irv[0] = b->avel[0] - frv[0];
+      irv[1] = b->avel[1] - frv[1];
+      irv[2] = b->avel[2] - frv[2];
+
+      // make a rotation quaternion q that corresponds to frv * h.
+      // compare this with the full-finite-rotation case below.
+      h *= REAL(0.5);
+      dReal theta = k * h;
+      q[0] = dCos(theta);
+      dReal s = sinc(theta) * h;
+      q[1] = frv[0] * s;
+      q[2] = frv[1] * s;
+      q[3] = frv[2] * s;
+    }
+    else {
+      // make a rotation quaternion q that corresponds to w * h
+      dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] +
+			  b->avel[2]*b->avel[2]);
+      h *= REAL(0.5);
+      dReal theta = wlen * h;
+      q[0] = dCos(theta);
+      dReal s = sinc(theta) * h;
+      q[1] = b->avel[0] * s;
+      q[2] = b->avel[1] * s;
+      q[3] = b->avel[2] * s;
+    }
+
+    // do the finite rotation
+    dQuaternion q2;
+    dQMultiply0 (q2,q,b->q);
+    for (j=0; j<4; j++) b->q[j] = q2[j];
+
+    // do the infitesimal rotation if required
+    if (b->flags & dxBodyFlagFiniteRotationAxis) {
+      dReal dq[4];
+      dWtoDQ (irv,b->q,dq);
+      for (j=0; j<4; j++) b->q[j] += h * dq[j];
+    }
+  }
+  else {
+    // the normal way - do an infitesimal rotation
+    dReal dq[4];
+    dWtoDQ (b->avel,b->q,dq);
+    for (j=0; j<4; j++) b->q[j] += h * dq[j];
+  }
+
+  // normalize the quaternion and convert it to a rotation matrix
+  dNormalize4 (b->q);
+  dQtoR (b->q,b->R);
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+//****************************************************************************
+// the slow, but sure way
+// note that this does not do any joint feedback!
+
+// given lists of bodies and joints that form an island, perform a first
+// order timestep.
+//
+// `body' is the body array, `nb' is the size of the array.
+// `_joint' is the body array, `nj' is the size of the array.
+
+void dInternalStepIsland_x1 (dxWorld *world, dxBody * const *body, int nb,
+			     dxJoint * const *_joint, int nj, dReal stepsize)
+{
+  int i,j,k;
+  int n6 = 6*nb;
+
+# ifdef TIMING
+  dTimerStart("preprocessing");
+# endif
+
+  // number all bodies in the body list - set their tag values
+  for (i=0; i<nb; i++) body[i]->tag = i;
+
+  // make a local copy of the joint array, because we might want to modify it.
+  // (the "dxJoint *const*" declaration says we're allowed to modify the joints
+  // but not the joint array, because the caller might need it unchanged).
+  dxJoint **joint = (dxJoint**) ALLOCA (nj * sizeof(dxJoint*));
+  memcpy (joint,_joint,nj * sizeof(dxJoint*));
+
+  // for all bodies, compute the inertia tensor and its inverse in the global
+  // frame, and compute the rotational force and add it to the torque
+  // accumulator.
+  // @@@ check computation of rotational force.
+  dReal *I = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal));
+  dReal *invI = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal));
+
+  //dSetZero (I,3*nb*4);
+  //dSetZero (invI,3*nb*4);
+  for (i=0; i<nb; i++) {
+    dReal tmp[12];
+    // compute inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->R);
+    dMULTIPLY0_333 (I+i*12,body[i]->R,tmp);
+    // compute inverse inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->R);
+    dMULTIPLY0_333 (invI+i*12,body[i]->R,tmp);
+    // compute rotational force
+    dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
+    dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
+  }
+
+  // add the gravity force to all bodies
+  for (i=0; i<nb; i++) {
+    if ((body[i]->flags & dxBodyNoGravity)==0) {
+      body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
+      body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
+      body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
+    }
+  }
+
+  // get m = total constraint dimension, nub = number of unbounded variables.
+  // create constraint offset array and number-of-rows array for all joints.
+  // the constraints are re-ordered as follows: the purely unbounded
+  // constraints, the mixed unbounded + LCP constraints, and last the purely
+  // LCP constraints.
+  //
+  // joints with m=0 are inactive and are removed from the joints array
+  // entirely, so that the code that follows does not consider them.
+  int m = 0;
+  dxJoint::Info1 *info = (dxJoint::Info1*) ALLOCA (nj*sizeof(dxJoint::Info1));
+  int *ofs = (int*) ALLOCA (nj*sizeof(int));
+  for (i=0, j=0; j<nj; j++) {	// i=dest, j=src
+    joint[j]->vtable->getInfo1 (joint[j],info+i);
+    dIASSERT (info[i].m >= 0 && info[i].m <= 6 &&
+	      info[i].nub >= 0 && info[i].nub <= info[i].m);
+    if (info[i].m > 0) {
+      joint[i] = joint[j];
+      i++;
+    }
+  }
+  nj = i;
+
+  // the purely unbounded constraints
+  for (i=0; i<nj; i++) if (info[i].nub == info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  int nub = m;
+  // the mixed unbounded + LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  // the purely LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub == 0) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+
+  // create (6*nb,6*nb) inverse mass matrix `invM', and fill it with mass
+  // parameters
+# ifdef TIMING
+  dTimerNow ("create mass matrix");
+# endif
+  int nskip = dPAD (n6);
+  dReal *invM = (dReal*) ALLOCA (n6*nskip*sizeof(dReal));
+  dSetZero (invM,n6*nskip);
+  for (i=0; i<nb; i++) {
+    dReal *MM = invM+(i*6)*nskip+(i*6);
+    MM[0] = body[i]->invMass;
+    MM[nskip+1] = body[i]->invMass;
+    MM[2*nskip+2] = body[i]->invMass;
+    MM += 3*nskip+3;
+    for (j=0; j<3; j++) for (k=0; k<3; k++) {
+      MM[j*nskip+k] = invI[i*12+j*4+k];
+    }
+  }
+
+  // assemble some body vectors: fe = external forces, v = velocities
+  dReal *fe = (dReal*) ALLOCA (n6 * sizeof(dReal));
+  dReal *v = (dReal*) ALLOCA (n6 * sizeof(dReal));
+  //dSetZero (fe,n6);
+  //dSetZero (v,n6);
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) fe[i*6+j] = body[i]->facc[j];
+    for (j=0; j<3; j++) fe[i*6+3+j] = body[i]->tacc[j];
+    for (j=0; j<3; j++) v[i*6+j] = body[i]->lvel[j];
+    for (j=0; j<3; j++) v[i*6+3+j] = body[i]->avel[j];
+  }
+
+  // this will be set to the velocity update
+  dReal *vnew = (dReal*) ALLOCA (n6 * sizeof(dReal));
+  dSetZero (vnew,n6);
+
+  // if there are constraints, compute cforce
+  if (m > 0) {
+    // create a constraint equation right hand side vector `c', a constraint
+    // force mixing vector `cfm', and LCP low and high bound vectors, and an
+    // 'findex' vector.
+    dReal *c = (dReal*) ALLOCA (m*sizeof(dReal));
+    dReal *cfm = (dReal*) ALLOCA (m*sizeof(dReal));
+    dReal *lo = (dReal*) ALLOCA (m*sizeof(dReal));
+    dReal *hi = (dReal*) ALLOCA (m*sizeof(dReal));
+    int *findex = (int*) alloca (m*sizeof(int));
+    dSetZero (c,m);
+    dSetValue (cfm,m,world->global_cfm);
+    dSetValue (lo,m,-dInfinity);
+    dSetValue (hi,m, dInfinity);
+    for (i=0; i<m; i++) findex[i] = -1;
+
+    // create (m,6*nb) jacobian mass matrix `J', and fill it with constraint
+    // data. also fill the c vector.
+#   ifdef TIMING
+    dTimerNow ("create J");
+#   endif
+    dReal *J = (dReal*) ALLOCA (m*nskip*sizeof(dReal));
+    dSetZero (J,m*nskip);
+    dxJoint::Info2 Jinfo;
+    Jinfo.rowskip = nskip;
+    Jinfo.fps = dRecip(stepsize);
+    Jinfo.erp = world->global_erp;
+    for (i=0; i<nj; i++) {
+      Jinfo.J1l = J + nskip*ofs[i] + 6*joint[i]->node[0].body->tag;
+      Jinfo.J1a = Jinfo.J1l + 3;
+      if (joint[i]->node[1].body) {
+	Jinfo.J2l = J + nskip*ofs[i] + 6*joint[i]->node[1].body->tag;
+	Jinfo.J2a = Jinfo.J2l + 3;
+      }
+      else {
+	Jinfo.J2l = 0;
+	Jinfo.J2a = 0;
+      }
+      Jinfo.c = c + ofs[i];
+      Jinfo.cfm = cfm + ofs[i];
+      Jinfo.lo = lo + ofs[i];
+      Jinfo.hi = hi + ofs[i];
+      Jinfo.findex = findex + ofs[i];
+      joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
+      // adjust returned findex values for global index numbering
+      for (j=0; j<info[i].m; j++) {
+	if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
+      }
+    }
+
+    // compute A = J*invM*J'
+#   ifdef TIMING
+    dTimerNow ("compute A");
+#   endif
+    dReal *JinvM = (dReal*) ALLOCA (m*nskip*sizeof(dReal));
+    //dSetZero (JinvM,m*nskip);
+    dMultiply0 (JinvM,J,invM,m,n6,n6);
+    int mskip = dPAD(m);
+    dReal *A = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
+    //dSetZero (A,m*mskip);
+    dMultiply2 (A,JinvM,J,m,n6,m);
+
+    // add cfm to the diagonal of A
+    for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * Jinfo.fps;
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (A,m,m,1,"A");
+#   endif
+
+    // compute `rhs', the right hand side of the equation J*a=c
+#   ifdef TIMING
+    dTimerNow ("compute rhs");
+#   endif
+    dReal *tmp1 = (dReal*) ALLOCA (n6 * sizeof(dReal));
+    //dSetZero (tmp1,n6);
+    dMultiply0 (tmp1,invM,fe,n6,n6,1);
+    for (i=0; i<n6; i++) tmp1[i] += v[i]/stepsize;
+    dReal *rhs = (dReal*) ALLOCA (m * sizeof(dReal));
+    //dSetZero (rhs,m);
+    dMultiply0 (rhs,J,tmp1,m,n6,1);
+    for (i=0; i<m; i++) rhs[i] = c[i]/stepsize - rhs[i];
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (c,m,1,0,"c");
+    comparator.nextMatrix (rhs,m,1,0,"rhs");
+#   endif
+
+    // solve the LCP problem and get lambda.
+    // this will destroy A but that's okay
+#   ifdef TIMING
+    dTimerNow ("solving LCP problem");
+#   endif
+    dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
+    dReal *residual = (dReal*) ALLOCA (m * sizeof(dReal));
+    dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex);
+
+//  OLD WAY - direct factor and solve
+//
+//    // factorize A (L*L'=A)
+//#   ifdef TIMING
+//    dTimerNow ("factorize A");
+//#   endif
+//    dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
+//    memcpy (L,A,m*mskip*sizeof(dReal));
+//    if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
+//
+//    // compute lambda
+//#   ifdef TIMING
+//    dTimerNow ("compute lambda");
+//#   endif
+//    dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
+//    memcpy (lambda,rhs,m * sizeof(dReal));
+//    dSolveCholesky (L,lambda,m);
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (lambda,m,1,0,"lambda");
+#   endif
+
+    // compute the velocity update `vnew'
+#   ifdef TIMING
+    dTimerNow ("compute velocity update");
+#   endif
+    dMultiply1 (tmp1,J,lambda,n6,m,1);
+    for (i=0; i<n6; i++) tmp1[i] += fe[i];
+    dMultiply0 (vnew,invM,tmp1,n6,n6,1);
+    for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i];
+
+    // see if the constraint has worked: compute J*vnew and make sure it equals
+    // `c' (to within a certain tolerance).
+#   ifdef TIMING
+    dTimerNow ("verify constraint equation");
+#   endif
+    dMultiply0 (tmp1,J,vnew,m,n6,1);
+    dReal err = 0;
+    for (i=0; i<m; i++) err += dFabs(tmp1[i]-c[i]);
+    printf ("%.6e\n",err);
+  }
+  else {
+    // no constraints
+    dMultiply0 (vnew,invM,fe,n6,n6,1);
+    for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i];
+  }
+
+# ifdef COMPARE_METHODS
+  comparator.nextMatrix (vnew,n6,1,0,"vnew");
+# endif
+
+  // apply the velocity update to the bodies
+# ifdef TIMING
+  dTimerNow ("update velocity");
+# endif
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) body[i]->lvel[j] = vnew[i*6+j];
+    for (j=0; j<3; j++) body[i]->avel[j] = vnew[i*6+3+j];
+  }
+
+  // update the position and orientation from the new linear/angular velocity
+  // (over the given timestep)
+# ifdef TIMING
+  dTimerNow ("update position");
+# endif
+  for (i=0; i<nb; i++) moveAndRotateBody (body[i],stepsize);
+
+# ifdef TIMING
+  dTimerNow ("tidy up");
+# endif
+
+  // zero all force accumulators
+  for (i=0; i<nb; i++) {
+    body[i]->facc[0] = 0;
+    body[i]->facc[1] = 0;
+    body[i]->facc[2] = 0;
+    body[i]->facc[3] = 0;
+    body[i]->tacc[0] = 0;
+    body[i]->tacc[1] = 0;
+    body[i]->tacc[2] = 0;
+    body[i]->tacc[3] = 0;
+  }
+
+# ifdef TIMING
+  dTimerEnd();
+  if (m > 0) dTimerReport (stdout,1);
+# endif
+}
+
+//****************************************************************************
+// an optimized version of dInternalStepIsland1()
+
+void dInternalStepIsland_x2 (dxWorld *world, dxBody * const *body, int nb,
+			     dxJoint * const *_joint, int nj, dReal stepsize)
+{
+  int i,j,k;
+# ifdef TIMING
+  dTimerStart("preprocessing");
+# endif
+
+  dReal stepsize1 = dRecip(stepsize);
+
+  // number all bodies in the body list - set their tag values
+  for (i=0; i<nb; i++) body[i]->tag = i;
+
+  // make a local copy of the joint array, because we might want to modify it.
+  // (the "dxJoint *const*" declaration says we're allowed to modify the joints
+  // but not the joint array, because the caller might need it unchanged).
+  dxJoint **joint = (dxJoint**) ALLOCA (nj * sizeof(dxJoint*));
+  memcpy (joint,_joint,nj * sizeof(dxJoint*));
+
+  // for all bodies, compute the inertia tensor and its inverse in the global
+  // frame, and compute the rotational force and add it to the torque
+  // accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
+  // @@@ check computation of rotational force.
+  dReal *I = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal));
+  dReal *invI = (dReal*) ALLOCA (3*nb*4 * sizeof(dReal));
+
+  //dSetZero (I,3*nb*4);
+  //dSetZero (invI,3*nb*4);
+  for (i=0; i<nb; i++) {
+    dReal tmp[12];
+    // compute inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->R);
+    dMULTIPLY0_333 (I+i*12,body[i]->R,tmp);
+    // compute inverse inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->R);
+    dMULTIPLY0_333 (invI+i*12,body[i]->R,tmp);
+    // compute rotational force
+    dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
+    dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
+  }
+
+  // add the gravity force to all bodies
+  for (i=0; i<nb; i++) {
+    if ((body[i]->flags & dxBodyNoGravity)==0) {
+      body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
+      body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
+      body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
+    }
+  }
+
+  // get m = total constraint dimension, nub = number of unbounded variables.
+  // create constraint offset array and number-of-rows array for all joints.
+  // the constraints are re-ordered as follows: the purely unbounded
+  // constraints, the mixed unbounded + LCP constraints, and last the purely
+  // LCP constraints. this assists the LCP solver to put all unbounded
+  // variables at the start for a quick factorization.
+  //
+  // joints with m=0 are inactive and are removed from the joints array
+  // entirely, so that the code that follows does not consider them.
+  // also number all active joints in the joint list (set their tag values).
+  // inactive joints receive a tag value of -1.
+
+  int m = 0;
+  dxJoint::Info1 *info = (dxJoint::Info1*) ALLOCA (nj*sizeof(dxJoint::Info1));
+  int *ofs = (int*) ALLOCA (nj*sizeof(int));
+  for (i=0, j=0; j<nj; j++) {	// i=dest, j=src
+    joint[j]->vtable->getInfo1 (joint[j],info+i);
+    dIASSERT (info[i].m >= 0 && info[i].m <= 6 &&
+	      info[i].nub >= 0 && info[i].nub <= info[i].m);
+    if (info[i].m > 0) {
+      joint[i] = joint[j];
+      joint[i]->tag = i;
+      i++;
+    }
+    else {
+      joint[j]->tag = -1;
+    }
+  }
+  nj = i;
+
+  // the purely unbounded constraints
+  for (i=0; i<nj; i++) if (info[i].nub == info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  int nub = m;
+  // the mixed unbounded + LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  // the purely LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub == 0) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+
+  // this will be set to the force due to the constraints
+  dReal *cforce = (dReal*) ALLOCA (nb*8 * sizeof(dReal));
+  dSetZero (cforce,nb*8);
+
+  // if there are constraints, compute cforce
+  if (m > 0) {
+    // create a constraint equation right hand side vector `c', a constraint
+    // force mixing vector `cfm', and LCP low and high bound vectors, and an
+    // 'findex' vector.
+    dReal *c = (dReal*) ALLOCA (m*sizeof(dReal));
+    dReal *cfm = (dReal*) ALLOCA (m*sizeof(dReal));
+    dReal *lo = (dReal*) ALLOCA (m*sizeof(dReal));
+    dReal *hi = (dReal*) ALLOCA (m*sizeof(dReal));
+    int *findex = (int*) alloca (m*sizeof(int));
+    dSetZero (c,m);
+    dSetValue (cfm,m,world->global_cfm);
+    dSetValue (lo,m,-dInfinity);
+    dSetValue (hi,m, dInfinity);
+    for (i=0; i<m; i++) findex[i] = -1;
+
+    // get jacobian data from constraints. a (2*m)x8 matrix will be created
+    // to store the two jacobian blocks from each constraint. it has this
+    // format:
+    //
+    //   l l l 0 a a a 0  \    .
+    //   l l l 0 a a a 0   }-- jacobian body 1 block for joint 0 (3 rows)
+    //   l l l 0 a a a 0  /
+    //   l l l 0 a a a 0  \    .
+    //   l l l 0 a a a 0   }-- jacobian body 2 block for joint 0 (3 rows)
+    //   l l l 0 a a a 0  /
+    //   l l l 0 a a a 0  }--- jacobian body 1 block for joint 1 (1 row)
+    //   l l l 0 a a a 0  }--- jacobian body 2 block for joint 1 (1 row)
+    //   etc...
+    //
+    //   (lll) = linear jacobian data
+    //   (aaa) = angular jacobian data
+    //
+#   ifdef TIMING
+    dTimerNow ("create J");
+#   endif
+    dReal *J = (dReal*) ALLOCA (2*m*8*sizeof(dReal));
+    dSetZero (J,2*m*8);
+    dxJoint::Info2 Jinfo;
+    Jinfo.rowskip = 8;
+    Jinfo.fps = stepsize1;
+    Jinfo.erp = world->global_erp;
+    for (i=0; i<nj; i++) {
+      Jinfo.J1l = J + 2*8*ofs[i];
+      Jinfo.J1a = Jinfo.J1l + 4;
+      Jinfo.J2l = Jinfo.J1l + 8*info[i].m;
+      Jinfo.J2a = Jinfo.J2l + 4;
+      Jinfo.c = c + ofs[i];
+      Jinfo.cfm = cfm + ofs[i];
+      Jinfo.lo = lo + ofs[i];
+      Jinfo.hi = hi + ofs[i];
+      Jinfo.findex = findex + ofs[i];
+      joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
+      // adjust returned findex values for global index numbering
+      for (j=0; j<info[i].m; j++) {
+	if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
+      }
+    }
+
+    // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
+    // format as J so we just go through the constraints in J multiplying by
+    // the appropriate scalars and matrices.
+#   ifdef TIMING
+    dTimerNow ("compute A");
+#   endif
+    dReal *JinvM = (dReal*) ALLOCA (2*m*8*sizeof(dReal));
+    dSetZero (JinvM,2*m*8);
+    for (i=0; i<nj; i++) {
+      int b = joint[i]->node[0].body->tag;
+      dReal body_invMass = body[b]->invMass;
+      dReal *body_invI = invI + b*12;
+      dReal *Jsrc = J + 2*8*ofs[i];
+      dReal *Jdst = JinvM + 2*8*ofs[i];
+      for (j=info[i].m-1; j>=0; j--) {
+	for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass;
+	dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI);
+	Jsrc += 8;
+	Jdst += 8;
+      }
+      if (joint[i]->node[1].body) {
+	b = joint[i]->node[1].body->tag;
+	body_invMass = body[b]->invMass;
+	body_invI = invI + b*12;
+	for (j=info[i].m-1; j>=0; j--) {
+	  for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass;
+	  dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI);
+	  Jsrc += 8;
+	  Jdst += 8;
+	}
+      }
+    }
+
+    // now compute A = JinvM * J'. A's rows and columns are grouped by joint,
+    // i.e. in the same way as the rows of J. block (i,j) of A is only nonzero
+    // if joints i and j have at least one body in common. this fact suggests
+    // the algorithm used to fill A:
+    //
+    //    for b = all bodies
+    //      n = number of joints attached to body b
+    //      for i = 1..n
+    //        for j = i+1..n
+    //          ii = actual joint number for i
+    //          jj = actual joint number for j
+    //          // (ii,jj) will be set to all pairs of joints around body b
+    //          compute blockwise: A(ii,jj) += JinvM(ii) * J(jj)'
+    //
+    // this algorithm catches all pairs of joints that have at least one body
+    // in common. it does not compute the diagonal blocks of A however -
+    // another similar algorithm does that.
+
+    int mskip = dPAD(m);
+    dReal *A = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
+    dSetZero (A,m*mskip);
+    for (i=0; i<nb; i++) {
+      for (dxJointNode *n1=body[i]->firstjoint; n1; n1=n1->next) {
+	for (dxJointNode *n2=n1->next; n2; n2=n2->next) {
+	  // get joint numbers and ensure ofs[j1] >= ofs[j2]
+	  int j1 = n1->joint->tag;
+	  int j2 = n2->joint->tag;
+	  if (ofs[j1] < ofs[j2]) {
+	    int tmp = j1;
+	    j1 = j2;
+	    j2 = tmp;
+	  }
+
+	  // if either joint was tagged as -1 then it is an inactive (m=0)
+	  // joint that should not be considered
+	  if (j1==-1 || j2==-1) continue;
+
+	  // determine if body i is the 1st or 2nd body of joints j1 and j2
+	  int jb1 = (joint[j1]->node[1].body == body[i]);
+	  int jb2 = (joint[j2]->node[1].body == body[i]);
+	  // jb1/jb2 must be 0 for joints with only one body
+	  dIASSERT(joint[j1]->node[1].body || jb1==0);
+	  dIASSERT(joint[j2]->node[1].body || jb2==0);
+
+	  // set block of A
+	  MultiplyAdd2_p8r (A + ofs[j1]*mskip + ofs[j2],
+			    JinvM + 2*8*ofs[j1] + jb1*8*info[j1].m,
+			    J     + 2*8*ofs[j2] + jb2*8*info[j2].m,
+			    info[j1].m,info[j2].m, mskip);
+	}
+      }
+    }
+    // compute diagonal blocks of A
+    for (i=0; i<nj; i++) {
+      Multiply2_p8r (A + ofs[i]*(mskip+1),
+		     JinvM + 2*8*ofs[i],
+		     J + 2*8*ofs[i],
+		     info[i].m,info[i].m, mskip);
+      if (joint[i]->node[1].body) {
+	MultiplyAdd2_p8r (A + ofs[i]*(mskip+1),
+			  JinvM + 2*8*ofs[i] + 8*info[i].m,
+			  J + 2*8*ofs[i] + 8*info[i].m,
+			  info[i].m,info[i].m, mskip);
+      }
+    }
+
+    // add cfm to the diagonal of A
+    for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * stepsize1;
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (A,m,m,1,"A");
+#   endif
+
+    // compute the right hand side `rhs'
+#   ifdef TIMING
+    dTimerNow ("compute rhs");
+#   endif
+    dReal *tmp1 = (dReal*) ALLOCA (nb*8 * sizeof(dReal));
+    //dSetZero (tmp1,nb*8);
+    // put v/h + invM*fe into tmp1
+    for (i=0; i<nb; i++) {
+      dReal body_invMass = body[i]->invMass;
+      dReal *body_invI = invI + i*12;
+      for (j=0; j<3; j++) tmp1[i*8+j] = body[i]->facc[j] * body_invMass +
+			    body[i]->lvel[j] * stepsize1;
+      dMULTIPLY0_331 (tmp1 + i*8 + 4,body_invI,body[i]->tacc);
+      for (j=0; j<3; j++) tmp1[i*8+4+j] += body[i]->avel[j] * stepsize1;
+    }
+    // put J*tmp1 into rhs
+    dReal *rhs = (dReal*) ALLOCA (m * sizeof(dReal));
+    //dSetZero (rhs,m);
+    for (i=0; i<nj; i++) {
+      dReal *JJ = J + 2*8*ofs[i];
+      Multiply0_p81 (rhs+ofs[i],JJ,
+		     tmp1 + 8*joint[i]->node[0].body->tag, info[i].m);
+      if (joint[i]->node[1].body) {
+	MultiplyAdd0_p81 (rhs+ofs[i],JJ + 8*info[i].m,
+			  tmp1 + 8*joint[i]->node[1].body->tag, info[i].m);
+      }
+    }
+    // complete rhs
+    for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i];
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (c,m,1,0,"c");
+    comparator.nextMatrix (rhs,m,1,0,"rhs");
+#   endif
+
+    // solve the LCP problem and get lambda.
+    // this will destroy A but that's okay
+#   ifdef TIMING
+    dTimerNow ("solving LCP problem");
+#   endif
+    dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
+    dReal *residual = (dReal*) ALLOCA (m * sizeof(dReal));
+    dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex);
+
+//  OLD WAY - direct factor and solve
+//
+//    // factorize A (L*L'=A)
+//#   ifdef TIMING
+//    dTimerNow ("factorize A");
+//#   endif
+//    dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
+//    memcpy (L,A,m*mskip*sizeof(dReal));
+//#   ifdef FAST_FACTOR
+//    dFastFactorCholesky (L,m);  // does not report non positive definiteness
+//#   else
+//    if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
+//#   endif
+//
+//    // compute lambda
+//#   ifdef TIMING
+//    dTimerNow ("compute lambda");
+//#   endif
+//    dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
+//    memcpy (lambda,rhs,m * sizeof(dReal));
+//    dSolveCholesky (L,lambda,m);
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (lambda,m,1,0,"lambda");
+#   endif
+
+    // compute the constraint force `cforce'
+#   ifdef TIMING
+    dTimerNow ("compute constraint force");
+#   endif
+    // compute cforce = J'*lambda
+    for (i=0; i<nj; i++) {
+      dReal *JJ = J + 2*8*ofs[i];
+      dxBody* b1 = joint[i]->node[0].body;
+      dxBody* b2 = joint[i]->node[1].body;
+      dJointFeedback *fb = joint[i]->feedback;
+
+/******************** breakable joint contribution ***********************/
+    // this saves us a few dereferences
+    dxJointBreakInfo *jBI = joint[i]->breakInfo;
+    // we need joint feedback if the joint is breakable or if the user
+    // requested feedback.
+	if (jBI||fb) {
+      // we need feedback on the amount of force that this joint is
+      // applying to the bodies. we use a slightly slower computation
+      // that splits out the force components and puts them in the
+      // feedback structure.
+      dJointFeedback temp_fb; // temporary storage for joint feedback
+	  dReal data1[8],data2[8];
+	  Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m);
+	  dReal *cf1 = cforce + 8*b1->tag;
+	  cf1[0] += (temp_fb.f1[0] = data1[0]);
+	  cf1[1] += (temp_fb.f1[1] = data1[1]);
+	  cf1[2] += (temp_fb.f1[2] = data1[2]);
+	  cf1[4] += (temp_fb.t1[0] = data1[4]);
+	  cf1[5] += (temp_fb.t1[1] = data1[5]);
+	  cf1[6] += (temp_fb.t1[2] = data1[6]);
+	  if (b2) {
+	    Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
+	    dReal *cf2 = cforce + 8*b2->tag;
+	    cf2[0] += (temp_fb.f2[0] = data2[0]);
+	    cf2[1] += (temp_fb.f2[1] = data2[1]);
+	    cf2[2] += (temp_fb.f2[2] = data2[2]);
+	    cf2[4] += (temp_fb.t2[0] = data2[4]);
+	    cf2[5] += (temp_fb.t2[1] = data2[5]);
+	    cf2[6] += (temp_fb.t2[2] = data2[6]);
+	  }
+	  // if the user requested so we must copy the feedback information to
+	  // the feedback struct that the user suplied.
+	  if (fb) {
+	    // copy temp_fb to fb
+	    fb->f1[0] = temp_fb.f1[0];
+	    fb->f1[1] = temp_fb.f1[1];
+	    fb->f1[2] = temp_fb.f1[2];
+	    fb->t1[0] = temp_fb.t1[0];
+	    fb->t1[1] = temp_fb.t1[1];
+	    fb->t1[2] = temp_fb.t1[2];
+	    if (b2) {
+	      fb->f2[0] = temp_fb.f2[0];
+	      fb->f2[1] = temp_fb.f2[1];
+	      fb->f2[2] = temp_fb.f2[2];
+	      fb->t2[0] = temp_fb.t2[0];
+	      fb->t2[1] = temp_fb.t2[1];
+	      fb->t2[2] = temp_fb.t2[2];
+	    }
+	  }
+	  // if the joint is breakable we need to check the breaking conditions
+      if (jBI) {
+        dReal relCF1[3];
+		dReal relCT1[3];
+		// multiply the force and torque vectors by the rotation matrix of body 1
+		dMULTIPLY1_331 (&relCF1[0],b1->R,&temp_fb.f1[0]);
+		dMULTIPLY1_331 (&relCT1[0],b1->R,&temp_fb.t1[0]);
+		if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) {
+		  // check if the force is to high
+          for (int i = 0; i < 3; i++) {
+            if (relCF1[i] > jBI->b1MaxF[i]) {
+		      jBI->flags |= dJOINT_BROKEN;
+		      goto doneCheckingBreaks;
+		    }
+          }
+		}
+		if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) {
+		  // check if the torque is to high
+          for (int i = 0; i < 3; i++) {
+            if (relCT1[i] > jBI->b1MaxT[i]) {
+		      jBI->flags |= dJOINT_BROKEN;
+		      goto doneCheckingBreaks;
+            }
+          }
+		}
+        if (b2) {
+          dReal relCF2[3];
+          dReal relCT2[3];
+          // multiply the force and torque vectors by the rotation matrix of body 2
+          dMULTIPLY1_331 (&relCF2[0],b2->R,&temp_fb.f2[0]);
+          dMULTIPLY1_331 (&relCT2[0],b2->R,&temp_fb.t2[0]);
+		  if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) {
+            // check if the force is to high
+            for (int i = 0; i < 3; i++) {
+              if (relCF2[i] > jBI->b2MaxF[i]) {
+                jBI->flags |= dJOINT_BROKEN;
+                goto doneCheckingBreaks;
+              }
+            }
+		  }
+		  if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) {
+		  // check if the torque is to high
+            for (int i = 0; i < 3; i++) {
+              if (relCT2[i] > jBI->b2MaxT[i]) {
+                jBI->flags |= dJOINT_BROKEN;
+                goto doneCheckingBreaks;
+              }
+            }
+		  }
+        }
+		doneCheckingBreaks:
+		;
+      }
+    }
+/*************************************************************************/
+      else {
+	// no feedback is required, let's compute cforce the faster way
+	MultiplyAdd1_8q1 (cforce + 8*b1->tag,JJ, lambda+ofs[i], info[i].m);
+	if (b2) {
+	  MultiplyAdd1_8q1 (cforce + 8*b2->tag,
+			    JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
+	}
+      }
+    }
+  }
+
+  // compute the velocity update
+# ifdef TIMING
+  dTimerNow ("compute velocity update");
+# endif
+
+  // add fe to cforce
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) cforce[i*8+j] += body[i]->facc[j];
+    for (j=0; j<3; j++) cforce[i*8+4+j] += body[i]->tacc[j];
+  }
+  // multiply cforce by stepsize
+  for (i=0; i < nb*8; i++) cforce[i] *= stepsize;
+  // add invM * cforce to the body velocity
+  for (i=0; i<nb; i++) {
+    dReal body_invMass = body[i]->invMass;
+    dReal *body_invI = invI + i*12;
+    for (j=0; j<3; j++) body[i]->lvel[j] += body_invMass * cforce[i*8+j];
+    dMULTIPLYADD0_331 (body[i]->avel,body_invI,cforce+i*8+4);
+  }
+
+  // update the position and orientation from the new linear/angular velocity
+  // (over the given timestep)
+# ifdef TIMING
+  dTimerNow ("update position");
+# endif
+  for (i=0; i<nb; i++) moveAndRotateBody (body[i],stepsize);
+
+# ifdef COMPARE_METHODS
+  dReal *tmp_vnew = (dReal*) ALLOCA (nb*6*sizeof(dReal));
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) tmp_vnew[i*6+j] = body[i]->lvel[j];
+    for (j=0; j<3; j++) tmp_vnew[i*6+3+j] = body[i]->avel[j];
+  }
+  comparator.nextMatrix (tmp_vnew,nb*6,1,0,"vnew");
+# endif
+
+# ifdef TIMING
+  dTimerNow ("tidy up");
+# endif
+
+  // zero all force accumulators
+  for (i=0; i<nb; i++) {
+    body[i]->facc[0] = 0;
+    body[i]->facc[1] = 0;
+    body[i]->facc[2] = 0;
+    body[i]->facc[3] = 0;
+    body[i]->tacc[0] = 0;
+    body[i]->tacc[1] = 0;
+    body[i]->tacc[2] = 0;
+    body[i]->tacc[3] = 0;
+  }
+
+# ifdef TIMING
+  dTimerEnd();
+  if (m > 0) dTimerReport (stdout,1);
+# endif
+}
+
+//****************************************************************************
+
+void dInternalStepIsland (dxWorld *world, dxBody * const *body, int nb,
+			  dxJoint * const *joint, int nj, dReal stepsize)
+{
+# ifndef COMPARE_METHODS
+  dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize);
+# endif
+
+# ifdef COMPARE_METHODS
+  int i;
+
+  // save body state
+  dxBody *state = (dxBody*) ALLOCA (nb*sizeof(dxBody));
+  for (i=0; i<nb; i++) memcpy (state+i,body[i],sizeof(dxBody));
+
+  // take slow step
+  comparator.reset();
+  dInternalStepIsland_x1 (world,body,nb,joint,nj,stepsize);
+  comparator.end();
+
+  // restore state
+  for (i=0; i<nb; i++) memcpy (body[i],state+i,sizeof(dxBody));
+
+  // take fast step
+  dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize);
+  comparator.end();
+
+  //comparator.dump();
+  //_exit (1);
+# endif
+}
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/stepfast.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/stepfast.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/stepfast.cpp	(revision 216)
@@ -0,0 +1,1212 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * Fast iterative solver, David Whittaker. Email: david@csworkbench.com  *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// This is the StepFast code by David Whittaker. This code is faster, but
+// sometimes less stable than, the original "big matrix" code.
+// Refer to the user's manual for more information.
+// Note that this source file duplicates a lot of stuff from step.cpp,
+// eventually we should move the common code to a third file.
+
+#include "objects.h"
+#include "joint.h"
+#include <ode/config.h>
+#include <ode/objects.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/timer.h>
+#include <ode/error.h>
+#include <ode/matrix.h>
+#include "lcp.h"
+#include "step.h"
+
+
+// misc defines
+
+#define ALLOCA dALLOCA16
+
+#define RANDOM_JOINT_ORDER
+//#define FAST_FACTOR	//use a factorization approximation to the LCP solver (fast, theoretically less accurate)
+#define SLOW_LCP      //use the old LCP solver
+//#define NO_ISLANDS    //does not perform island creation code (3~4% of simulation time), body disabling doesn't work
+//#define TIMING
+
+
+static int autoEnableDepth = 2;
+
+void dWorldSetAutoEnableDepthSF1 (dxWorld *world, int autodepth)
+{
+	if (autodepth > 0)
+		autoEnableDepth = autodepth;
+	else
+		autoEnableDepth = 0;
+}
+
+int dWorldGetAutoEnableDepthSF1 (dxWorld *world)
+{
+	return autoEnableDepth;
+}
+
+//little bit of math.... the _sym_ functions assume the return matrix will be symmetric
+static void
+Multiply2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip)
+{
+	int i, j;
+	dReal sum, *aa, *ad, *bb, *cc;
+	dIASSERT (p > 0 && A && B && C);
+	bb = B;
+	for (i = 0; i < p; i++)
+	{
+		//aa is going accross the matrix, ad down
+		aa = ad = A;
+		cc = C;
+		for (j = i; j < p; j++)
+		{
+			sum = bb[0] * cc[0];
+			sum += bb[1] * cc[1];
+			sum += bb[2] * cc[2];
+			sum += bb[4] * cc[4];
+			sum += bb[5] * cc[5];
+			sum += bb[6] * cc[6];
+			*(aa++) = *ad = sum;
+			ad += Askip;
+			cc += 8;
+		}
+		bb += 8;
+		A += Askip + 1;
+		C += 8;
+	}
+}
+
+static void
+MultiplyAdd2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip)
+{
+	int i, j;
+	dReal sum, *aa, *ad, *bb, *cc;
+	dIASSERT (p > 0 && A && B && C);
+	bb = B;
+	for (i = 0; i < p; i++)
+	{
+		//aa is going accross the matrix, ad down
+		aa = ad = A;
+		cc = C;
+		for (j = i; j < p; j++)
+		{
+			sum = bb[0] * cc[0];
+			sum += bb[1] * cc[1];
+			sum += bb[2] * cc[2];
+			sum += bb[4] * cc[4];
+			sum += bb[5] * cc[5];
+			sum += bb[6] * cc[6];
+			*(aa++) += sum;
+			*ad += sum;
+			ad += Askip;
+			cc += 8;
+		}
+		bb += 8;
+		A += Askip + 1;
+		C += 8;
+	}
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void
+Multiply0_p81 (dReal * A, dReal * B, dReal * C, int p)
+{
+	int i;
+	dIASSERT (p > 0 && A && B && C);
+	dReal sum;
+	for (i = p; i; i--)
+	{
+		sum = B[0] * C[0];
+		sum += B[1] * C[1];
+		sum += B[2] * C[2];
+		sum += B[4] * C[4];
+		sum += B[5] * C[5];
+		sum += B[6] * C[6];
+		*(A++) = sum;
+		B += 8;
+	}
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void
+MultiplyAdd0_p81 (dReal * A, dReal * B, dReal * C, int p)
+{
+	int i;
+	dIASSERT (p > 0 && A && B && C);
+	dReal sum;
+	for (i = p; i; i--)
+	{
+		sum = B[0] * C[0];
+		sum += B[1] * C[1];
+		sum += B[2] * C[2];
+		sum += B[4] * C[4];
+		sum += B[5] * C[5];
+		sum += B[6] * C[6];
+		*(A++) += sum;
+		B += 8;
+	}
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void
+Multiply1_8q1 (dReal * A, dReal * B, dReal * C, int q)
+{
+	int k;
+	dReal sum;
+	dIASSERT (q > 0 && A && B && C);
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[k * 8] * C[k];
+	A[0] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[1 + k * 8] * C[k];
+	A[1] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[2 + k * 8] * C[k];
+	A[2] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[4 + k * 8] * C[k];
+	A[4] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[5 + k * 8] * C[k];
+	A[5] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[6 + k * 8] * C[k];
+	A[6] = sum;
+}
+
+//****************************************************************************
+// body rotation
+
+// return sin(x)/x. this has a singularity at 0 so special handling is needed
+// for small arguments.
+
+static inline dReal
+sinc (dReal x)
+{
+	// if |x| < 1e-4 then use a taylor series expansion. this two term expansion
+	// is actually accurate to one LS bit within this range if double precision
+	// is being used - so don't worry!
+	if (dFabs (x) < 1.0e-4)
+		return REAL (1.0) - x * x * REAL (0.166666666666666666667);
+	else
+		return dSin (x) / x;
+}
+
+
+// given a body b, apply its linear and angular rotation over the time
+// interval h, thereby adjusting its position and orientation.
+
+static inline void
+moveAndRotateBody (dxBody * b, dReal h)
+{
+	int j;
+
+	// handle linear velocity
+	for (j = 0; j < 3; j++)
+		b->pos[j] += h * b->lvel[j];
+
+	if (b->flags & dxBodyFlagFiniteRotation)
+	{
+		dVector3 irv;			// infitesimal rotation vector
+		dQuaternion q;			// quaternion for finite rotation
+
+		if (b->flags & dxBodyFlagFiniteRotationAxis)
+		{
+			// split the angular velocity vector into a component along the finite
+			// rotation axis, and a component orthogonal to it.
+			dVector3 frv, irv;	// finite rotation vector
+			dReal k = dDOT (b->finite_rot_axis, b->avel);
+			frv[0] = b->finite_rot_axis[0] * k;
+			frv[1] = b->finite_rot_axis[1] * k;
+			frv[2] = b->finite_rot_axis[2] * k;
+			irv[0] = b->avel[0] - frv[0];
+			irv[1] = b->avel[1] - frv[1];
+			irv[2] = b->avel[2] - frv[2];
+
+			// make a rotation quaternion q that corresponds to frv * h.
+			// compare this with the full-finite-rotation case below.
+			h *= REAL (0.5);
+			dReal theta = k * h;
+			q[0] = dCos (theta);
+			dReal s = sinc (theta) * h;
+			q[1] = frv[0] * s;
+			q[2] = frv[1] * s;
+			q[3] = frv[2] * s;
+		}
+		else
+		{
+			// make a rotation quaternion q that corresponds to w * h
+			dReal wlen = dSqrt (b->avel[0] * b->avel[0] + b->avel[1] * b->avel[1] + b->avel[2] * b->avel[2]);
+			h *= REAL (0.5);
+			dReal theta = wlen * h;
+			q[0] = dCos (theta);
+			dReal s = sinc (theta) * h;
+			q[1] = b->avel[0] * s;
+			q[2] = b->avel[1] * s;
+			q[3] = b->avel[2] * s;
+		}
+
+		// do the finite rotation
+		dQuaternion q2;
+		dQMultiply0 (q2, q, b->q);
+		for (j = 0; j < 4; j++)
+			b->q[j] = q2[j];
+
+		// do the infitesimal rotation if required
+		if (b->flags & dxBodyFlagFiniteRotationAxis)
+		{
+			dReal dq[4];
+			dWtoDQ (irv, b->q, dq);
+			for (j = 0; j < 4; j++)
+				b->q[j] += h * dq[j];
+		}
+	}
+	else
+	{
+		// the normal way - do an infitesimal rotation
+		dReal dq[4];
+		dWtoDQ (b->avel, b->q, dq);
+		for (j = 0; j < 4; j++)
+			b->q[j] += h * dq[j];
+	}
+
+	// normalize the quaternion and convert it to a rotation matrix
+	dNormalize4 (b->q);
+	dQtoR (b->q, b->R);
+
+	// notify all attached geoms that this body has moved
+	for (dxGeom * geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+		dGeomMoved (geom);
+}
+
+//****************************************************************************
+//This is an implementation of the iterated/relaxation algorithm.
+//Here is a quick overview of the algorithm per Sergi Valverde's posts to the
+//mailing list:
+//
+//  for i=0..N-1 do
+//      for c = 0..C-1 do
+//          Solve constraint c-th
+//          Apply forces to constraint bodies
+//      next
+//  next
+//  Integrate bodies
+
+void
+dInternalStepFast (dxWorld * world, dxBody * body[2], dReal * GI[2], dReal * GinvI[2], dxJoint * joint, dxJoint::Info1 info, dxJoint::Info2 Jinfo, dReal stepsize)
+{
+	int i, j, k;
+# ifdef TIMING
+	dTimerNow ("constraint preprocessing");
+# endif
+
+	dReal stepsize1 = dRecip (stepsize);
+
+	int m = info.m;
+	// nothing to do if no constraints.
+	if (m <= 0)
+		return;
+
+	int nub = 0;
+	if (info.nub == info.m)
+		nub = m;
+
+	// compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
+	// format as J so we just go through the constraints in J multiplying by
+	// the appropriate scalars and matrices.
+#   ifdef TIMING
+	dTimerNow ("compute A");
+#   endif
+	dReal JinvM[2 * 6 * 8];
+	//dSetZero (JinvM, 2 * m * 8);
+
+	dReal *Jsrc = Jinfo.J1l;
+	dReal *Jdst = JinvM;
+	if (body[0])
+	{
+		for (j = m - 1; j >= 0; j--)
+		{
+			for (k = 0; k < 3; k++)
+				Jdst[k] = Jsrc[k] * body[0]->invMass;
+			dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[0]);
+			Jsrc += 8;
+			Jdst += 8;
+		}
+	}
+	if (body[1])
+	{
+		Jsrc = Jinfo.J2l;
+		Jdst = JinvM + 8 * m;
+		for (j = m - 1; j >= 0; j--)
+		{
+			for (k = 0; k < 3; k++)
+				Jdst[k] = Jsrc[k] * body[1]->invMass;
+			dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[1]);
+			Jsrc += 8;
+			Jdst += 8;
+		}
+	}
+
+
+	// now compute A = JinvM * J'.
+	int mskip = dPAD (m);
+	dReal A[6 * 8];
+	//dSetZero (A, 6 * 8);
+
+	if (body[0])
+		Multiply2_sym_p8p (A, JinvM, Jinfo.J1l, m, mskip);
+	if (body[1])
+		MultiplyAdd2_sym_p8p (A, JinvM + 8 * m, Jinfo.J2l, m, mskip);
+
+	// add cfm to the diagonal of A
+	for (i = 0; i < m; i++)
+		A[i * mskip + i] += Jinfo.cfm[i] * stepsize1;
+
+	// compute the right hand side `rhs'
+#   ifdef TIMING
+	dTimerNow ("compute rhs");
+#   endif
+	dReal tmp1[16];
+	//dSetZero (tmp1, 16);
+	// put v/h + invM*fe into tmp1
+	for (i = 0; i < 2; i++)
+	{
+		if (!body[i])
+			continue;
+		for (j = 0; j < 3; j++)
+			tmp1[i * 8 + j] = body[i]->facc[j] * body[i]->invMass + body[i]->lvel[j] * stepsize1;
+		dMULTIPLY0_331 (tmp1 + i * 8 + 4, GinvI[i], body[i]->tacc);
+		for (j = 0; j < 3; j++)
+			tmp1[i * 8 + 4 + j] += body[i]->avel[j] * stepsize1;
+	}
+	// put J*tmp1 into rhs
+	dReal rhs[6];
+	//dSetZero (rhs, 6);
+
+	if (body[0])
+		Multiply0_p81 (rhs, Jinfo.J1l, tmp1, m);
+	if (body[1])
+		MultiplyAdd0_p81 (rhs, Jinfo.J2l, tmp1 + 8, m);
+
+	// complete rhs
+	for (i = 0; i < m; i++)
+		rhs[i] = Jinfo.c[i] * stepsize1 - rhs[i];
+
+#ifdef SLOW_LCP
+	// solve the LCP problem and get lambda.
+	// this will destroy A but that's okay
+#	ifdef TIMING
+	dTimerNow ("solving LCP problem");
+#	endif
+	dReal *lambda = (dReal *) ALLOCA (m * sizeof (dReal));
+	dReal *residual = (dReal *) ALLOCA (m * sizeof (dReal));
+	dReal lo[6], hi[6];
+	memcpy (lo, Jinfo.lo, m * sizeof (dReal));
+	memcpy (hi, Jinfo.hi, m * sizeof (dReal));
+	dSolveLCP (m, A, lambda, rhs, residual, nub, lo, hi, Jinfo.findex);
+#endif
+
+	// LCP Solver replacement:
+	// This algorithm goes like this:
+	// Do a straightforward LDLT factorization of the matrix A, solving for
+	// A*x = rhs
+	// For each x[i] that is outside of the bounds of lo[i] and hi[i],
+	//    clamp x[i] into that range.
+	//    Substitute into A the now known x's
+	//    subtract the residual away from the rhs.
+	//    Remove row and column i from L, updating the factorization
+	//    place the known x's at the end of the array, keeping up with location in p
+	// Repeat until all constraints have been clamped or all are within bounds
+	//
+	// This is probably only faster in the single joint case where only one repeat is
+	// the norm.
+
+#ifdef FAST_FACTOR
+	// factorize A (L*D*L'=A)
+#	ifdef TIMING
+	dTimerNow ("factorize A");
+#	endif
+	dReal d[6];
+	dReal L[6 * 8];
+	memcpy (L, A, m * mskip * sizeof (dReal));
+	dFactorLDLT (L, d, m, mskip);
+
+	// compute lambda
+#	ifdef TIMING
+	dTimerNow ("compute lambda");
+#	endif
+
+	int left = m;				//constraints left to solve.
+	int remove[6];
+	dReal lambda[6];
+	dReal x[6];
+	int p[6];
+	for (i = 0; i < 6; i++)
+		p[i] = i;
+	while (true)
+	{
+		memcpy (x, rhs, left * sizeof (dReal));
+		dSolveLDLT (L, d, x, left, mskip);
+
+		int fixed = 0;
+		for (i = 0; i < left; i++)
+		{
+			j = p[i];
+			remove[i] = false;
+			// This isn't the exact same use of findex as dSolveLCP.... since x[findex]
+			// may change after I've already clamped x[i], but it should be close
+			if (Jinfo.findex[j] > -1)
+			{
+				dReal f = fabs (Jinfo.hi[j] * x[p[Jinfo.findex[j]]]);
+				if (x[i] > f)
+					x[i] = f;
+				else if (x[i] < -f)
+					x[i] = -f;
+				else
+					continue;
+			}
+			else
+			{
+				if (x[i] > Jinfo.hi[j])
+					x[i] = Jinfo.hi[j];
+				else if (x[i] < Jinfo.lo[j])
+					x[i] = Jinfo.lo[j];
+				else
+					continue;
+			}
+			remove[i] = true;
+			fixed++;
+		}
+		if (fixed == 0 || fixed == left)	//no change or all constraints solved
+			break;
+
+		for (i = 0; i < left; i++)	//sub in to right hand side.
+			if (remove[i])
+				for (j = 0; j < left; j++)
+					if (!remove[j])
+						rhs[j] -= A[j * mskip + i] * x[i];
+
+		for (int r = left - 1; r >= 0; r--)	//eliminate row/col for fixed variables
+		{
+			if (remove[r])
+			{
+				//dRemoveLDLT adapted for use without row pointers.
+				if (r == left - 1)
+				{
+					left--;
+					continue;	// deleting last row/col is easy
+				}
+				else if (r == 0)
+				{
+					dReal a[6];
+					for (i = 0; i < left; i++)
+						a[i] = -A[i * mskip];
+					a[0] += REAL (1.0);
+					dLDLTAddTL (L, d, a, left, mskip);
+				}
+				else
+				{
+					dReal t[6];
+					dReal a[6];
+					for (i = 0; i < r; i++)
+						t[i] = L[r * mskip + i] / d[i];
+					for (i = 0; i < left - r; i++)
+						a[i] = dDot (L + (r + i) * mskip, t, r) - A[(r + i) * mskip + r];
+					a[0] += REAL (1.0);
+					dLDLTAddTL (L + r * mskip + r, d + r, a, left - r, mskip);
+				}
+
+				dRemoveRowCol (L, left, mskip, r);
+				//end dRemoveLDLT
+
+				left--;
+				if (r < (left - 1))
+				{
+					dReal tx = x[r];
+					memmove (d + r, d + r + 1, (left - r) * sizeof (dReal));
+					memmove (rhs + r, rhs + r + 1, (left - r) * sizeof (dReal));
+					//x will get written over by rhs anyway, no need to move it around
+					//just store the fixed value we just discovered in it.
+					x[left] = tx;
+					for (i = 0; i < m; i++)
+						if (p[i] > r && p[i] <= left)
+							p[i]--;
+					p[r] = left;
+				}
+			}
+		}
+	}
+
+	for (i = 0; i < m; i++)
+		lambda[i] = x[p[i]];
+#	endif
+	// compute the constraint force `cforce'
+#	ifdef TIMING
+	dTimerNow ("compute constraint force");
+#endif
+
+	// compute cforce = J'*lambda
+	dJointFeedback *fb = joint->feedback;
+	dReal cforce[16];
+	//dSetZero (cforce, 16);
+
+/******************** breakable joint contribution ***********************/
+	// this saves us a few dereferences
+    dxJointBreakInfo *jBI = joint->breakInfo;
+    // we need joint feedback if the joint is breakable or if the user
+    // requested feedback.
+	if (jBI||fb) {
+		// we need feedback on the amount of force that this joint is
+		// applying to the bodies. we use a slightly slower computation
+		// that splits out the force components and puts them in the
+		// feedback structure.
+		dJointFeedback temp_fb; // temporary storage for joint feedback
+		dReal data1[8],data2[8];
+		if (body[0])
+		{
+			Multiply1_8q1 (data1, Jinfo.J1l, lambda, m);
+			dReal *cf1 = cforce;
+			cf1[0] = (temp_fb.f1[0] = data1[0]);
+			cf1[1] = (temp_fb.f1[1] = data1[1]);
+			cf1[2] = (temp_fb.f1[2] = data1[2]);
+			cf1[4] = (temp_fb.t1[0] = data1[4]);
+			cf1[5] = (temp_fb.t1[1] = data1[5]);
+			cf1[6] = (temp_fb.t1[2] = data1[6]);
+		}
+		if (body[1])
+		{
+			Multiply1_8q1 (data2, Jinfo.J2l, lambda, m);
+			dReal *cf2 = cforce + 8;
+			cf2[0] = (temp_fb.f2[0] = data2[0]);
+			cf2[1] = (temp_fb.f2[1] = data2[1]);
+			cf2[2] = (temp_fb.f2[2] = data2[2]);
+			cf2[4] = (temp_fb.t2[0] = data2[4]);
+			cf2[5] = (temp_fb.t2[1] = data2[5]);
+			cf2[6] = (temp_fb.t2[2] = data2[6]);
+		}
+		// if the user requested so we must copy the feedback information to
+		// the feedback struct that the user suplied.
+		if (fb) {
+			// copy temp_fb to fb
+			fb->f1[0] = temp_fb.f1[0];
+			fb->f1[1] = temp_fb.f1[1];
+			fb->f1[2] = temp_fb.f1[2];
+			fb->t1[0] = temp_fb.t1[0];
+			fb->t1[1] = temp_fb.t1[1];
+			fb->t1[2] = temp_fb.t1[2];
+			if (body[1]) {
+				fb->f2[0] = temp_fb.f2[0];
+				fb->f2[1] = temp_fb.f2[1];
+				fb->f2[2] = temp_fb.f2[2];
+				fb->t2[0] = temp_fb.t2[0];
+				fb->t2[1] = temp_fb.t2[1];
+				fb->t2[2] = temp_fb.t2[2];
+			}
+		}
+		// if the joint is breakable we need to check the breaking conditions
+		if (jBI) {
+			dReal relCF1[3];
+			dReal relCT1[3];
+			// multiply the force and torque vectors by the rotation matrix of body 1
+			dMULTIPLY1_331 (&relCF1[0],body[0]->R,&temp_fb.f1[0]);
+			dMULTIPLY1_331 (&relCT1[0],body[0]->R,&temp_fb.t1[0]);
+			if (jBI->flags & dJOINT_BREAK_AT_B1_FORCE) {
+				// check if the force is to high
+				for (int i = 0; i < 3; i++) {
+					if (relCF1[i] > jBI->b1MaxF[i]) {
+						jBI->flags |= dJOINT_BROKEN;
+						goto doneCheckingBreaks;
+					}
+				}
+			}
+			if (jBI->flags & dJOINT_BREAK_AT_B1_TORQUE) {
+				// check if the torque is to high
+				for (int i = 0; i < 3; i++) {
+					if (relCT1[i] > jBI->b1MaxT[i]) {
+						jBI->flags |= dJOINT_BROKEN;
+						goto doneCheckingBreaks;
+					}
+				}
+			}
+			if (body[1]) {
+				dReal relCF2[3];
+				dReal relCT2[3];
+				// multiply the force and torque vectors by the rotation matrix of body 2
+				dMULTIPLY1_331 (&relCF2[0],body[1]->R,&temp_fb.f2[0]);
+				dMULTIPLY1_331 (&relCT2[0],body[1]->R,&temp_fb.t2[0]);
+				if (jBI->flags & dJOINT_BREAK_AT_B2_FORCE) {
+					// check if the force is to high
+					for (int i = 0; i < 3; i++) {
+						if (relCF2[i] > jBI->b2MaxF[i]) {
+							jBI->flags |= dJOINT_BROKEN;
+							goto doneCheckingBreaks;
+						}
+					}
+				}
+				if (jBI->flags & dJOINT_BREAK_AT_B2_TORQUE) {
+					// check if the torque is to high
+					for (int i = 0; i < 3; i++) {
+						if (relCT2[i] > jBI->b2MaxT[i]) {
+							jBI->flags |= dJOINT_BROKEN;
+							goto doneCheckingBreaks;
+						}
+					}
+				}
+			}
+			doneCheckingBreaks:
+			;
+		}
+	}
+/*************************************************************************/
+	else
+	{
+		// no feedback is required, let's compute cforce the faster way
+		if (body[0])
+			Multiply1_8q1 (cforce, Jinfo.J1l, lambda, m);
+		if (body[1])
+			Multiply1_8q1 (cforce + 8, Jinfo.J2l, lambda, m);
+	}
+
+	for (i = 0; i < 2; i++)
+	{
+		if (!body[i])
+			continue;
+		for (j = 0; j < 3; j++)
+		{
+			body[i]->facc[j] += cforce[i * 8 + j];
+			body[i]->tacc[j] += cforce[i * 8 + 4 + j];
+		}
+	}
+}
+
+void
+dInternalStepIslandFast (dxWorld * world, dxBody * const *bodies, int nb, dxJoint * const *_joints, int nj, dReal stepsize, int maxiterations)
+{
+#   ifdef TIMING
+	dTimerNow ("preprocessing");
+#   endif
+	dxBody *bodyPair[2], *body;
+	dReal *GIPair[2], *GinvIPair[2];
+	dxJoint *joint;
+	int iter, b, j, i;
+	dReal ministep = stepsize / maxiterations;
+
+	// make a local copy of the joint array, because we might want to modify it.
+	// (the "dxJoint *const*" declaration says we're allowed to modify the joints
+	// but not the joint array, because the caller might need it unchanged).
+	dxJoint **joints = (dxJoint **) ALLOCA (nj * sizeof (dxJoint *));
+	memcpy (joints, _joints, nj * sizeof (dxJoint *));
+
+	// get m = total constraint dimension, nub = number of unbounded variables.
+	// create constraint offset array and number-of-rows array for all joints.
+	// the constraints are re-ordered as follows: the purely unbounded
+	// constraints, the mixed unbounded + LCP constraints, and last the purely
+	// LCP constraints. this assists the LCP solver to put all unbounded
+	// variables at the start for a quick factorization.
+	//
+	// joints with m=0 are inactive and are removed from the joints array
+	// entirely, so that the code that follows does not consider them.
+	// also number all active joints in the joint list (set their tag values).
+	// inactive joints receive a tag value of -1.
+
+	int m = 0;
+	dxJoint::Info1 * info = (dxJoint::Info1 *) ALLOCA (nj * sizeof (dxJoint::Info1));
+	int *ofs = (int *) ALLOCA (nj * sizeof (int));
+	for (i = 0, j = 0; j < nj; j++)
+	{	// i=dest, j=src
+		joints[j]->vtable->getInfo1 (joints[j], info + i);
+		dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m);
+		if (info[i].m > 0)
+		{
+			joints[i] = joints[j];
+			joints[i]->tag = i;
+			i++;
+		}
+		else
+		{
+			joints[j]->tag = -1;
+		}
+	}
+	nj = i;
+
+	// the purely unbounded constraints
+	for (i = 0; i < nj; i++)
+	{
+		ofs[i] = m;
+		m += info[i].m;
+	}
+	dReal *c = NULL;
+	dReal *cfm = NULL;
+	dReal *lo = NULL;
+	dReal *hi = NULL;
+	int *findex = NULL;
+
+	dReal *J = NULL;
+	dxJoint::Info2 * Jinfo = NULL;
+
+	if (m)
+	{
+	// create a constraint equation right hand side vector `c', a constraint
+	// force mixing vector `cfm', and LCP low and high bound vectors, and an
+	// 'findex' vector.
+		c = (dReal *) ALLOCA (m * sizeof (dReal));
+		cfm = (dReal *) ALLOCA (m * sizeof (dReal));
+		lo = (dReal *) ALLOCA (m * sizeof (dReal));
+		hi = (dReal *) ALLOCA (m * sizeof (dReal));
+		findex = (int *) ALLOCA (m * sizeof (int));
+	dSetZero (c, m);
+	dSetValue (cfm, m, world->global_cfm);
+	dSetValue (lo, m, -dInfinity);
+	dSetValue (hi, m, dInfinity);
+	for (i = 0; i < m; i++)
+		findex[i] = -1;
+
+	// get jacobian data from constraints. a (2*m)x8 matrix will be created
+	// to store the two jacobian blocks from each constraint. it has this
+	// format:
+	//
+	//   l l l 0 a a a 0  \    .
+	//   l l l 0 a a a 0   }-- jacobian body 1 block for joint 0 (3 rows)
+	//   l l l 0 a a a 0  /
+	//   l l l 0 a a a 0  \    .
+	//   l l l 0 a a a 0   }-- jacobian body 2 block for joint 0 (3 rows)
+	//   l l l 0 a a a 0  /
+	//   l l l 0 a a a 0  }--- jacobian body 1 block for joint 1 (1 row)
+	//   l l l 0 a a a 0  }--- jacobian body 2 block for joint 1 (1 row)
+	//   etc...
+	//
+	//   (lll) = linear jacobian data
+	//   (aaa) = angular jacobian data
+	//
+#   ifdef TIMING
+	dTimerNow ("create J");
+#   endif
+		J = (dReal *) ALLOCA (2 * m * 8 * sizeof (dReal));
+		dSetZero (J, 2 * m * 8);
+		Jinfo = (dxJoint::Info2 *) ALLOCA (nj * sizeof (dxJoint::Info2));
+	for (i = 0; i < nj; i++)
+	{
+		Jinfo[i].rowskip = 8;
+		Jinfo[i].fps = dRecip (stepsize);
+		Jinfo[i].erp = world->global_erp;
+		Jinfo[i].J1l = J + 2 * 8 * ofs[i];
+		Jinfo[i].J1a = Jinfo[i].J1l + 4;
+		Jinfo[i].J2l = Jinfo[i].J1l + 8 * info[i].m;
+		Jinfo[i].J2a = Jinfo[i].J2l + 4;
+		Jinfo[i].c = c + ofs[i];
+		Jinfo[i].cfm = cfm + ofs[i];
+		Jinfo[i].lo = lo + ofs[i];
+		Jinfo[i].hi = hi + ofs[i];
+		Jinfo[i].findex = findex + ofs[i];
+		//joints[i]->vtable->getInfo2 (joints[i], Jinfo+i);
+	}
+
+	}
+
+	dReal *saveFacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal));
+	dReal *saveTacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal));
+	dReal *globalI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal));
+	dReal *globalInvI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal));
+	for (b = 0; b < nb; b++)
+	{
+		for (i = 0; i < 4; i++)
+		{
+			saveFacc[b * 4 + i] = bodies[b]->facc[i];
+			saveTacc[b * 4 + i] = bodies[b]->tacc[i];
+			bodies[b]->tag = b;
+		}
+	}
+
+	for (iter = 0; iter < maxiterations; iter++)
+	{
+#	ifdef TIMING
+		dTimerNow ("applying inertia and gravity");
+#	endif
+		dReal tmp[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+		for (b = 0; b < nb; b++)
+		{
+			body = bodies[b];
+
+			// for all bodies, compute the inertia tensor and its inverse in the global
+			// frame, and compute the rotational force and add it to the torque
+			// accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
+			// @@@ check computation of rotational force.
+
+			// compute inertia tensor in global frame
+			dMULTIPLY2_333 (tmp, body->mass.I, body->R);
+			dMULTIPLY0_333 (globalI + b * 12, body->R, tmp);
+			// compute inverse inertia tensor in global frame
+			dMULTIPLY2_333 (tmp, body->invI, body->R);
+			dMULTIPLY0_333 (globalInvI + b * 12, body->R, tmp);
+
+			for (i = 0; i < 4; i++)
+				body->tacc[i] = saveTacc[b * 4 + i];
+			// compute rotational force
+			dMULTIPLY0_331 (tmp, globalI + b * 12, body->avel);
+			dCROSS (body->tacc, -=, body->avel, tmp);
+
+			// add the gravity force to all bodies
+			if ((body->flags & dxBodyNoGravity) == 0)
+			{
+				body->facc[0] = saveFacc[b * 4 + 0] + body->mass.mass * world->gravity[0];
+				body->facc[1] = saveFacc[b * 4 + 1] + body->mass.mass * world->gravity[1];
+				body->facc[2] = saveFacc[b * 4 + 2] + body->mass.mass * world->gravity[2];
+				body->facc[3] = 0;
+			}
+
+		}
+
+#ifdef RANDOM_JOINT_ORDER
+#ifdef TIMING
+		dTimerNow ("randomizing joint order");
+#endif
+		//randomize the order of the joints by looping through the array
+		//and swapping the current joint pointer with a random one before it.
+		for (j = 0; j < nj; j++)
+		{
+			joint = joints[j];
+			dxJoint::Info1 i1 = info[j];
+			dxJoint::Info2 i2 = Jinfo[j];
+			int r = rand () % (j + 1);
+			joints[j] = joints[r];
+			info[j] = info[r];
+			Jinfo[j] = Jinfo[r];
+			joints[r] = joint;
+			info[r] = i1;
+			Jinfo[r] = i2;
+		}
+#endif
+
+		//now iterate through the random ordered joint array we created.
+		for (j = 0; j < nj; j++)
+		{
+#ifdef TIMING
+			dTimerNow ("setting up joint");
+#endif
+			joint = joints[j];
+			bodyPair[0] = joint->node[0].body;
+			bodyPair[1] = joint->node[1].body;
+
+			if (bodyPair[0] && (bodyPair[0]->flags & dxBodyDisabled))
+				bodyPair[0] = 0;
+			if (bodyPair[1] && (bodyPair[1]->flags & dxBodyDisabled))
+				bodyPair[1] = 0;
+			
+			//if this joint is not connected to any enabled bodies, skip it.
+			if (!bodyPair[0] && !bodyPair[1])
+				continue;
+			
+			if (bodyPair[0])
+			{
+				GIPair[0] = globalI + bodyPair[0]->tag * 12;
+				GinvIPair[0] = globalInvI + bodyPair[0]->tag * 12;
+			}
+			if (bodyPair[1])
+			{
+				GIPair[1] = globalI + bodyPair[1]->tag * 12;
+				GinvIPair[1] = globalInvI + bodyPair[1]->tag * 12;
+			}
+
+			joints[j]->vtable->getInfo2 (joints[j], Jinfo + j);
+
+			//dInternalStepIslandFast is an exact copy of the old routine with one
+			//modification: the calculated forces are added back to the facc and tacc
+			//vectors instead of applying them to the bodies and moving them.
+			if (info[j].m > 0)
+			{
+			dInternalStepFast (world, bodyPair, GIPair, GinvIPair, joint, info[j], Jinfo[j], ministep);
+			}		
+		}
+		//  }
+#	ifdef TIMING
+		dTimerNow ("moving bodies");
+#	endif
+		//Now we can simulate all the free floating bodies, and move them.
+		for (b = 0; b < nb; b++)
+		{
+			body = bodies[b];
+
+			for (i = 0; i < 4; i++)
+			{
+				body->facc[i] *= ministep;
+				body->tacc[i] *= ministep;
+			}
+
+			//apply torque
+			dMULTIPLYADD0_331 (body->avel, globalInvI + b * 12, body->tacc);
+
+			//apply force
+			for (i = 0; i < 3; i++)
+				body->lvel[i] += body->invMass * body->facc[i];
+
+			//move It!
+			moveAndRotateBody (body, ministep);
+		}
+	}
+	for (b = 0; b < nb; b++)
+		for (j = 0; j < 4; j++)
+			bodies[b]->facc[j] = bodies[b]->tacc[j] = 0;
+}
+
+
+#ifdef NO_ISLANDS
+
+// Since the iterative algorithm doesn't care about islands of bodies, this is a
+// faster algorithm that just sends it all the joints and bodies in one array.
+// It's downfall is it's inability to handle disabled bodies as well as the old one.
+static void
+processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations)
+{
+	// nothing to do if no bodies
+	if (world->nb <= 0)
+		return;
+
+#	ifdef TIMING
+	dTimerStart ("creating joint and body arrays");
+#	endif
+	dxBody **bodies, *body;
+	dxJoint **joints, *joint;
+	joints = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *));
+	bodies = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *));
+
+	int nj = 0;
+	for (joint = world->firstjoint; joint; joint = (dxJoint *) joint->next)
+		joints[nj++] = joint;
+
+	int nb = 0;
+	for (body = world->firstbody; body; body = (dxBody *) body->next)
+		bodies[nb++] = body;
+
+	dInternalStepIslandFast (world, bodies, nb, joints, nj, stepsize, maxiterations);
+#	ifdef TIMING
+	dTimerEnd ();
+	dTimerReport (stdout, 1);
+#	endif
+}
+
+#else
+
+//****************************************************************************
+// island processing
+
+// this groups all joints and bodies in a world into islands. all objects
+// in an island are reachable by going through connected bodies and joints.
+// each island can be simulated separately.
+// note that joints that are not attached to anything will not be included
+// in any island, an so they do not affect the simulation.
+//
+// this function starts new island from unvisited bodies. however, it will
+// never start a new islands from a disabled body. thus islands of disabled
+// bodies will not be included in the simulation. disabled bodies are
+// re-enabled if they are found to be part of an active island.
+
+static void
+processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations)
+{
+#ifdef TIMING
+	dTimerStart ("Island Setup");
+#endif
+	dxBody *b, *bb, **body;
+	dxJoint *j, **joint;
+
+	// nothing to do if no bodies
+	if (world->nb <= 0)
+		return;
+
+	// make arrays for body and joint lists (for a single island) to go into
+	body = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *));
+	joint = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *));
+	int bcount = 0;				// number of bodies in `body'
+	int jcount = 0;				// number of joints in `joint'
+	int tbcount = 0;
+	int tjcount = 0;
+	
+	// set all body/joint tags to 0
+	for (b = world->firstbody; b; b = (dxBody *) b->next)
+		b->tag = 0;
+	for (j = world->firstjoint; j; j = (dxJoint *) j->next)
+		j->tag = 0;
+
+	// allocate a stack of unvisited bodies in the island. the maximum size of
+	// the stack can be the lesser of the number of bodies or joints, because
+	// new bodies are only ever added to the stack by going through untagged
+	// joints. all the bodies in the stack must be tagged!
+	int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
+	dxBody **stack = (dxBody **) ALLOCA (stackalloc * sizeof (dxBody *));
+	int *autostack = (int *) ALLOCA (stackalloc * sizeof (int));
+
+	for (bb = world->firstbody; bb; bb = (dxBody *) bb->next)
+	{
+#ifdef TIMING
+		dTimerNow ("Island Processing");
+#endif
+		// get bb = the next enabled, untagged body, and tag it
+		if (bb->tag || (bb->flags & dxBodyDisabled))
+			continue;
+		bb->tag = 1;
+
+		// tag all bodies and joints starting from bb.
+		int stacksize = 0;
+		int autoDepth = autoEnableDepth;
+		b = bb;
+		body[0] = bb;
+		bcount = 1;
+		jcount = 0;
+		goto quickstart;
+		while (stacksize > 0)
+		{
+			b = stack[--stacksize];	// pop body off stack
+			autoDepth = autostack[stacksize];
+			body[bcount++] = b;	// put body on body list
+		  quickstart:
+
+			// traverse and tag all body's joints, add untagged connected bodies
+			// to stack
+			for (dxJointNode * n = b->firstjoint; n; n = n->next)
+			{
+				if (!n->joint->tag)
+				{
+					int thisDepth = autoEnableDepth;
+					n->joint->tag = 1;
+					joint[jcount++] = n->joint;
+					if (n->body && !n->body->tag)
+					{
+						if (n->body->flags & dxBodyDisabled)
+							thisDepth = autoDepth - 1;
+						if (thisDepth < 0)
+							continue;
+						n->body->flags &= ~dxBodyDisabled;
+						n->body->tag = 1;
+						autostack[stacksize] = thisDepth;
+						stack[stacksize++] = n->body;
+					}
+				}
+			}
+			dIASSERT (stacksize <= world->nb);
+			dIASSERT (stacksize <= world->nj);
+		}
+
+		// now do something with body and joint lists
+		dInternalStepIslandFast (world, body, bcount, joint, jcount, stepsize, maxiterations);
+
+		// what we've just done may have altered the body/joint tag values.
+		// we must make sure that these tags are nonzero.
+		// also make sure all bodies are in the enabled state.
+		int i;
+		for (i = 0; i < bcount; i++)
+		{
+			body[i]->tag = 1;
+			body[i]->flags &= ~dxBodyDisabled;
+		}
+		for (i = 0; i < jcount; i++)
+			joint[i]->tag = 1;
+		
+		tbcount += bcount;
+		tjcount += jcount;
+	}
+	
+#ifdef TIMING
+	dMessage(0, "Total joints processed: %i, bodies: %i", tjcount, tbcount);
+#endif
+
+	// if debugging, check that all objects (except for disabled bodies,
+	// unconnected joints, and joints that are connected to disabled bodies)
+	// were tagged.
+# ifndef dNODEBUG
+	for (b = world->firstbody; b; b = (dxBody *) b->next)
+	{
+		if (b->flags & dxBodyDisabled)
+		{
+			if (b->tag)
+				dDebug (0, "disabled body tagged");
+		}
+		else
+		{
+			if (!b->tag)
+				dDebug (0, "enabled body not tagged");
+		}
+	}
+	for (j = world->firstjoint; j; j = (dxJoint *) j->next)
+	{
+		if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled) == 0) || (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled) == 0))
+		{
+			if (!j->tag)
+				dDebug (0, "attached enabled joint not tagged");
+		}
+		else
+		{
+			if (j->tag)
+				dDebug (0, "unattached or disabled joint tagged");
+		}
+	}
+# endif
+  /******************** breakable joint contribution ***********************/
+  dxJoint* nextJ;
+  if (!world->firstjoint)
+    nextJ = 0;
+  else
+    nextJ = (dxJoint*)world->firstjoint->next;
+  for (j=world->firstjoint; j; j=nextJ) {
+  	nextJ = (dxJoint*)j->next;
+	// check if joint is breakable and broken
+    if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) {
+		// detach (break) the joint
+        dJointAttach (j, 0, 0);
+		// call the callback function if it is set
+		if (j->breakInfo->callback) j->breakInfo->callback (j);
+		// finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set
+		if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j);
+      }
+  }
+  /*************************************************************************/
+
+#	ifdef TIMING
+	dTimerEnd ();
+	dTimerReport (stdout, 1);
+#	endif
+}
+
+#endif
+
+
+void dWorldStepFast1 (dWorldID w, dReal stepsize, int maxiterations)
+{
+	dUASSERT (w, "bad world argument");
+	dUASSERT (stepsize > 0, "stepsize must be > 0");
+	processIslandsFast (w, stepsize, maxiterations);
+}
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/test_breakable.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/test_breakable.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/test_breakable.cpp	(revision 216)
@@ -0,0 +1,416 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+buggy with suspension.
+this also shows you how to use geom groups.
+
+*/
+
+
+#include <stdlib.h>
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCappedCylinder dsDrawCappedCylinderD
+#endif
+
+
+// some constants
+
+#define LENGTH 0.7	// chassis length
+#define WIDTH 0.4	// chassis width
+#define HEIGHT 0.2	// chassis height
+#define RADIUS 0.22	// wheel radius
+#define STARTZ 0.4	// starting height of chassis
+#define CMASS 1		// chassis mass
+#define WMASS 0.2	// wheel mass
+
+// dynamics and collision objects (chassis, 4 wheels, environment, obstacles, chain)
+static dWorldID world;
+static dSpaceID space;
+
+// chain stuff
+static const float chain_radius = 0.1;
+static const float chain_mass = 0.1;
+static const int chain_num = 10;
+static dBodyID chain_body[chain_num];
+static dGeomID chain_geom[chain_num];
+static dJointID chain_joint[chain_num-1]; 
+
+// 1 chasses, 4 wheels
+static dBodyID body[5];
+// joint[0] is left front wheel, joint[1] is right front wheel
+static dJointID joint[4]; 
+static int joint_exists[4];
+static dJointGroupID contactgroup;
+static dGeomID ground;
+static dSpaceID car_space;
+static dGeomID box[1];
+static dGeomID sphere[4];
+static dGeomID ground_box;
+static const int obstacle_num = 25;
+static dGeomID obstacle[obstacle_num];
+
+// things that the user controls
+
+static dReal speed=0,steer=0;	// user commands
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i,n;
+
+//   // do not collide objects that are connected
+//   dBodyID b1 = dGeomGetBody (o1),
+//           b2 = dGeomGetBody (o2);
+//   if (b1 && b2 && dAreConnected(b1, b2)) return;
+  
+  const int N = 10;
+  dContact contact[N];
+  n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
+  if (n > 0) {
+    for (i=0; i<n; i++) {
+      contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
+	dContactSoftERP | dContactSoftCFM | dContactApprox1;
+      contact[i].surface.mu = dInfinity;
+      contact[i].surface.slip1 = 0.1;
+      contact[i].surface.slip2 = 0.1;
+      contact[i].surface.soft_erp = 0.5;
+      contact[i].surface.soft_cfm = 0.3;
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c,
+		    dGeomGetBody(contact[i].geom.g1),
+		    dGeomGetBody(contact[i].geom.g2));
+    }
+  }
+}
+
+// callback function for joints that break
+static void jointBreakCallback (dJointID j)
+{
+       if (j == joint[0]) joint_exists[0] = 0;
+  else if (j == joint[1]) joint_exists[1] = 0;
+  else if (j == joint[2]) joint_exists[2] = 0;
+  else if (j == joint[3]) joint_exists[3] = 0;
+  printf ("A joint just broke\n");
+}
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {0.8317f,-0.9817f,0.8000f};
+  static float hpr[3] = {121.0000f,-27.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("Press:\t'a' to increase speed.\n"
+	  "\t'z' to decrease speed.\n"
+	  "\t',' to steer left.\n"
+	  "\t'.' to steer right.\n"
+	  "\t' ' to reset speed and steering.\n");
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  switch (cmd) {
+  case 'a': case 'A':
+    speed += 0.3;
+    break;
+  case 'z': case 'Z':
+    speed -= 0.3;
+    break;
+  case ',':
+    steer -= 0.5;
+    break;
+  case '.':
+    steer += 0.5;
+    break;
+  case ' ':
+    speed = 0;
+    steer = 0;
+    break;
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i;
+  if (!pause) {
+    for (i=0; i<2; i++) {
+  	  if (joint_exists[i]) {
+        // motor
+        dJointSetHinge2Param (joint[i],dParamVel2,-speed);
+        dJointSetHinge2Param (joint[i],dParamFMax2,0.1);
+
+        // steering
+        dReal v = steer - dJointGetHinge2Angle1 (joint[i]);
+        if (v > 0.1) v = 0.1;
+        if (v < -0.1) v = -0.1;
+        v *= 10.0;
+        dJointSetHinge2Param (joint[i],dParamVel,v);
+        dJointSetHinge2Param (joint[i],dParamFMax,0.2);
+        dJointSetHinge2Param (joint[i],dParamLoStop,-0.75);
+        dJointSetHinge2Param (joint[i],dParamHiStop,0.75);
+        dJointSetHinge2Param (joint[i],dParamFudgeFactor,0.1);
+	  }
+	}
+	
+    dSpaceCollide (space,0,&nearCallback);
+    //dWorldStep (world,0.05);
+	dWorldStepFast1 (world,0.05,5);
+
+    // remove all contact joints
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (0,1,1);
+  dsSetTexture (DS_WOOD);
+  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
+  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
+  dsSetColor (1,1,1);
+  for (i=1; i<=4; i++) 
+    dsDrawCylinder (dBodyGetPosition(body[i]),
+                    dBodyGetRotation(body[i]),
+					0.2,
+                    RADIUS);
+
+  dVector3 ss;
+  dGeomBoxGetLengths (ground_box,ss);
+  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
+  
+  dsSetColor (1,0,0);
+  for (i=0; i<obstacle_num; i++) {
+    dVector3 ss;
+	dGeomBoxGetLengths (obstacle[i],ss);
+	dsDrawBox (dGeomGetPosition(obstacle[i]),dGeomGetRotation(obstacle[i]),ss);
+  }
+
+  dsSetColor (1,1,0);
+  for (i=0; i<chain_num; i++) {
+    dsDrawSphere (dGeomGetPosition(chain_geom[i]),dGeomGetRotation(chain_geom[i]),chain_radius);
+  }
+  
+  /*
+  printf ("%.10f %.10f %.10f %.10f\n",
+	  dJointGetHingeAngle (joint[1]),
+	  dJointGetHingeAngle (joint[2]),
+	  dJointGetHingeAngleRate (joint[1]),
+	  dJointGetHingeAngleRate (joint[2]));
+  */
+}
+
+int main (int argc, char **argv)
+{
+  int i;
+  dMass m;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+  // create world
+
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  ground = dCreatePlane (space,0,0,1,0);
+
+  // chassis body
+  body[0] = dBodyCreate (world);
+  dBodySetPosition (body[0],0,0,STARTZ);
+  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
+  dMassAdjust (&m,CMASS);
+  dBodySetMass (body[0],&m);
+  box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT);
+  dGeomSetBody (box[0],body[0]);
+  
+  // a chain
+  for (i=0; i<chain_num; i++) {
+    chain_body[i] = dBodyCreate (world);
+	dBodySetPosition (chain_body[i],-LENGTH-(i*2*chain_radius),0,STARTZ-HEIGHT*0.5);
+    dMassSetSphere (&m,1,chain_radius);
+    dMassAdjust (&m,chain_mass);
+    dBodySetMass (chain_body[i],&m);
+    chain_geom[i] = dCreateSphere (space,chain_radius);
+    dGeomSetBody (chain_geom[i],chain_body[i]);
+  }
+  
+  // wheel bodies
+  for (i=1; i<=4; i++) {
+    body[i] = dBodyCreate (world);
+    dQuaternion q;
+    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
+    dBodySetQuaternion (body[i],q);
+    dMassSetSphere (&m,1,RADIUS);
+    dMassAdjust (&m,WMASS);
+    dBodySetMass (body[i],&m);
+    sphere[i-1] = dCreateSphere (0,RADIUS);
+    dGeomSetBody (sphere[i-1],body[i]);
+  }
+  dBodySetPosition (body[1],  0.5*LENGTH,  WIDTH*1.0, STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[2],  0.5*LENGTH, -WIDTH*1.0, STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[3], -0.5*LENGTH,  WIDTH*1.0, STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[4], -0.5*LENGTH, -WIDTH*1.0, STARTZ-HEIGHT*0.5);
+
+  // front wheel hinge
+  /*
+  joint[0] = dJointCreateHinge2 (world,0);
+  dJointAttach (joint[0],body[0],body[1]);
+  const dReal *a = dBodyGetPosition (body[1]);
+  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
+  dJointSetHinge2Axis1 (joint[0],0,0,1);
+  dJointSetHinge2Axis2 (joint[0],0,1,0);
+  */
+
+  // front and back wheel hinges
+  for (i=0; i<4; i++) {
+    joint[i] = dJointCreateHinge2 (world,0);
+	joint_exists[i] = 1;
+    dJointAttach (joint[i],body[0],body[i+1]);
+    const dReal *a = dBodyGetPosition (body[i+1]);
+    dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
+    dJointSetHinge2Axis1 (joint[i],0,0,1);
+    dJointSetHinge2Axis2 (joint[i],0,1,0);
+
+    // the wheels can break
+    dJointSetBreakable (joint[i], 1);
+    // the wheels wil break at a specific force
+    dJointSetBreakMode (joint[i], 
+                        dJOINT_BREAK_AT_B1_FORCE |
+                        dJOINT_BREAK_AT_B2_FORCE |
+                        dJOINT_DELETE_ON_BREAK);
+    // specify the force for the first body connected to the joint ...
+    dJointSetBreakForce (joint[i], 0, 2.5, 2.5, 2.5);
+    // and for the second body
+    dJointSetBreakForce (joint[i], 1, 2.5, 2.5, 2.5);
+	// set the callback function
+	dJointSetBreakCallback (joint[i], &jointBreakCallback);
+  }
+  
+  // joints for the chain
+  for (i=0; i<chain_num-1; i++) {
+    chain_joint[i] = dJointCreateFixed (world,0);
+    dJointAttach (chain_joint[i],chain_body[i+1],chain_body[i]);
+	dJointSetFixed (chain_joint[i]);
+	// the chain can break
+    dJointSetBreakable (chain_joint[i], 1);
+    // the chain wil break at a specific force
+    dJointSetBreakMode (chain_joint[i], 
+      dJOINT_BREAK_AT_B1_FORCE |
+      dJOINT_BREAK_AT_B2_FORCE |
+      dJOINT_DELETE_ON_BREAK);
+    // specify the force for the first body connected to the joint ...
+    dJointSetBreakForce (chain_joint[i], 0, 0.5, 0.5, 0.5);
+    // and for the second body
+    dJointSetBreakForce (chain_joint[i], 1, 0.5, 0.5, 0.5);
+	// set the callback function
+	dJointSetBreakCallback (chain_joint[i], &jointBreakCallback);
+  }
+  
+  // set joint suspension
+  for (i=0; i<4; i++) {
+    dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4);
+    dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.1);
+  }
+
+  // lock back wheels along the steering axis
+  for (i=1; i<4; i++) {
+    // set stops to make sure wheels always stay in alignment
+    dJointSetHinge2Param (joint[i],dParamLoStop,0);
+    dJointSetHinge2Param (joint[i],dParamHiStop,0);
+    // the following alternative method is no good as the wheels may get out
+    // of alignment:
+    //   dJointSetHinge2Param (joint[i],dParamVel,0);
+    //   dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
+  }
+  
+  // create car space and add it to the top level space
+  car_space = dSimpleSpaceCreate (space);
+  dSpaceSetCleanup (car_space,0);
+  dSpaceAdd (car_space,box[0]);
+  dSpaceAdd (car_space,sphere[0]);
+  dSpaceAdd (car_space,sphere[1]);
+  dSpaceAdd (car_space,sphere[2]);
+
+  // environment
+  ground_box = dCreateBox (space,2,1.5,1);
+  dMatrix3 R;
+  dRFromAxisAndAngle (R,0,1,0,-0.15);
+  dGeomSetPosition (ground_box,2,0,-0.34);
+  dGeomSetRotation (ground_box,R);
+  
+  // obstacles
+  for (i=0; i<obstacle_num; i++) {
+    dReal height = 0.1+(dReal(rand()%10)/10.0);
+    obstacle[i] = dCreateBox (space,0.2,0.2,height);
+	dGeomSetPosition (
+	  obstacle[i],
+	  (rand()%20)-10,
+	  (rand()%20)-10,
+	  height/2.0);
+  }
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dGeomDestroy (box[0]);
+  for (i=0; i<4; i++)
+    dGeomDestroy (sphere[i]);
+	
+  dCloseODE ();
+  
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/contrib/BreakableJoints/test_buggy.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/BreakableJoints/test_buggy.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/BreakableJoints/test_buggy.cpp	(revision 216)
@@ -0,0 +1,327 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+buggy with suspension.
+this also shows you how to use geom groups.
+
+*/
+
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCappedCylinder dsDrawCappedCylinderD
+#endif
+
+
+// some constants
+
+#define LENGTH 0.7	// chassis length
+#define WIDTH 0.5	// chassis width
+#define HEIGHT 0.2	// chassis height
+#define RADIUS 0.18	// wheel radius
+#define STARTZ 0.5	// starting height of chassis
+#define CMASS 1		// chassis mass
+#define WMASS 0.2	// wheel mass
+
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+static dBodyID body[4];
+static dJointID joint[3];	// joint[0] is the front wheel
+static dJointGroupID contactgroup;
+static dGeomID ground;
+static dSpaceID car_space;
+static dGeomID box[1];
+static dGeomID sphere[3];
+static dGeomID ground_box;
+
+
+// things that the user controls
+
+static dReal speed=0,steer=0;	// user commands
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i,n;
+
+  // only collide things with the ground
+  int g1 = (o1 == ground || o1 == ground_box);
+  int g2 = (o2 == ground || o2 == ground_box);
+  if (!(g1 ^ g2)) return;
+
+  const int N = 10;
+  dContact contact[N];
+  n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
+  if (n > 0) {
+    for (i=0; i<n; i++) {
+      contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
+	dContactSoftERP | dContactSoftCFM | dContactApprox1;
+      contact[i].surface.mu = dInfinity;
+      contact[i].surface.slip1 = 0.1;
+      contact[i].surface.slip2 = 0.1;
+      contact[i].surface.soft_erp = 0.5;
+      contact[i].surface.soft_cfm = 0.3;
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c,
+		    dGeomGetBody(contact[i].geom.g1),
+		    dGeomGetBody(contact[i].geom.g2));
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {0.8317f,-0.9817f,0.8000f};
+  static float hpr[3] = {121.0000f,-27.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("Press:\t'a' to increase speed.\n"
+	  "\t'z' to decrease speed.\n"
+	  "\t',' to steer left.\n"
+	  "\t'.' to steer right.\n"
+	  "\t' ' to reset speed and steering.\n");
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  switch (cmd) {
+  case 'a': case 'A':
+    speed += 0.3;
+    break;
+  case 'z': case 'Z':
+    speed -= 0.3;
+    break;
+  case ',':
+    steer -= 0.5;
+    break;
+  case '.':
+    steer += 0.5;
+    break;
+  case ' ':
+    speed = 0;
+    steer = 0;
+    break;
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i;
+  if (!pause) {
+    // motor
+    dJointSetHinge2Param (joint[0],dParamVel2,-speed);
+    dJointSetHinge2Param (joint[0],dParamFMax2,0.1);
+
+    // steering
+    dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
+    if (v > 0.1) v = 0.1;
+    if (v < -0.1) v = -0.1;
+    v *= 10.0;
+    dJointSetHinge2Param (joint[0],dParamVel,v);
+    dJointSetHinge2Param (joint[0],dParamFMax,0.2);
+    dJointSetHinge2Param (joint[0],dParamLoStop,-0.75);
+    dJointSetHinge2Param (joint[0],dParamHiStop,0.75);
+    dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1);
+
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldStep (world,0.05);
+
+    // remove all contact joints
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (0,1,1);
+  dsSetTexture (DS_WOOD);
+  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
+  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
+  dsSetColor (1,1,1);
+  for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
+				       dBodyGetRotation(body[i]),0.02f,RADIUS);
+
+  dVector3 ss;
+  dGeomBoxGetLengths (ground_box,ss);
+  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
+
+  /*
+  printf ("%.10f %.10f %.10f %.10f\n",
+	  dJointGetHingeAngle (joint[1]),
+	  dJointGetHingeAngle (joint[2]),
+	  dJointGetHingeAngleRate (joint[1]),
+	  dJointGetHingeAngleRate (joint[2]));
+  */
+}
+
+
+int main (int argc, char **argv)
+{
+  int i;
+  dMass m;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  ground = dCreatePlane (space,0,0,1,0);
+
+  // chassis body
+  body[0] = dBodyCreate (world);
+  dBodySetPosition (body[0],0,0,STARTZ);
+  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
+  dMassAdjust (&m,CMASS);
+  dBodySetMass (body[0],&m);
+  box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT);
+  dGeomSetBody (box[0],body[0]);
+
+  // wheel bodies
+  for (i=1; i<=3; i++) {
+    body[i] = dBodyCreate (world);
+    dQuaternion q;
+    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
+    dBodySetQuaternion (body[i],q);
+    dMassSetSphere (&m,1,RADIUS);
+    dMassAdjust (&m,WMASS);
+    dBodySetMass (body[i],&m);
+    sphere[i-1] = dCreateSphere (0,RADIUS);
+    dGeomSetBody (sphere[i-1],body[i]);
+  }
+  dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);
+
+  // front wheel hinge
+  /*
+  joint[0] = dJointCreateHinge2 (world,0);
+  dJointAttach (joint[0],body[0],body[1]);
+  const dReal *a = dBodyGetPosition (body[1]);
+  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
+  dJointSetHinge2Axis1 (joint[0],0,0,1);
+  dJointSetHinge2Axis2 (joint[0],0,1,0);
+  */
+
+  // front and back wheel hinges
+  for (i=0; i<3; i++) {
+    joint[i] = dJointCreateHinge2 (world,0);
+    dJointAttach (joint[i],body[0],body[i+1]);
+    const dReal *a = dBodyGetPosition (body[i+1]);
+    dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
+    dJointSetHinge2Axis1 (joint[i],0,0,1);
+    dJointSetHinge2Axis2 (joint[i],0,1,0);
+
+    // breakable joints contribution
+    // the wheels can break
+    dJointSetBreakable (joint[i], 1);
+    // the wheels wil break at a specific force
+    dJointSetBreakMode (joint[i], dJOINT_BREAK_AT_B1_FORCE|dJOINT_BREAK_AT_B2_FORCE);
+    // specify the force for the first body connected to the joint ...
+    dJointSetBreakForce (joint[i], 0, 1.5, 1.5, 1.5);
+    // and for the second body
+    dJointSetBreakForce (joint[i], 1, 1.5, 1.5, 1.5);
+  }
+
+  // set joint suspension
+  for (i=0; i<3; i++) {
+    dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4);
+    dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8);
+  }
+
+  // lock back wheels along the steering axis
+  for (i=1; i<3; i++) {
+    // set stops to make sure wheels always stay in alignment
+    dJointSetHinge2Param (joint[i],dParamLoStop,0);
+    dJointSetHinge2Param (joint[i],dParamHiStop,0);
+    // the following alternative method is no good as the wheels may get out
+    // of alignment:
+    //   dJointSetHinge2Param (joint[i],dParamVel,0);
+    //   dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
+  }
+
+  // create car space and add it to the top level space
+  car_space = dSimpleSpaceCreate (space);
+  dSpaceSetCleanup (car_space,0);
+  dSpaceAdd (car_space,box[0]);
+  dSpaceAdd (car_space,sphere[0]);
+  dSpaceAdd (car_space,sphere[1]);
+  dSpaceAdd (car_space,sphere[2]);
+
+  // environment
+  ground_box = dCreateBox (space,2,1.5,1);
+  dMatrix3 R;
+  dRFromAxisAndAngle (R,0,1,0,-0.15);
+  dGeomSetPosition (ground_box,2,0,-0.34);
+  dGeomSetRotation (ground_box,R);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dGeomDestroy (box[0]);
+  dGeomDestroy (sphere[0]);
+  dGeomDestroy (sphere[1]);
+  dGeomDestroy (sphere[2]);
+
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/AssemblyInfo.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/AssemblyInfo.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/AssemblyInfo.cpp	(revision 216)
@@ -0,0 +1,58 @@
+#include "stdafx.h"
+
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("")];
+[assembly:AssemblyDescriptionAttribute("")];
+[assembly:AssemblyConfigurationAttribute("")];
+[assembly:AssemblyCompanyAttribute("")];
+[assembly:AssemblyProductAttribute("")];
+[assembly:AssemblyCopyrightAttribute("")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];		
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("1.0.*")];
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//        When specifying the KeyFile, the location of the KeyFile should be
+//        relative to the project directory.
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly:AssemblyDelaySignAttribute(false)];
+[assembly:AssemblyKeyFileAttribute("")];
+[assembly:AssemblyKeyNameAttribute("")];
+
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Body.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Body.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Body.cpp	(revision 216)
@@ -0,0 +1,322 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "Body.h"
+
+namespace ODEManaged
+{
+
+	//Constructors
+
+		Body::Body(void)
+		{
+			_id = 0;
+		}
+
+		Body::Body(World &world)
+		{
+			_id = dBodyCreate(world.Id());
+		}
+
+
+	//Destructor
+
+		Body::~Body(void)
+		{
+			dBodyDestroy(this->_id);
+		}
+
+
+	//Methods
+
+		//Id
+		dBodyID Body::Id()
+		{
+			return _id;
+		}
+
+
+		//SetData
+		void Body::SetData(void *data)
+		{
+			dBodySetData(this->_id, data);
+		}
+
+		//GetData
+		void *Body::GetData(void)
+		{
+			return dBodyGetData(this->_id);
+		}
+
+
+		//SetPosition
+		void Body::SetPosition (double x, double y, double z)
+		{
+			dBodySetPosition(this->_id, x, y, z);
+		}
+
+
+	//Overloaded GetPosition
+		Vector3 Body::GetPosition(void)
+		{
+			Vector3 retVal;
+			const dReal *temp;
+			temp = dBodyGetPosition(this->_id);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		};
+
+		void Body::GetPosition(double position __gc[])
+		{
+			const dReal *temp;
+			temp = dBodyGetPosition(this->_id);
+			position[0] = temp[0];
+			position[1] = temp[1];
+			position[2] = temp[2];
+		}
+
+
+		//SetRotationIdentity
+		void Body::SetRotationIdentity(void)
+		{
+			dMatrix3 temp;
+			dRSetIdentity(temp);
+			dBodySetRotation(this->_id, temp);	
+		}
+	
+
+		//SetRotation (left handed system=>transpose)
+		void Body::SetRotation(Matrix3 rotation)
+		{
+			dMatrix3 temp;
+			temp[0] = rotation.m11;  
+			temp[4] = rotation.m12;  
+			temp[8] = rotation.m13; 
+			temp[1] = rotation.m21;
+			temp[5] = rotation.m22; 
+			temp[9] = rotation.m23; 
+			temp[2] = rotation.m31; 
+			temp[6] = rotation.m32; 
+			temp[10] = rotation.m33; 
+			dBodySetRotation(this->_id, temp);
+		}
+
+		//GetRotation (left handed system=>transpose)
+		Matrix3 Body::GetRotation(void)
+		{
+			Matrix3 retVal;
+			//const dMatrix3 *m;
+			const dReal *temp;
+			temp = dBodyGetRotation(this->_id);
+			retVal.m11 = temp[0];
+			retVal.m12 = temp[4];
+			retVal.m13 = temp[8];
+			retVal.m21 = temp[1];
+			retVal.m22 = temp[5];
+			retVal.m23 = temp[9];
+			retVal.m31 = temp[2];
+			retVal.m32 = temp[6];
+			retVal.m33 = temp[10];
+			return retVal;	
+		}
+
+
+		//Overloaded SetMass
+		void Body::SetMass(double mass, Vector3 centerOfGravity, Matrix3 inertia)
+		{
+			dMass *temp = new dMass();
+			dMassSetParameters(temp, mass, 
+							   centerOfGravity.x, 
+							   centerOfGravity.y, 
+							   centerOfGravity.z, 
+							   inertia.m11, inertia.m22, 
+							   inertia.m33, inertia.m12, 
+							   inertia.m13, inertia.m23);
+
+  			dBodySetMass(this->_id, temp);
+		}
+
+
+		//SetMassSphere
+		void Body::SetMassSphere(double density, double radius)
+		{
+			dMass *temp = new dMass();
+			dMassSetSphere(temp, density, radius);
+			dBodySetMass(this->_id, temp);
+		}	
+
+
+		//SetMassBox
+		void Body::SetMassBox(double density, double sideX, double sideY, double sideZ)
+		{
+			dMass *temp = new dMass();
+			dMassSetBox(temp, density, sideX, sideY, sideZ);
+			dBodySetMass(this->_id, temp);
+		}	
+
+
+		//SetMassCappedCylinder
+		void Body::SetMassCappedCylinder(double density, int axis, double cylinderRadius, double cylinderLength)
+		{
+			dMass *temp = new dMass();
+			dMassSetCappedCylinder(temp, density, axis,
+								   cylinderRadius, 
+								   cylinderLength);
+
+			dBodySetMass(this->_id, temp);
+		}
+
+
+		//AddForce
+		void Body::AddForce(double fX, double fY, double fZ)
+		{
+			dBodyAddForce(this->_id, fX, fY, fZ);
+		}
+
+
+		//AddRelForce
+		void Body::AddRelForce(double fX, double fY, double fZ)
+		{
+			dBodyAddRelForce(this->_id, fX,fY,fZ);
+		}
+
+
+		//AddForceAtPos
+		void Body::AddForceAtPos(double fX, double fY, double fZ, double pX, double pY, double pZ)
+		{
+			dBodyAddForceAtPos(this->_id, fX, fY, fZ, pX, pY, pZ);
+		}
+
+
+		//AddRelForceAtPos
+		void Body::AddRelForceAtPos(double fX, double fY, double fZ, double pX, double pY, double pZ)
+		{
+			dBodyAddRelForceAtPos(this->_id, fX, fY, fZ, pX, pY, pZ);
+		}
+
+
+		//AddRelForceAtRelPos
+		void Body::AddRelForceAtRelPos(double fX, double fY, double fZ, double pX, double pY, double pZ)
+		{
+			dBodyAddRelForceAtRelPos(this->_id, fX, fY, fZ, pX, pY, pZ);
+		}	
+
+
+		//ApplyLinearVelocityDrag
+		void Body::ApplyLinearVelocityDrag(double dragCoef)
+		{
+			const dReal *temp;
+			double fX;
+			double fY;
+			double fZ;		
+			temp = dBodyGetLinearVel(this->_id);			
+			fX = temp[0]*dragCoef*-1;
+			fY = temp[1]*dragCoef*-1;
+			fZ = temp[2]*dragCoef*-1;
+			dBodyAddForce(this->_id, fX, fY, fZ);
+		}
+
+
+		//ApplyAngularVelocityDrag
+		void Body::ApplyAngularVelocityDrag(double dragCoef)
+		{
+			const dReal *temp;
+			double fX;
+			double fY;
+			double fZ;
+			temp = dBodyGetAngularVel(this->_id);
+			fX = temp[0]*dragCoef*-1;
+			fY = temp[1]*dragCoef*-1;
+			fZ = temp[2]*dragCoef*-1;
+			dBodyAddTorque(this->_id, fX, fY, fZ);
+		}
+
+
+		//AddTorque
+		void Body::AddTorque(double fX, double fY, double fZ)
+		{
+			dBodyAddTorque(this->_id, fX, fY, fZ);
+		}
+
+
+		//AddRelTorque
+		void Body::AddRelTorque(double fX, double fY, double fZ)
+		{
+			dBodyAddRelTorque(this->_id, fX,fY,fZ);
+		}
+
+
+		//SetLinearVelocity
+		void Body::SetLinearVelocity(double x, double y, double z)
+		{
+			dBodySetLinearVel(this->_id, x, y, z);
+		}
+
+
+		//GetLinearVelocity
+		Vector3 Body::GetLinearVelocity(void)
+		{
+			Vector3 retVal;
+			const dReal *temp;
+			temp = dBodyGetLinearVel(this->_id);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+		//SetAngularVelocity
+		void Body::SetAngularVelocity(double x, double y, double z)
+		{
+			dBodySetAngularVel(this->_id, x, y, z);
+		}
+
+		//GetAngularVelocity
+		Vector3 Body::GetAngularVelocity(void)
+		{
+			Vector3 retVal;
+			const dReal *temp;
+			temp = dBodyGetAngularVel(this->_id);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+		
+		//GetRelPointPos
+		Vector3 Body::GetRelPointPos(double pX, double pY, double pZ)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dBodyGetRelPointPos(this->_id, pX, pY, pZ, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+		//GetRelPointVel
+		Vector3 Body::GetRelPointVel(double pX, double pY, double pZ)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dBodyGetRelPointVel(this->_id, pX, pY, pZ, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+		//ConnectedTo
+		int Body::ConnectedTo(const Body &b)
+		{ 
+			return dAreConnected(this->_id, b._id);
+		}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Body.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Body.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Body.h	(revision 216)
@@ -0,0 +1,76 @@
+#pragma once
+
+#include "World.h"
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{	
+	__gc public class Body
+	{
+		public:
+
+			//Constructors and Destructors
+		
+			Body(void);
+			Body(World &world);
+		
+			~Body(void);
+
+
+			//Public Methods
+
+			dBodyID Id();
+			void	SetData				(void *data);
+			void	*GetData			(void);
+
+			//POSITION
+			void SetPosition(double x, double y, double z);
+			Vector3 GetPosition(void);
+			void GetPosition(double  position __gc[]);
+			
+			//ROTATION
+			void SetRotationIdentity(void);
+			void SetRotation(Matrix3 rotation);
+			Matrix3 GetRotation(void);
+
+			//MASS
+			void SetMass(double mass, Vector3 centerOfGravity, Matrix3 inertia);
+			void SetMassSphere(double density, double radius);
+			void SetMassBox(double density, double sideX, double sideY, double sideZ);
+			void SetMassCappedCylinder(double density, int axis, double cylinderRadius, double cylinderLength);
+
+			//FORCE AND TORQUE
+			void AddForce(double fX, double fY, double fZ);
+			void AddRelForce(double fX, double fY, double fZ);
+			void AddForceAtPos(double fX, double fY, double fZ,double pX, double pY, double pZ);
+			void AddRelForceAtPos(double fX, double fY, double fZ,double pX, double pY, double pZ);
+			void AddRelForceAtRelPos(double fX, double fY, double fZ,double pX, double pY, double pZ);
+			void ApplyLinearVelocityDrag(double dragCoef);
+			void ApplyAngularVelocityDrag(double dragCoef);
+
+			
+			void AddTorque(double fX, double fY, double fZ);
+			void AddRelTorque(double fX, double fY, double fZ);
+
+			//LINEAR VELOCITY
+			void SetLinearVelocity (double x, double y, double z);
+			Vector3 GetLinearVelocity(void);
+
+			//ANGULAR VELOCITY
+			void SetAngularVelocity (double x, double y, double z);
+			Vector3 GetAngularVelocity(void);
+
+			//POINT
+			Vector3 GetRelPointPos(double pX, double pY, double pZ);
+			Vector3 GetRelPointVel(double pX, double pY, double pZ);
+
+			//CONNECTED TO
+			int ConnectedTo (const Body &b);
+
+		private:
+			
+			dBodyID _id;
+
+	};
+}
+
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/CommonMgd.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/CommonMgd.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/CommonMgd.h	(revision 216)
@@ -0,0 +1,43 @@
+#pragma once
+
+namespace ODEManaged
+{
+
+	__value public struct Vector3
+	{
+		double x;
+		double y;
+		double z;
+	};
+
+
+	__value public struct Vector4
+	{
+		double W;
+		double x;
+		double y;
+		double z;
+	};
+
+
+	__value public struct Matrix3
+	{
+		double m11;
+		double m12;
+		double m13;
+		double m21;
+		double m22;
+		double m23;
+		double m31;
+		double m32;
+		double m33;
+	};
+
+	//__value public struct NearCallback
+	//{
+	//	void *data;
+	//	dGeomID o1;
+	//	dGeomID o2;
+	//};
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/DotNetManaged.sln
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/DotNetManaged.sln	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/DotNetManaged.sln	(revision 216)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DotNetManaged", "DotNetManaged.vcproj", "{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Debug
+		ConfigName.1 = Release
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Debug.ActiveCfg = Debug|Win32
+		{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Debug.Build.0 = Debug|Win32
+		{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Release.ActiveCfg = Release|Win32
+		{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/DotNetManaged.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/DotNetManaged.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/DotNetManaged.vcproj	(revision 216)
@@ -0,0 +1,379 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="DotNetManaged"
+	ProjectGUID="{4B75AC19-971A-4CC6-A4F5-0695C9F8562F}"
+	Keyword="ManagedCProj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="2"
+			CharacterSet="2"
+			ManagedExtensions="TRUE">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				AdditionalIncludeDirectories="&quot;F:\Documents and Settings\Visual Studio Projects\ODE\Contrib\tri-collider&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\ODE\Src&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\ODE&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\Include&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG"
+				MinimalRebuild="FALSE"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="1"
+				WarningLevel="3"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/DotNetManaged.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="2"
+			CharacterSet="2"
+			ManagedExtensions="TRUE"
+			WholeProgramOptimization="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="0"
+				OmitFramePointers="TRUE"
+				AdditionalIncludeDirectories="&quot;F:\Documents and Settings\Visual Studio Projects\ODE&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\Contrib\DotNetManaged\odeOLd&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\Include&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\Include\ODE&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\ODE\Src&quot;;&quot;F:\Documents and Settings\Visual Studio Projects\ODE\Contrib\tri-collider&quot;"
+				PreprocessorDefinitions="WIN32;NDEBUG"
+				MinimalRebuild="FALSE"
+				WarningLevel="3"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/ode.dll"
+				SuppressStartupBanner="TRUE"
+				GenerateDebugInformation="FALSE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+			<File
+				RelativePath="..\..\ODE\Src\array.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\error.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\fastdot.c">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\fastldlt.c">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\fastlsolve.c">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\fastltsolve.c">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\geom.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\joint.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\lcp.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\mass.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\mat.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\matrix.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\memory.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\misc.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\objects.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\obstack.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\ode.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\odemath.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\rotation.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\space.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\step.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\testing.cpp">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\timer.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc">
+			<File
+				RelativePath="..\..\ODE\Src\array.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\common.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\config.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\contact.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\error.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\geom.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\geom_internal.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\joint.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\lcp.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\mass.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\mat.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\matrix.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\memory.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\misc.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\objects.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\obstack.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\ode.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\odecpp.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\odemath.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\rotation.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\space.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\step.h">
+			</File>
+			<File
+				RelativePath="..\..\ODE\Src\testing.h">
+			</File>
+			<File
+				RelativePath="..\..\Include\ODE\timer.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;r">
+		</Filter>
+		<Filter
+			Name="Wrapper"
+			Filter="">
+			<Filter
+				Name="Header Files"
+				Filter="">
+				<File
+					RelativePath="Body.h">
+				</File>
+				<File
+					RelativePath="CommonMgd.h">
+				</File>
+				<File
+					RelativePath="Geom.h">
+				</File>
+				<File
+					RelativePath="Joint.h">
+				</File>
+				<File
+					RelativePath="JointAMotor.h">
+				</File>
+				<File
+					RelativePath="JointBall.h">
+				</File>
+				<File
+					RelativePath="JointFixed.h">
+				</File>
+				<File
+					RelativePath="JointGroup.h">
+				</File>
+				<File
+					RelativePath="JointHinge.h">
+				</File>
+				<File
+					RelativePath="JointHinge2.h">
+				</File>
+				<File
+					RelativePath="JointSlider.h">
+				</File>
+				<File
+					RelativePath="Space.h">
+				</File>
+				<File
+					RelativePath="Stdafx.h">
+				</File>
+				<File
+					RelativePath="World.h">
+				</File>
+			</Filter>
+			<Filter
+				Name="Source Files"
+				Filter="">
+				<File
+					RelativePath="Body.cpp">
+				</File>
+				<File
+					RelativePath="Geom.cpp">
+					<FileConfiguration
+						Name="Debug|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="Joint.cpp">
+					<FileConfiguration
+						Name="Debug|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="JointAMotor.cpp">
+				</File>
+				<File
+					RelativePath="JointBall.cpp">
+				</File>
+				<File
+					RelativePath="JointFixed.cpp">
+				</File>
+				<File
+					RelativePath="JointGroup.cpp">
+				</File>
+				<File
+					RelativePath="JointHinge.cpp">
+				</File>
+				<File
+					RelativePath="JointHinge2.cpp">
+				</File>
+				<File
+					RelativePath="JointSlider.cpp">
+				</File>
+				<File
+					RelativePath="Space.cpp">
+					<FileConfiguration
+						Name="Debug|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32">
+						<Tool
+							Name="VCCLCompilerTool"
+							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="Stdafx.cpp">
+				</File>
+				<File
+					RelativePath="World.cpp">
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Geom.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Geom.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Geom.cpp	(revision 216)
@@ -0,0 +1,219 @@
+
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "Geom.h"
+
+
+namespace ODEManaged
+{
+
+	//Constructors
+
+		Geom::Geom(void)
+		{ 
+			_id = 0;
+		}
+
+
+	//Destructor
+
+		Geom::~Geom(void)
+		{
+			dGeomDestroy(this->_id);
+		}
+
+
+	//Methods
+			
+		//Id
+		dGeomID Geom::Id(void)
+		{
+			return _id;
+		}
+
+
+		//GetBody
+		dBodyID Geom::GetBody(void)
+		{
+			return dGeomGetBody(this->_id);
+		}
+
+
+		//Overloaded SetBody
+		void Geom::SetBody(Body &body)
+		{
+			dGeomSetBody(this->_id, body.Id());
+		}
+
+		//void Geom::SetBody(dBodyID b)
+		//{
+		//	dGeomSetBody(this->_id, b);
+		//}
+
+
+		//SetPosition
+		void Geom::SetPosition(double x, double y, double z)
+		{
+			dGeomSetPosition(this->_id, x, y, z);
+		}
+
+
+		//SetRotation
+		void Geom::SetRotation(Matrix3 rotation)
+		{
+			dMatrix3 temp;
+			temp[0] = rotation.m11;  
+			temp[4] = rotation.m12;  
+			temp[8] = rotation.m13; 
+			temp[1] = rotation.m21;
+			temp[5] = rotation.m22; 
+			temp[9] = rotation.m23; 
+			temp[2] = rotation.m31; 
+			temp[6] = rotation.m32; 
+			temp[10] = rotation.m33;
+			dGeomSetRotation(_id, temp);
+		}
+		
+		
+		//Destroy
+		void Geom::Destroy() 
+		{
+			if(this->_id) dGeomDestroy(this->_id);
+			_id = 0;
+		}
+
+
+		//SetData
+		void Geom::SetData(void *data)
+		{
+			dGeomSetData(this->_id, data);
+		}
+
+
+		//GetData
+		void *Geom::GetData(void)
+		{
+			return dGeomGetData(this->_id);
+		}
+
+
+		//GetPosition
+		Vector3 Geom::GetPosition(void)
+		{
+			Vector3 retVal;
+			const dReal *temp;
+			temp = dGeomGetPosition(this->_id);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+		//GetRotation (left handed system=>transpose)
+		Matrix3 Geom::GetRotation(void)
+		{
+			Matrix3 retVal;
+			const dReal *temp;
+			temp = dGeomGetRotation(this->_id);
+			retVal.m11 = temp[0];
+			retVal.m12 = temp[4];
+			retVal.m13 = temp[8];
+			retVal.m21 = temp[1];
+			retVal.m22 = temp[5];
+			retVal.m23 = temp[9];
+			retVal.m31 = temp[2];
+			retVal.m32 = temp[6];
+			retVal.m33 = temp[10];
+			return retVal;	
+		}
+
+
+		//CreateSphere
+		void Geom::CreateSphere(Space &space, double radius)
+		{
+			if(this->_id) dGeomDestroy(this->_id);
+			_id = dCreateSphere(space.Id(), radius);
+		}
+
+
+		//CreateBox
+		void Geom::CreateBox(Space &space, double lx, double ly, double lz)
+		{
+			if(this->_id) dGeomDestroy(this->_id);
+			_id = dCreateBox(space.Id(), lx, ly, lz);
+		}
+
+		
+		//CreatePlane
+		void Geom::CreatePlane(Space &space, double a, double b, double c, double d) 
+		{
+			if(this->_id) dGeomDestroy(this->_id);
+			_id = dCreatePlane(space.Id(), a, b, c, d);
+		}
+
+
+		//CreateCCylinder
+		void Geom::CreateCCylinder(Space &space, double radius, double length)
+		{
+			if(this->_id) dGeomDestroy(this->_id);
+			_id = dCreateCCylinder(space.Id(), radius, length);
+		}
+	
+
+		//SphereGetRadius
+		double Geom::SphereGetRadius(void)
+		{
+			return dGeomSphereGetRadius(this->_id);
+		}
+		
+		
+		//BoxGetLengths
+		Vector3 Geom::BoxGetLengths(void)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dGeomBoxGetLengths(this->_id, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+		//PlaneGetParams
+		Vector4 Geom::PlaneGetParams(void)
+		{
+			Vector4 retVal;
+			dVector4 temp;
+			dGeomPlaneGetParams(this->_id, temp);
+			retVal.W = temp[0];
+			retVal.x = temp[1];
+			retVal.y = temp[2];
+			retVal.z = temp[3];
+			return retVal;
+		}
+		
+		
+		//CCylinderGetParams
+		void Geom::CCylinderGetParams(double *radius, double *length)
+		{
+			dGeomCCylinderGetParams(this->_id, radius, length);
+		}
+		
+
+		//GetClass
+		int Geom::GetClass(void)
+		{
+			return dGeomGetClass(this->_id);
+		}
+		
+}
+
+
+
+
+
+
+
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Geom.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Geom.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Geom.h	(revision 216)
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "Body.h"
+#include "Space.h"
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{
+	__gc public class Geom
+	{
+	public:
+
+		
+		//Constructor
+			
+			Geom					(void);
+
+			
+		//Destructor
+			
+			~Geom					(void);
+
+
+		//Methods
+
+			//Basic Stuff
+
+				dGeomID Id					(void);
+				dBodyID GetBody				(void);
+				
+				//Overloaded SetBody
+				void	SetBody				(Body &body);
+				/*void	SetBody				(dBodyID b);*/
+				
+				Vector3	GetPosition			(void);
+				void	SetPosition			(double x, double y, double z);
+				
+				Matrix3	GetRotation			(void);
+				void	SetRotation			(Matrix3 rotation);
+				
+				void	SetData				(void *data);
+				void	*GetData			(void);
+
+
+			//Create Objects
+
+				void	CreateSphere		(Space &space, double radius);
+				void	CreateBox			(Space &space, double lx, double ly, double lz);
+				void	CreatePlane			(Space &space, double a, double b, double c, double d);
+				void	CreateCCylinder		(Space &space, double radius, double length);
+				
+
+			//Destroy Objects
+
+				void	Destroy				(void);
+
+
+			//Get Object's Parameters
+
+				double	SphereGetRadius		(void);
+				Vector3 BoxGetLengths		(void);
+				Vector4 PlaneGetParams		(void);
+				void	CCylinderGetParams	(double *radius, double *length);
+				int		GetClass			(void);
+
+
+		//Properties
+		
+			private:
+			
+				dGeomID _id;
+	
+	};
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Joint.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Joint.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Joint.cpp	(revision 216)
@@ -0,0 +1,35 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "joint.h"
+#include "CommonMgd.h"
+#include "world.h"
+
+namespace ODEManaged
+{
+	
+	//Constructor
+
+		Joint::Joint(void)
+		{
+			_id=0;
+		}
+
+
+	//Destructor
+
+		Joint::~Joint(void)
+		{
+			dJointDestroy(this->_id);
+		}
+
+
+	//Methods
+
+		//Id
+		dJointID Joint::Id(void)
+		{
+			return _id;
+		}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Joint.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Joint.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Joint.h	(revision 216)
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "JointGroup.h"
+#include "World.h"
+#include "Body.h"
+
+namespace ODEManaged
+{	
+	__gc public class Joint
+	{
+	protected:
+		//Constructor and Destructor Defenition
+		Joint(void);
+		~Joint(void);
+
+		//Public Methods
+		dJointID Id(void);
+
+		dJointID _id;	
+ };
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointAMotor.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointAMotor.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointAMotor.cpp	(revision 216)
@@ -0,0 +1,162 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "JointAMotor.h"
+
+namespace ODEManaged
+{
+
+	//Constructors
+
+		JointAMotor::JointAMotor(void) : Joint(){}
+
+
+		JointAMotor::JointAMotor(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateAMotor(world.Id(), 0);
+		}
+
+		
+		JointAMotor::JointAMotor(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateAMotor(world.Id(), jointGroup.Id());
+		}
+
+
+	//Destructor
+
+		JointAMotor::~JointAMotor(void){}
+
+
+	//Methods
+
+		//Overloaded Create 
+			void JointAMotor::Create(World &world, JointGroup &jointGroup)
+			{
+				if(this->_id) dJointDestroy(this->_id);
+				_id = dJointCreateAMotor(world.Id(), jointGroup.Id());
+			}
+
+			void JointAMotor::Create(World &world)
+			{
+				if(this->_id) dJointDestroy(this->_id);
+				_id = dJointCreateAMotor(world.Id(), 0);
+			}
+
+
+		//Overloaded Attach
+			void JointAMotor::Attach(Body &body1, Body &body2)
+			{
+				dJointAttach(this->_id, body1.Id(), body2.Id());
+			}
+
+			void JointAMotor::Attach(Body &body1)
+			{
+				dJointAttach(this->_id, body1.Id(), 0);
+			}
+
+
+		//SetNumAxes
+
+			void JointAMotor::SetNumAxes(int num)
+			{
+				dJointSetAMotorNumAxes(this->_id, num);
+			}
+
+
+		//GetNumAxes
+
+			int JointAMotor::GetNumAxes(void)
+			{
+				return dJointGetAMotorNumAxes(this->_id);
+			}
+
+
+		//SetAxis
+
+			void JointAMotor::SetAxis(int anum, int rel, double x, double y ,double z)
+			{
+				dJointSetAMotorAxis(this->_id, anum, rel, x, y, z);
+			}
+
+
+		//GetAxis
+
+			Vector3 JointAMotor::GetAxis(int anum)
+			{
+				Vector3 retVal;
+				dVector3 temp;
+				dJointGetAMotorAxis(this->_id, anum, temp);
+				retVal.x = temp[0];
+				retVal.y = temp[1];
+				retVal.z = temp[2];
+				return retVal;
+			}
+
+
+		//SetAngle
+
+			void JointAMotor::SetAngle(int anum, double angle)
+			{
+				dJointSetAMotorAngle(this->_id, anum, angle);
+			}
+
+
+		//GetAngle
+
+			double JointAMotor::GetAngle(int anum)
+			{
+				return dJointGetAMotorAngle(this->_id, anum);
+			}
+
+
+		//SetParam
+
+			void JointAMotor::SetParam(int parameter, double value)
+			{
+				dJointSetAMotorParam(this->_id, parameter, value);
+			}
+
+
+		//GetParam
+
+			double JointAMotor::GetParam(int parameter)
+			{
+				return dJointGetAMotorParam(this->_id, parameter);
+			}
+
+
+		//SetMode
+
+			void JointAMotor::SetMode(int mode)
+			{
+				dJointSetAMotorMode(this->_id, mode);
+			}
+
+
+		//GetMode
+
+			int JointAMotor::GetMode(void)
+			{
+				return dJointGetAMotorMode(this->_id);
+			}
+
+
+		//GetAxisRel
+
+			int JointAMotor::GetAxisRel(int anum)
+			{
+				return dJointGetAMotorAxisRel(this->_id, anum);
+			}
+
+
+		//GetAngleRate
+
+			double JointAMotor::GetAngleRate(int anum)
+			{
+				return dJointGetAMotorAngleRate(this->_id, anum);
+			}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointAMotor.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointAMotor.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointAMotor.h	(revision 216)
@@ -0,0 +1,62 @@
+#pragma once
+
+#include "Joint.h"
+
+namespace ODEManaged
+{
+	__gc public class JointAMotor : public Joint
+	{
+	public:
+
+
+		//Constructors
+
+			JointAMotor				(void);
+			JointAMotor				(World &world);
+			JointAMotor				(World &world, JointGroup &jointGroup);
+			
+
+		//Destructor
+			
+			virtual ~JointAMotor	(void);
+
+
+		//Methods	
+		
+			//Basic Stuff
+			
+				//Overloaded Create
+				void	Create			(World &world, JointGroup &jointGroup);
+				void	Create			(World &world);
+
+				void	SetNumAxes		(int num);
+				int		GetNumAxes		(void);
+
+				void	SetAxis			(int anum, int rel, double x, double y, double z);
+				Vector3 GetAxis			(int anum);
+				
+				void	SetAngle		(int anum, double angle);
+				double	GetAngle		(int anum);
+
+				void	SetMode			(int mode);
+				int		GetMode			(void);
+
+				int		GetAxisRel		(int anum);
+				double	GetAngleRate	(int anum);
+
+				//Overloaded Attach
+				void	Attach			(Body &body1, Body &body2);	
+				void	Attach			(Body &body1);
+
+
+			//Movement Parameters
+
+			void	SetParam		(int parameter, double value);
+			double	GetParam		(int parameter);
+			
+
+			
+
+
+	};
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointBall.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointBall.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointBall.cpp	(revision 216)
@@ -0,0 +1,79 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "jointball.h"
+
+namespace ODEManaged
+{
+	
+	//Constructors
+
+		JointBall::JointBall(void) : Joint(){}
+
+
+		JointBall::JointBall(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateBall(world.Id(), 0);
+		}
+
+		
+		JointBall::JointBall(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateBall(world.Id(), jointGroup.Id());
+		}
+
+
+	//Destructor
+
+		JointBall::~JointBall(void){}
+
+
+	//Methods
+
+		//Overloaded Create 
+		void JointBall::Create(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateBall(world.Id(), jointGroup.Id());
+		}
+
+		void JointBall::Create(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateBall(world.Id(), 0);
+		}
+
+
+		//Overloaded Attach
+		void JointBall::Attach(Body &body1, Body &body2)
+		{
+			dJointAttach(this->_id, body1.Id(), body2.Id());
+		}
+
+		void JointBall::Attach(Body &body1)
+		{
+			dJointAttach(this->_id, body1.Id(), 0);
+		}
+
+
+		//SetAnchor
+		void JointBall::SetAnchor(double x, double y ,double z)
+		{
+			dJointSetBallAnchor(this->_id, x, y, z);
+		}
+
+		//GetAnchor
+		Vector3 JointBall::GetAnchor(void)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dJointGetBallAnchor(this->_id,temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointBall.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointBall.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointBall.h	(revision 216)
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "Joint.h"
+
+namespace ODEManaged
+{
+	__gc public class JointBall : public Joint
+	{
+	public:
+
+		//Constructors
+
+			JointBall(void);
+			JointBall(World &world);
+			JointBall(World &world, JointGroup &jointGroup);
+		
+
+		//Destructors
+
+			virtual ~JointBall(void);
+
+
+		//Methods
+		
+			//Overloaded Create
+			void Create(World &world, JointGroup &jointGroup);
+			void Create(World &world);
+			
+			//Overloaded Attach
+			void Attach(Body &body1, Body &body2);	
+			void Attach(Body &body1);
+
+			void SetAnchor(double x, double y, double z);
+			Vector3 GetAnchor(void);
+
+	};
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointFixed.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointFixed.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointFixed.cpp	(revision 216)
@@ -0,0 +1,67 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "jointfixed.h"
+
+namespace ODEManaged
+{
+
+	//Constructors
+
+		JointFixed::JointFixed(void) : Joint(){}
+
+
+		JointFixed::JointFixed(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateFixed(world.Id(),0);
+		}
+		
+
+		JointFixed::JointFixed(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateFixed(world.Id(), jointGroup.Id());
+		}
+
+
+	//Destructor
+
+		JointFixed::~JointFixed(void){}
+
+
+	//Methods
+
+		//Overloaded Create 
+		void JointFixed::Create(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateFixed(world.Id(), jointGroup.Id());
+		}
+
+		void JointFixed::Create(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateFixed(world.Id(), 0);
+		}
+
+
+		//Overloaded Attach
+		void JointFixed::Attach(Body &body1, Body &body2)
+		{
+			dJointAttach(this->_id, body1.Id(), body2.Id());
+		}
+
+		void JointFixed::Attach(Body &body1)
+		{
+			dJointAttach(this->_id, body1.Id(), 0);
+		}
+
+
+		//Fixed
+		void JointFixed::SetFixed(void)
+		{
+			dJointSetFixed(this->_id);
+		}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointFixed.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointFixed.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointFixed.h	(revision 216)
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "Joint.h"
+
+namespace ODEManaged
+{
+	__gc public class JointFixed : public Joint
+	{
+	public:
+
+		//Constructors
+
+			JointFixed(void);
+			JointFixed(World &world);
+			JointFixed(World &world, JointGroup &jointGroup);
+		
+
+		//Destructor
+
+			virtual ~JointFixed(void);
+
+
+		//Methods
+		
+			//Overloaded Create
+			void Create(World &world, JointGroup &jointGroup);
+			void Create(World &world);
+
+			//Overloaded Attach 
+			void Attach(Body &body1, Body &body2);	
+			void Attach(Body &body1);
+		
+			void SetFixed(void);
+
+	};
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointGroup.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointGroup.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointGroup.cpp	(revision 216)
@@ -0,0 +1,53 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "jointgroup.h"
+
+namespace ODEManaged
+{
+
+	//Constructors
+
+		JointGroup::JointGroup(void)
+		{	
+			_id=0;
+		}
+
+		JointGroup::JointGroup (int maxSize)
+		{
+			_id = dJointGroupCreate(maxSize);
+		}
+
+
+	//Destructor
+
+		JointGroup::~JointGroup(void)
+		{
+			dJointGroupDestroy(this->_id);
+		}
+
+	
+	//Methods
+
+		//ID
+		dJointGroupID JointGroup::Id()
+		{
+			return _id;
+		}
+
+
+		//Create
+		void JointGroup::Create (int maxSize)
+		{
+			if(_id) dJointGroupDestroy(_id);
+			_id = dJointGroupCreate(maxSize);
+		}
+
+
+		//Empty
+		void JointGroup::Empty (void)
+		{
+			dJointGroupEmpty(this->_id);
+		}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointGroup.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointGroup.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointGroup.h	(revision 216)
@@ -0,0 +1,33 @@
+#pragma once
+
+namespace ODEManaged
+{
+	__gc public class JointGroup
+	{
+	public:
+
+		//Constructors
+
+			JointGroup(void);
+			JointGroup(int maxSize);
+		
+
+		//Destructor
+
+			~JointGroup(void);
+
+
+		//Methods
+		
+			dJointGroupID Id(void);
+			void Create(int maxSize);
+			void Empty(void);
+
+		
+		private:
+
+			dJointGroupID _id;
+
+	};
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge.cpp	(revision 216)
@@ -0,0 +1,121 @@
+#include "stdafx.h"
+
+#include <ode/ode.h>
+#include "jointhinge.h"
+
+namespace ODEManaged
+{
+
+	//Constructors
+
+		JointHinge::JointHinge(void) : Joint(){}
+
+
+		JointHinge::JointHinge(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateHinge(world.Id(), 0);
+		}
+
+		
+		JointHinge::JointHinge(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateHinge(world.Id(), jointGroup.Id());
+		}
+
+
+	//Destructor
+
+		JointHinge::~JointHinge(void){}
+
+
+	//Methods
+
+		//Overloaded Create 
+		void JointHinge::Create(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateHinge(world.Id(), jointGroup.Id());
+		}
+
+		void JointHinge::Create(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateHinge(world.Id(), 0);
+		}
+
+
+		//Overloaded Attach 
+		void JointHinge::Attach(Body &body1, Body &body2)
+		{
+			dJointAttach(this->_id, body1.Id(), body2.Id());
+		}
+
+		void JointHinge::Attach(Body &body1)
+		{
+			dJointAttach(this->_id, body1.Id(), 0);
+		}
+
+
+		//SetAxis
+		void JointHinge::SetAxis(double x, double y, double z)
+		{
+			dJointSetHingeAxis(this->_id, x, y, z);
+		}
+
+		//GetAxis
+		Vector3 JointHinge::GetAxis(void)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dJointGetHingeAxis(this->_id, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+		//SetAnchor
+		void JointHinge::SetAnchor(double x, double y, double z)
+		{
+			dJointSetHingeAnchor(this->_id, x, y, z);
+		}
+
+		//GetAnchor
+		Vector3 JointHinge::GetAnchor(void)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dJointGetHingeAnchor(this->_id, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+	//Movement Parameters
+
+		//SetAllMovParams
+		void JointHinge::SetAllMovParams(double LoStop, double HiStop,
+										 double Velocity, double MaxForce,
+										 double FudgeFactor, double Bounce,
+										 double StopERP, double StopCFM)
+		{
+			if (LoStop > -3.141592653 && LoStop <= 0) 
+				dJointSetHingeParam(this->_id, dParamLoStop, LoStop);
+
+			if (HiStop < 3.141592653 && HiStop >= 0)
+				dJointSetHingeParam(this->_id, dParamHiStop, HiStop);
+
+			dJointSetHingeParam(this->_id, dParamVel, Velocity);
+			dJointSetHingeParam(this->_id, dParamFMax, MaxForce);
+			dJointSetHingeParam(this->_id, dParamFudgeFactor, FudgeFactor);
+			dJointSetHingeParam(this->_id, dParamBounce, Bounce);
+			dJointSetHingeParam(this->_id, dParamStopERP, StopERP);
+			dJointSetHingeParam(this->_id, dParamStopCFM, StopCFM);
+		}
+				
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge.h	(revision 216)
@@ -0,0 +1,195 @@
+#pragma once
+
+#include "Joint.h"
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{
+	__gc public class JointHinge : public Joint
+	{
+	public:
+
+		//Constructors
+
+			JointHinge(void);
+			JointHinge(World &world);
+			JointHinge(World &world, JointGroup &jointGroup);
+			
+
+		//Destructor
+
+			virtual~JointHinge(void);
+
+		
+		//Methods	
+			
+			//Overloaded Create
+			void Create(World &world, JointGroup &jointGroup);
+			void Create(World &world);
+
+			//Overloaded Attach
+			void Attach(Body &body1, Body &body2);	
+			void Attach(Body &body1);
+
+			void SetAnchor(double x, double y, double z);
+			Vector3 GetAnchor(void);
+
+			void SetAxis(double x, double y, double z);
+			Vector3 GetAxis(void);
+
+			void SetAllMovParams(double LoStop, double HiStop,
+								 double Velocity, double MaxForce,
+								 double FudgeFactor, double Bounce,
+								 double StopERP, double StopCFM);
+
+
+		//Properties
+
+			//LoStop
+			__property double get_LoStop(void)
+				{
+					return dJointGetHingeParam(this->_id, dParamLoStop);
+				}
+
+			__property void	set_LoStop(double value)
+			{
+				if (value > -3.141592653 && value <= 0)
+					dJointSetHingeParam(this->_id, dParamLoStop, value);
+			}
+
+
+			//HiStop
+			__property double get_HiStop(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamHiStop);
+			}
+
+			__property void set_HiStop(double value)
+			{
+				if (value < 3.141592653 && value >= 0)
+					dJointSetHingeParam(this->_id, dParamHiStop, value);
+			}
+			
+
+			//Velocity
+			__property double get_Velocity(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamVel);
+			}
+
+			__property void set_Velocity(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamVel, value);
+			}
+
+
+			//MaxForce
+			__property double get_MaxForce(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamFMax);
+			}
+
+			__property void set_MaxForce(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamFMax, value);
+			}
+
+
+			//FudgeFactor
+			__property double get_FudgeFactor(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamFudgeFactor);
+			}
+
+			__property void set_FudgeFactor(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamFudgeFactor, value);
+			}
+
+
+			//Bounce
+			__property double get_Bounce(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamBounce);
+			}
+
+			__property void set_Bounce(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamBounce, value);
+			}
+
+
+			//StopERP
+			__property double get_StopERP(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamStopERP);
+			}
+
+			__property void set_StopERP(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamStopERP, value);
+			}
+
+
+			//StopCFM
+			__property double get_StopCFM(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamStopCFM);
+			}
+
+			__property void set_StopCFM(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamStopCFM, value);
+			}
+
+
+			//GetAngle
+			__property double get_Angle(void)
+			{
+				return dJointGetHingeAngle(this->_id);
+			}
+
+
+			//GetAngleRate
+			__property double get_AngleRate(void)
+			{
+				return dJointGetHingeAngleRate(this->_id);
+			}
+
+	};
+
+}
+
+//				void	SetSuspensionERP(double value);
+//				double	GetSuspensionERP(void);
+
+//				void	SetSuspensionCFM(double value);
+//				double	GetSuspensionCFM(void);
+
+/*				
+			//SetSuspensionERP
+			void JointHinge::SetSuspensionERP(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamSuspensionERP, value);
+			}
+
+			//GetSuspensionERP
+			double JointHinge::GetSuspensionERP(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamSuspensionERP);
+			}
+							
+				
+			//SetSuspensionCFM
+			void JointHinge::SetSuspensionCFM(double value)
+			{
+				dJointSetHingeParam(this->_id, dParamSuspensionCFM, value);
+			}
+
+			//GetSuspensionCFM
+			double JointHinge::GetSuspensionCFM(void)
+			{
+				return dJointGetHingeParam(this->_id, dParamSuspensionCFM);
+			}
+
+*/
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge2.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge2.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge2.cpp	(revision 216)
@@ -0,0 +1,133 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "jointhinge2.h"
+
+namespace ODEManaged
+{
+	//Constructors
+	JointHinge2::JointHinge2(void) : Joint(){}
+
+	JointHinge2::JointHinge2(World &world)
+	{
+		if(this->_id) dJointDestroy(this->_id);
+		_id = dJointCreateHinge2(world.Id(),0);
+	}
+	
+	JointHinge2::JointHinge2(World &world, JointGroup &jointGroup)
+	{
+		if(this->_id) dJointDestroy(this->_id);
+		_id = dJointCreateHinge2(world.Id(), jointGroup.Id());
+	}
+
+	//Destructor
+	JointHinge2::~JointHinge2(void){}
+
+	//CreateHinge2 (overload 1)
+	void JointHinge2::Create(World &world, JointGroup &jointGroup)
+	{
+		if(this->_id) dJointDestroy(this->_id);
+		_id = dJointCreateHinge2(world.Id(), jointGroup.Id());
+	}
+
+	//CreateHinge2 (overload 2)
+	void JointHinge2::Create(World &world)
+	{
+		if(this->_id) dJointDestroy(this->_id);
+		_id = dJointCreateHinge2(world.Id(),0);
+	}
+
+	//SetAnchor1
+	void JointHinge2::SetAnchor (double x, double y ,double z)
+	{
+		dJointSetHinge2Anchor(_id, x,y,z);
+	}
+
+	//GetAnchor1
+	Vector3 JointHinge2::GetAnchor()
+	{
+		Vector3 retVal;
+		dVector3 temp;
+		dJointGetHinge2Anchor(_id,temp);
+		retVal.x = temp[0];
+		retVal.y = temp[1];
+		retVal.z = temp[2];
+		return retVal;
+	}
+
+	//SetAxis1
+	void JointHinge2::SetAxis1 (double x, double y ,double z)
+	{
+		dJointSetHinge2Axis1(_id, x,y,z);
+	}
+
+	//GetAxis1
+	Vector3 JointHinge2::GetAxis1()
+	{
+		Vector3 retVal;
+		dVector3 temp;
+		dJointGetHinge2Axis1(_id,temp);
+		retVal.x = temp[0];
+		retVal.y = temp[1];
+		retVal.z = temp[2];
+		return retVal;
+	}
+
+	//SetAxis2
+	void JointHinge2::SetAxis2 (double x, double y ,double z)
+	{
+		dJointSetHinge2Axis2(_id, x,y,z);
+	}
+
+	//GetAxis2
+	Vector3 JointHinge2::GetAxis2()
+	{
+		Vector3 retVal;
+		dVector3 temp;
+		dJointGetHinge2Axis2(_id,temp);
+		retVal.x = temp[0];
+		retVal.y = temp[1];
+		retVal.z = temp[2];
+		return retVal;
+	}
+
+	//GetAngle1
+	double JointHinge2::GetAngle1 ()
+	{
+		return dJointGetHinge2Angle1(this->_id);
+	}
+
+	//GetAngle1Rate
+	double JointHinge2::GetAngle1Rate ()
+	{
+		return dJointGetHinge2Angle1Rate(this->_id);
+	}
+
+	////GetAngle hmm, this doesn't exist
+	//double JointHinge2::GetAngle2 ()
+	//{
+	//	return dJointGetHinge2Angle2(this->_id);
+	//}
+
+	//GetAngle2Rate
+	double JointHinge2::GetAngle2Rate ()
+	{
+		return dJointGetHinge2Angle2Rate(this->_id);
+	}
+
+
+	//Attach (overload 1)
+	void JointHinge2::Attach (Body &body1, Body &body2)
+	{
+		dJointAttach(_id, body1.Id(),body2.Id());
+	}
+
+	//Attach (overload 2) 
+	//TODO: possibly add an overload that takes anchor as a param also.
+	void JointHinge2::Attach (Body &body1)
+	{
+		dJointAttach(_id, body1.Id(),0);
+	}
+
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge2.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge2.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointHinge2.h	(revision 216)
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "Joint.h"
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{
+	__gc public class JointHinge2 : public Joint
+	{
+		public:
+
+
+		//Constructors
+
+			JointHinge2				(void);
+			JointHinge2				(World &world);
+			JointHinge2				(World &world, JointGroup &jointGroup);
+			
+		//Destructors
+
+			virtual ~JointHinge2	(void);
+			
+
+		//Methods
+
+			//Overloaded Hinge.Create
+			void	Create			(World &world, JointGroup &jointGroup);
+			void	Create			(World &world);
+			
+			void	SetAnchor		(double x, double y, double z);
+			Vector3 GetAnchor		(void);
+
+			void	SetAxis1		(double x, double y, double z);
+			Vector3 GetAxis1		(void);
+
+			void	SetAxis2		(double x, double y, double z);
+			Vector3 GetAxis2		(void);
+
+			double	GetAngle1		(void);
+			double	GetAngle1Rate	(void);
+
+			//double GetAngle2 (void);
+			double	GetAngle2Rate	(void);
+
+			void	Attach			(Body &body1, Body &body2);	
+			void	Attach(			Body &body1);
+	};
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointSlider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointSlider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointSlider.cpp	(revision 216)
@@ -0,0 +1,102 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "jointslider.h"
+
+namespace ODEManaged
+{
+	
+	//Constructors
+	
+		JointSlider::JointSlider(void) : Joint(){}
+
+
+		JointSlider::JointSlider(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateSlider(world.Id(), 0);
+		}
+
+
+		JointSlider::JointSlider(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateSlider(world.Id(), jointGroup.Id());
+		}
+
+
+	//Destructor
+
+		JointSlider::~JointSlider(void){}
+
+
+	//Methods
+
+		//Overloaded Create
+		void JointSlider::Create(World &world, JointGroup &jointGroup)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateSlider(world.Id(), jointGroup.Id());
+		}
+
+		void JointSlider::Create(World &world)
+		{
+			if(this->_id) dJointDestroy(this->_id);
+			_id = dJointCreateSlider(world.Id(), 0);
+		}
+
+		
+		//Overloaded Attach 
+		void JointSlider::Attach(Body &body1, Body &body2)
+		{
+			dJointAttach(this->_id, body1.Id(), body2.Id());
+		}
+
+		void JointSlider::Attach(Body &body1)
+		{
+			dJointAttach(this->_id, body1.Id(), 0);
+		}
+
+
+		//SetAxis
+		void JointSlider::SetAxis(double x, double y, double z)
+		{
+			dJointSetSliderAxis(this->_id, x, y, z);
+		}
+
+		//GetAxis
+		Vector3 JointSlider::GetAxis(void)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dJointGetSliderAxis(this->_id, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+
+	//Movement Parameters
+
+		//SetAllMovParams
+		void JointSlider::SetAllMovParams(double LoStop, double HiStop,
+										  double Velocity, double MaxForce,
+										  double FudgeFactor, double Bounce,
+										  double StopERP, double StopCFM)
+		{
+			if (LoStop <= 0) 
+				dJointSetHingeParam(this->_id, dParamLoStop, LoStop);
+
+			if (HiStop >= 0)
+				dJointSetHingeParam(this->_id, dParamHiStop, HiStop);
+
+			dJointSetSliderParam(this->_id, dParamVel, Velocity);
+			dJointSetSliderParam(this->_id, dParamFMax, MaxForce);
+			dJointSetSliderParam(this->_id, dParamFudgeFactor, FudgeFactor);
+			dJointSetSliderParam(this->_id, dParamBounce, Bounce);
+			dJointSetSliderParam(this->_id, dParamStopERP, StopERP);
+			dJointSetSliderParam(this->_id, dParamStopCFM, StopCFM);
+		}
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointSlider.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointSlider.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/JointSlider.h	(revision 216)
@@ -0,0 +1,158 @@
+#pragma once
+
+#include "Joint.h"
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{
+	__gc public class JointSlider : public Joint
+	{
+	public:
+			
+		
+		//Constructors
+
+			JointSlider(void);
+			JointSlider(World &world);
+			JointSlider(World &world, JointGroup &jointGroup);
+			
+
+		//Destructors
+
+			virtual ~JointSlider(void);
+
+			
+		//Methods	
+			
+			//Overloaded Create
+			void Create(World &world, JointGroup &jointGroup);
+			void Create(World &world);
+			
+			//Overloaded Attach
+			void Attach(Body &body1, Body &body2);	
+			void Attach(Body &body1);
+			
+			void SetAxis(double x, double y, double z);
+			Vector3 GetAxis(void);
+
+			void SetAllMovParams(double LoStop, double HiStop,
+								 double Velocity, double MaxForce,
+								 double FudgeFactor, double Bounce,
+								 double StopERP, double StopCFM);
+
+
+		//Properties
+
+			//LoStop
+			__property double get_LoStop(void)
+				{
+					return dJointGetSliderParam(this->_id, dParamLoStop);
+				}
+
+			__property void	set_LoStop(double value)
+			{
+				if (value <=0)
+					dJointSetSliderParam(this->_id, dParamLoStop, value);
+			}
+
+
+			//HiStop
+			__property double get_HiStop(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamHiStop);
+			}
+
+			__property void set_HiStop(double value)
+			{
+				if (value >= 0)
+					dJointSetSliderParam(this->_id, dParamHiStop, value);
+			}
+			
+
+			//Velocity
+			__property double get_Velocity(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamVel);
+			}
+
+			__property void set_Velocity(double value)
+			{
+				dJointSetSliderParam(this->_id, dParamVel, value);
+			}
+
+
+			//MaxForce
+			__property double get_MaxForce(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamFMax);
+			}
+
+			__property void set_MaxForce(double value)
+			{
+				dJointSetSliderParam(this->_id, dParamFMax, value);
+			}
+
+
+			//FudgeFactor
+			__property double get_FudgeFactor(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamFudgeFactor);
+			}
+
+			__property void set_FudgeFactor(double value)
+			{
+				dJointSetSliderParam(this->_id, dParamFudgeFactor, value);
+			}
+
+
+			//Bounce
+			__property double get_Bounce(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamBounce);
+			}
+
+			__property void set_Bounce(double value)
+			{
+				dJointSetSliderParam(this->_id, dParamBounce, value);
+			}
+
+
+			//StopERP
+			__property double get_StopERP(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamStopERP);
+			}
+
+			__property void set_StopERP(double value)
+			{
+				dJointSetSliderParam(this->_id, dParamStopERP, value);
+			}
+
+
+			//StopCFM
+			__property double get_StopCFM(void)
+			{
+				return dJointGetSliderParam(this->_id, dParamStopCFM);
+			}
+
+			__property void set_StopCFM(double value)
+			{
+				dJointSetSliderParam(this->_id, dParamStopCFM, value);
+			}
+
+
+			//GetAngle
+			__property double get_Position(void)
+			{
+				return dJointGetSliderPosition(this->_id);
+			}
+
+
+			//GetAngleRate
+			__property double get_PositionRate(void)
+			{
+				return dJointGetSliderPositionRate(this->_id);
+			}
+
+	};
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Space.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Space.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Space.cpp	(revision 216)
@@ -0,0 +1,53 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "Space.h"
+#include "TEST.h"
+
+namespace ODEManaged
+{
+
+	//Constructor
+
+		Space::Space(void)
+		{ 
+			_id = dSimpleSpaceCreate();
+		}
+
+		Space::Space(int minlevel, int maxlevel)
+		{ 
+			_id = dHashSpaceCreate();
+			dHashSpaceSetLevels(this->_id, minlevel, maxlevel);
+		}
+
+	
+	//Destructor
+
+		Space::~Space(void)
+		{
+			dSpaceDestroy(this->_id);
+		}
+
+
+	//Methods
+
+		//Id
+		dSpaceID Space::Id()
+		{
+			return _id;
+		}
+
+
+		//Collide
+		void Space::Collide(void *data, dNearCallback *callback)
+		{		
+			dSpaceCollide(this->_id, data, callback);
+		}
+
+
+
+
+
+
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Space.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Space.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Space.h	(revision 216)
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{
+	__gc public class Space
+	{
+	public:
+
+		//Constructor
+			
+			Space(void);
+			Space(int minlevel, int maxlevel);
+			
+		//Destructor
+			
+			~Space(void);
+
+
+		//Methods
+
+			dSpaceID Id(void);
+			void Collide(void *data, dNearCallback *callback);
+
+
+		private:
+			
+			dSpaceID _id;
+
+	};
+
+}
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Stdafx.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Stdafx.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Stdafx.cpp	(revision 216)
@@ -0,0 +1,5 @@
+// stdafx.cpp : source file that includes just the standard includes
+// ODEManaged.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/Stdafx.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/Stdafx.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/Stdafx.h	(revision 216)
@@ -0,0 +1,12 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#using <mscorlib.dll>
+
+
+
+
+
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/TEST.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/TEST.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/TEST.h	(revision 216)
@@ -0,0 +1,17 @@
+		
+#pragma once
+
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{	
+		
+void RnearCallback(void *data, dGeomID o1, dGeomID o2)
+		{
+		}
+
+}
+
+
+
+
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/World.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/World.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/World.cpp	(revision 216)
@@ -0,0 +1,74 @@
+#include "StdAfx.h"
+
+#include <ode/ode.h>
+#include "World.h"
+
+namespace ODEManaged
+{
+	
+	//Constructor
+	
+		World::World(void)
+		{
+			/*dWorldID _temp = dWorldCreate();
+			_id = _temp;*/ 
+			_id = dWorldCreate();
+		}
+
+
+	//Destructor
+
+		World::~World(void)
+		{
+			dWorldDestroy(this->_id);
+		}
+
+
+	//Methods
+
+		//Id
+		dWorldID World::Id()
+		{
+			return _id;
+		}
+
+
+		//SetGravity
+		void World::SetGravity(double x, double y, double z)
+		{ 
+			dWorldSetGravity(this->_id, x, y, z); 
+		}
+
+
+		//Overloaded GetGravity
+		Vector3 World::GetGravity(void)
+		{
+			Vector3 retVal;
+			dVector3 temp;
+			dWorldGetGravity(this->_id, temp);
+			retVal.x = temp[0];
+			retVal.y = temp[1];
+			retVal.z = temp[2];
+			return retVal;
+		}
+
+		void World::GetGravity(double gravity __gc[])
+		{
+			dVector3 temp;
+			dWorldGetGravity(this->_id, temp);
+			gravity[0] = temp[0];
+			gravity[1] = temp[1];
+			gravity[2] = temp[2];
+		}
+
+
+		//Step
+		void World::Step(double stepSize)
+		{
+			dWorldStep(this->_id, stepSize);
+		}
+
+}
+
+
+
Index: /code/branches/ode/ode-0.9/contrib/DotNetManaged/World.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/DotNetManaged/World.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/DotNetManaged/World.h	(revision 216)
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "CommonMgd.h"
+
+namespace ODEManaged
+{	
+	__gc public class World
+	{	
+	public:
+
+		//Constructor
+		
+			World(void);
+
+
+		//Destructor
+			
+			~World(void);
+
+			
+		// Methods
+
+			dWorldID Id(void);
+			
+			void SetGravity(double x, double y, double z);
+
+			//Overloaded GetGravity
+			Vector3 GetGravity(void);		
+			void GetGravity(double gravity __gc[]);
+
+			void Step(double stepSize);
+
+
+		//Properties
+
+			//Constraint Force Mixing
+			__property void set_CFM(double cfm)
+			{
+				dWorldSetCFM(this->_id,cfm);
+			}
+
+			__property double get_CFM(void)
+			{
+				return dWorldGetCFM(this->_id); 
+			}
+
+
+			//Error Reduction Parameter
+			__property void set_ERP(double erp)
+			{
+				dWorldSetERP(this->_id,erp);
+			}
+
+			__property double get_ERP(void)
+			{
+				return dWorldGetERP(this->_id); 
+			}
+
+
+		private:
+
+			dWorldID _id;
+
+	};
+
+}
+
Index: /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.cpp	(revision 216)
@@ -0,0 +1,218 @@
+
+/* ************************************************************************ */
+/* 
+   grouped and transformed geometry functions 
+   author: Tim Schmidt tisch@uni-paderborn.de
+*/
+
+
+#include <ode/common.h>
+#include <ode/geom.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include <ode/memory.h>
+#include <ode/misc.h>
+#include <ode/objects.h>
+#include <ode/matrix.h>
+#include <ode/GeomTransformGroup.h>
+#include "objects.h"
+#include "array.h"
+#include "geom_internal.h"
+
+// given a pointer `p' to a dContactGeom, return the dContactGeom at
+// p + skip bytes.
+
+#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
+
+
+// ############################################################################
+
+int dGeomTransformGroupClass = -1;
+// ############################################################################
+
+struct dxGeomTransformGroup {
+  dArray<dxGeom*> parts;	// all the geoms that make up the group
+  dVector3 relativePosition;
+  dMatrix3 relativeRotation;
+};
+// ############################################################################
+
+void dGeomTransformGroupSetRelativePosition (dxGeom *g, dReal x, dReal y, dReal z)
+{
+  dAASSERT (g);
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  transformGroup->relativePosition[0] = x;
+  transformGroup->relativePosition[1] = y;
+  transformGroup->relativePosition[2] = z;
+}
+// ############################################################################
+
+void dGeomTransformGroupSetRelativeRotation (dxGeom *g, const dMatrix3 R)
+{
+  dAASSERT (g);
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  memcpy (transformGroup->relativeRotation,R,sizeof(dMatrix3));
+}
+// ############################################################################
+
+const dReal * dGeomTransformGroupGetRelativePosition (dxGeom *g)
+{
+  dAASSERT (g);
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  return transformGroup->relativePosition;
+}
+// ############################################################################
+
+const dReal * dGeomTransformGroupGetRelativeRotation (dxGeom *g)
+{
+  dAASSERT (g);
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  return transformGroup->relativeRotation;
+}
+// ############################################################################
+
+static void computeFinalTransformation (const dxGeom *tg, const dxGeom *part)
+{
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(tg);
+  dMULTIPLY0_331 (part->pos,tg->R,transformGroup->relativePosition);
+  part->pos[0] += tg->pos[0];
+  part->pos[1] += tg->pos[1];
+  part->pos[2] += tg->pos[2];
+  dMULTIPLY0_333 (part->R,tg->R,transformGroup->relativeRotation);
+}
+// ############################################################################
+
+int dCollideTransformGroup (const dxGeom *o1, const dxGeom *o2, int flags,
+	       dContactGeom *contact, int skip)
+{
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(o1);
+  if (transformGroup->parts.size() == 0)
+  {
+    return 0;
+  }
+  int numleft = flags & NUMC_MASK;
+  if (numleft == 0) numleft = 1;
+  flags &= ~NUMC_MASK;
+  int num=0, i=0;
+  while (i < transformGroup->parts.size() && numleft > 0) 
+  {
+    dUASSERT (transformGroup->parts[i]->spaceid==0,
+	      "GeomTransformGroup encapsulated object must not be in a space");
+    dUASSERT (transformGroup->parts[i]->body==0,
+	      "GeomTransformGroup encapsulated object must not be attached to a body");
+    if (!o1->space_aabb) 
+    {
+      computeFinalTransformation (o1, transformGroup->parts[i]);
+    }
+    dxBody *bodyBackup = transformGroup->parts[i]->body;
+    transformGroup->parts[i]->body = o1->body;
+    int n = dCollide (transformGroup->parts[i],const_cast<dxGeom*>(o2),
+		      flags | numleft,contact,skip);
+    transformGroup->parts[i]->body = bodyBackup;
+    contact = CONTACT (contact,skip*n);
+    numleft -= n;
+    num += n;
+    i++;
+  }
+  return num;
+}
+// ############################################################################
+
+static dColliderFn * dGeomTransformGroupColliderFn (int num)
+{
+  return (dColliderFn *) &dCollideTransformGroup;
+}
+// ############################################################################
+
+static void dGeomTransformGroupAABB (dxGeom *geom, dReal aabb[6])
+{
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(geom);
+  aabb[0] = dInfinity;
+  aabb[1] = -dInfinity;
+  aabb[2] = dInfinity;
+  aabb[3] = -dInfinity;
+  aabb[4] = dInfinity;
+  aabb[5] = -dInfinity;
+  int i,j;
+  for (i=0; i < transformGroup->parts.size(); i++)
+  {
+    computeFinalTransformation (geom, transformGroup->parts[i]);
+    dReal aabb2[6];
+    transformGroup->parts[i]->_class->aabb (transformGroup->parts[i],aabb2);
+    for (j=0; j<6; j += 2) if (aabb2[j] < aabb[j]) aabb[j] = aabb2[j];
+    for (j=1; j<6; j += 2) if (aabb2[j] > aabb[j]) aabb[j] = aabb2[j];
+  }
+}
+// ############################################################################
+
+static void dGeomTransformGroupDtor (dxGeom *geom)
+{
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(geom);
+  transformGroup->parts.~dArray();
+}
+// ############################################################################
+
+dxGeom *dCreateGeomTransformGroup (dSpaceID space)
+{
+  if (dGeomTransformGroupClass == -1) {
+    dGeomClass c;
+    c.bytes = sizeof (dxGeomTransformGroup);
+    c.collider = &dGeomTransformGroupColliderFn;
+    c.aabb = &dGeomTransformGroupAABB;
+    c.aabb_test = 0;
+    c.dtor = dGeomTransformGroupDtor;
+    dGeomTransformGroupClass = dCreateGeomClass (&c);
+  }
+  dxGeom *g = dCreateGeom (dGeomTransformGroupClass);
+  if (space)
+  {
+    dSpaceAdd (space,g);
+  }
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  transformGroup->parts.constructor();
+  dSetZero (transformGroup->relativePosition,4);
+  dRSetIdentity (transformGroup->relativeRotation);
+  return g;
+}
+// ############################################################################
+
+void dGeomTransformGroupAddGeom (dxGeom *g, dxGeom *obj)
+{
+  dUASSERT (g && g->_class->num == dGeomTransformGroupClass,
+	    "argument not a geom TransformGroup");
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  transformGroup->parts.push (obj);
+}
+// ############################################################################
+
+void dGeomTransformGroupRemoveGeom (dxGeom *g, dxGeom *obj)
+{
+  dUASSERT (g && g->_class->num == dGeomTransformGroupClass,
+	    "argument not a geom TransformGroup");
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  for (int i=0; i < transformGroup->parts.size(); i++) {
+    if (transformGroup->parts[i] == obj) {
+      transformGroup->parts.remove (i);
+      return;
+    }
+  }
+}
+// ############################################################################
+
+dxGeom * dGeomTransformGroupGetGeom (dxGeom *g, int i)
+{
+  dUASSERT (g && g->_class->num == dGeomTransformGroupClass,
+	    "argument not a geom TransformGroup");
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  dAASSERT (i >= 0 && i < transformGroup->parts.size());
+  return transformGroup->parts[i];
+}
+// ############################################################################
+
+int dGeomTransformGroupGetNumGeoms (dxGeom *g)
+{
+  dUASSERT (g && g->_class->num == dGeomTransformGroupClass,
+	    "argument not a geom TransformGroup");
+  dxGeomTransformGroup *transformGroup = (dxGeomTransformGroup*) CLASSDATA(g);
+  return transformGroup->parts.size();
+}
Index: /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/GeomTransformGroup.h	(revision 216)
@@ -0,0 +1,29 @@
+ 
+/* ************************************************************************ */
+/* 
+   grouped and transformed geometry functions 
+   author: Tim Schmidt tisch@uni-paderborn.de
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern int dGeomTransformGroupClass;
+
+void dGeomTransformGroupSetRelativePosition (dGeomID g, dReal x, dReal y, dReal z);
+void dGeomTransformGroupSetRelativeRotation (dGeomID g, const dMatrix3 R);
+const dReal * dGeomTransformGroupGetRelativePosition (dxGeom *g);
+const dReal * dGeomTransformGroupGetRelativeRotation (dxGeom *g);
+dGeomID dCreateGeomTransformGroup (dSpaceID space);
+void dGeomTransformGroupAddGeom    (dGeomID tg, dGeomID obj);
+void dGeomTransformGroupRemoveGeom (dGeomID tg, dGeomID obj);
+dGeomID dGeomTransformGroupGetGeom (dGeomID tg, int i);
+int dGeomTransformGroupGetNumGeoms (dGeomID tg);
+
+
+#ifdef __cplusplus
+}
+#endif
Index: /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/README.txt
===================================================================
--- /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/README.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/GeomTransformGroup/README.txt	(revision 216)
@@ -0,0 +1,148 @@
+README for GeomTransformGroup by Tim Schmidt.
+---------------------------------------------
+
+This is a patch to add the dGeomTransformGroup object to the list of geometry 
+objects.
+
+It should work with the cvs version of the ode library from 07/24/2002.
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+comment by russ smith: this code is easy to use with the rest of ODE.
+simply copy GeomTransformGroup.cpp to ode/src and copy GeomTransformGroup.h
+to include/ode. then add GeomTransformGroup.cpp to the ODE_SRC variable
+in the makefile. rebuild, and you're done! of course i could have done all
+this for you, but i prefer to keep GeomTransformGroup separated from the
+rest of ODE for now while other issues with the collision system are
+resolved.
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+Description:
+
+The dGeomTransformGroup is an adaption of the TransformGroup known from 
+Java3D (and maybe other libraries with a similar scene graph representation).
+It can be used to build an arbitrarily structured tree of objects that are 
+each positioned relative to the particular parent node.
+
+If you have a plane for example, there is one root node associated with the 
+plane's body and another three transformgroups placed 'under' this node. One 
+with the fuselage (cappedcylinder) under it and two with the underlying wings 
+(flat boxes). And if you want to add engines, simply put them 'next to' the 
+wings under another two transformgroups.
+
+bodyTG ---> associated with dBody
+    |
+    +--fuselageTG
+    |   |
+    |   +--fuselageCylinder
+    |
+    +--leftwingTG
+    |   |
+    |   +--wingBox
+    |   |
+    |   +--leftengineTG
+    |         |
+    |         +--leftengineCylinder
+    | 
+    +--rightwingTG
+        |
+        +--wingBox
+        |
+        +--rightengineTG
+              |
+              +--rightengineCylinder
+
+This is a method to easily compose objects without the necessity of always 
+calculating global coordinates. But apart from this there is something else 
+that makes dGeomTransformGroups very valuable.
+
+Maybe you remember that some users reported the problem of acquiring the 
+correct bodies to be attached by a contactjoint in the nearCallback when 
+using dGeomGroups and dGeomTransforms at the same time. This results from the 
+fact that dGeomGroups are not associated with bodies while all other 
+geometries are.
+
+So, as you can see in the nearCallback of the the test_buggy demo you have to 
+attach the contactjoint with the bodies that you get from the geometries that 
+are stored in the contact struct (-> dGeomGetBody(contacts[i].geom.g1)). 
+Normally you would do this by asking o1 and o2 directly with dGeomGetBody(o1) 
+and dGeomGetBody(o2) respectively.
+
+As a first approach you can overcome that problem by testing o1 and o2 if 
+they are groups or not to find out how to get the corresponding bodies.
+
+However this will fail if you want grouped transforms that are constructed 
+out of dGeomTransforms encapsulated in a dGeomGroup. According to the test 
+you use contacts[i].geom.g1 to get the right body. Unfortunately g1 is 
+encapsulated in a transform and therefore not attached to any body. In this 
+case the dGeomTransform 'in the middle' would have been the right object to 
+be asked for the body.
+
+You may now conclude that it is a good idea to unwrap the group encapsulated 
+geoms at the beginning of the nearcallback and use dGeomGetBody(o1) 
+consistently. But keep in mind that this also means not to invoke 
+dCollide(..) on groups at all and therefore not to expoit the capability of 
+dGeomGroups to speed up collision detection by the creation of bounding boxes 
+around the encapsulated geometry.
+
+Everything becomes even worse if you create a dGeomTransform that contains a 
+dGeomGroup of geoms. The function that cares about the collision of 
+transforms with other objects uses the position and rotation of the 
+respective encapsulated object to compute its final position and orientation. 
+Unfortunately dGeomGroups do not have a position and rotation, so the result 
+will not be what you have expected.
+
+Here the dGeomTransformGroups comes into operation, because it combines the 
+advantages and capabilities of the dGeomGroup and the dGeomTransform.
+And as an effect of synergy it is now even possible to set the position of a 
+group of geoms with one single command.
+Even nested encapsulations of dGeomTransformGroups in dGeomTransformGroups 
+should be possible (to be honest, I have not tried that so far ;-) ).
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+API:
+
+dGeomID dCreateGeomTransformGroup (dSpaceID space);
+  - create a GeomTransformGroup 
+    
+void dGeomTransformGroupAddGeom    (dGeomID tg, dGeomID obj);
+  - Comparable to dGeomTransformSetGeom or dGeomGroupAdd
+  - add objects to this group
+   
+void dGeomTransformGroupRemoveGeom (dGeomID tg, dGeomID obj);
+  - remove objects from this group
+
+void dGeomTransformGroupSetRelativePosition
+            (dGeomID g, dReal x, dReal y, dReal z);
+void dGeomTransformGroupSetRelativeRotation
+            (dGeomID g, const dMatrix3 R);
+  - Comparable to setting the position and rotation of all the
+    dGeomTransform encapsulated geometry. The difference 
+    is that it is global with respect to this group and therefore
+    affects all geoms in this group.
+  - The relative position and rotation are attributes of the 
+    transformgroup, so the position and rotation of the individual
+    geoms are not changed 
+
+const dReal * dGeomTransformGroupGetRelativePosition (dGeomID g);
+const dReal * dGeomTransformGroupGetRelativeRotation (dGeomID g);
+  - get the relative position and rotation
+  
+dGeomID dGeomTransformGroupGetGeom (dGeomID tg, int i);
+  - Comparable to dGeomGroupGetGeom
+  - get a specific geom of the group
+  
+int dGeomTransformGroupGetNumGeoms (dGeomID tg);
+  - Comparable to dGeomGroupGetNumGeoms
+  - get the number of geoms in the group
+  
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Tim Schmidt
+student of computer science
+University of Paderborn, Germany
+tisch@uni-paderborn.de
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/README.txt
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/README.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/README.txt	(revision 216)
@@ -0,0 +1,95 @@
+-----------------------------
+ODE - Mac CFM Carbon Port
+(contact Frank Condello <pox@planetquake.com> with questions regarding this port)
+
+Although ODE contains a MacOSX makefile, and some individuals have implemented ODE in
+Cocoa, I opted to use (and prefer) CodeWarrior. This also opens up ODE to MacOS8 & 9
+users, without scarfing functionality in MacOSX (same binaries run on both platforms).
+
+The 'ode_CW7.mcp' project contains release and debug targets to create static ODE and
+DrawStuff libraries.
+
+'examples_CW7.mcp' contains targets for the entire ODE test suite, plus a couple other
+test programs which were posted to the ODE mailing list.
+
+
+-----------------------------
+Compiling Notes:
+
+You'll need to extract the CodeWarrior projects from the 'CW7_projects.sit.bin' archive
+(They're nearly a meg uncompressed so this was done to be bandwith friendly on the CVS).
+
+Projects require CodeWarrior 7 or above (recreating them with earlier versions shouldn't
+be too difficult). The projects use relative paths and are meant to be compiled from
+'contrib/Mac_CFMCarbon/'. Don't move them!
+
+All the libraries build into the 'lib/' directory, all test applications build into
+'contrib/Mac_CFMCarbon/mac_testbin/' (and must be run from that directory since the
+texture path is hard-coded).
+
+You'll need to compile the release ODE library, and the DrawStuff library before
+compiling the examples.
+
+The ODE 'configurator' has not been ported, but a Mac-friendly 'config.h' header has been
+manually hacked together (all PPC Macs should be fine with this header). Single or double
+precision can be defined in the 'CommonPrefix.h' header found in
+'contrib/Mac_CFMCarbon/mac_source/'.
+
+'contrib/Mac_CFMCarbon/mac_source/' also contains any mac specific additions to the main source.
+The directory structure here matches the main source tree, and I would recommend that this
+format is maintained when making additions, since the access paths are touchy (more below...)
+
+Some issues were encountered with duplicate header names. CodeWarrior tends to be
+unforgiving about this sort of thing but fudging with the access paths eventually
+cleared up the problem. If ODE fails to compile, make sure the <ode/objects.h> and
+"objects.h" or <timer.h> and <Timer.h> are actually pointing to the correct header.
+
+You'll need Apple's OpenGL SDK (with GLUT) in your compiler path to build DrawStuff. I've
+added redirection headers in 'contrib/Mac_CFMCarbon/mac_source/include/GL/' to properly
+link with the Apple headers (since the projects are set to follow DOS paths).
+
+The examples link against a crapload of static libraries, but my initial builds using
+ODE, MSL, GLUT, and DrawStuff shared/merged DLL's proved unstable (mostly problems with
+SIOUX spawning multiple sessions, and crashes in Classic). Static libs just worked better
+in the end, but the test apps are a little bloated as a result, and need to be re-linked
+whenever a change to a library is made.
+
+IMPORTANT: You must use the same 'CommonPrefix.h' settings for libraries, and test apps
+(i.e. double or single precision).
+
+
+-----------------------------
+Running the test apps:
+
+The test apps will show the SIOUX CLI prompt when run. Just hit OK to ignore it, or add any
+DrawStuff arguments. You'll want to log output to a file for 'test_ode'.
+
+There are two extra test programs in the 'mac_source' directory. Both were posted to the ODE
+mailing list by OSX users. 'test_stability1' visualizes some internal issues with ODE, and
+'test_stacktest' is a standalone GLUT program (doesn't use DrawStuff) that can be useful
+to stress test the library, and give you an idea of just how much stack memory you're
+going to need for large systems.
+
+ISSUES:
+
+The carbon DrawStuff lib uses GLUT to make life easy, but GLUT isn't exactly bug-free
+or stable on the Mac... Try moving the mouse around if a simulation is running slowly
+on OS9 (it's not ODE's fault, but rather a poor carbon GLUT implementation - seems GLUT stalls
+when it's not getting system events  - I haven't seen this problem on OSX).
+
+The 3D view may not update if typing in the SIOUX console window.
+
+You cannot pass startup args to GLUT due to the way the DrawStuff library initializes.
+
+'Write Frames' doesn't actually do anything at the moment.
+
+The 'test_joints' app seems broken (though I don't know what the intended effect should be)
+
+
+-----------------------------
+TODO:
+
+- Re-add shared library targets (if stability issues are resolved).
+- Implement 'Write Frames' in DrawStuff.
+- Write a Carbon compatible configurator
+- Create CodeWarrior 8 projects (once I scrounge up enough dough for the update).
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/CommonPrefix.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/CommonPrefix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/CommonPrefix.h	(revision 216)
@@ -0,0 +1,6 @@
+#define TARGET_API_MAC_CARBON 1
+#define finite isfinite
+#define dNODEBUG 1
+
+// Comment out for single precision
+#define PRECISION_DOUBLE 1
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DSPrefix.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DSPrefix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DSPrefix.h	(revision 216)
@@ -0,0 +1,6 @@
+#ifndef prefix_h
+#define prefix_h
+
+#include "CommonPrefix.h"
+
+#endif // prefix_h
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DebugPrefix.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DebugPrefix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/DebugPrefix.h	(revision 216)
@@ -0,0 +1,10 @@
+#ifndef prefix_h
+#define prefix_h
+
+#include "CommonPrefix.h"
+
+#ifdef dNODEBUG
+#undef dNODEBUG
+#endif
+
+#endif // prefix_h
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ExamplesPrefix.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ExamplesPrefix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ExamplesPrefix.h	(revision 216)
@@ -0,0 +1,13 @@
+#ifndef prefix_h
+#define prefix_h
+
+#include "CommonPrefix.h"
+
+// Hack to automatically call SIOUX's CLI interface for the test apps
+#include <console.h>
+#include <SIOUX.h>
+int fmain (int argc, char **argv);
+int main (int argc, char **argv) { argc = ccommand(&argv); return fmain(argc, argv); }
+#define main(argc, argv) fmain(argc, argv)
+
+#endif // prefix_h
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ODETestPrefix.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ODETestPrefix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ODETestPrefix.h	(revision 216)
@@ -0,0 +1,13 @@
+#ifndef prefix_h
+#define prefix_h
+
+#include "CommonPrefix.h"
+
+// Hack to automatically call SIOUX's CLI interface for the test apps
+#include <console.h>
+#include <SIOUX.h>
+int fmain ();
+int main (int argc, char **argv) { argc = ccommand(&argv); return fmain(); }
+#define main() fmain()
+
+#endif // prefix_h
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ReleasePrefix.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ReleasePrefix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ReleasePrefix.h	(revision 216)
@@ -0,0 +1,6 @@
+#ifndef prefix_h
+#define prefix_h
+
+#include "CommonPrefix.h"
+
+#endif // prefix_h
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/drawstuff/src/mac_glut_carbon.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/drawstuff/src/mac_glut_carbon.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/drawstuff/src/mac_glut_carbon.cpp	(revision 216)
@@ -0,0 +1,281 @@
+/*************************************************************************
+ *                                                                       *
+ * DrawStuff Library, Copyright (C) 2001 Russell L. Smith.               *
+ *   Email: russ@q12.org   Web: www.q12.org                              *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of the GNU Lesser General Public            *
+ * License as published by the Free Software Foundation; either          *
+ * version 2.1 of the License, or (at your option) any later version.    *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ * Lesser General Public License for more details.                       *
+ *                                                                       *
+ * You should have received a copy of the GNU Lesser General Public      *
+ * License along with this library (see the file LICENSE.TXT); if not,   *
+ * write to the Free Software Foundation, Inc., 59 Temple Place,         *
+ * Suite 330, Boston, MA 02111-1307 USA.                                 *
+ *                                                                       *
+ *************************************************************************/
+
+// main window and event handling for Mac CFM Carbon
+
+#include <ode/config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <glut.h>
+#include <SIOUX.h>
+
+#include <MacTypes.h>
+#include <Timer.h>
+
+#include <drawstuff/drawstuff.h>
+#include <drawstuff/version.h>
+#include "internal.h"
+
+
+//***************************************************************************
+// error handling for unix (works just fine with SIOUX)
+
+static void printMessage (char *msg1, char *msg2, va_list ap)
+{
+  fflush (stderr);
+  fflush (stdout);
+  fprintf (stderr,"\n%s: ",msg1);
+  vfprintf (stderr,msg2,ap);
+  fprintf (stderr,"\n");
+  fflush (stderr);
+}
+
+extern "C" void dsError (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  printMessage ("Error",msg,ap);
+  exit (1);
+}
+
+
+extern "C" void dsDebug (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  printMessage ("INTERNAL ERROR",msg,ap);
+  // *((char *)0) = 0;	 ... commit SEGVicide ?
+  abort();
+}
+
+extern "C" void dsPrint (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  vprintf (msg,ap);
+}
+
+//***************************************************************************
+// openGL window
+
+// window and openGL
+static int width=0,height=0;		// window size
+static int last_key_pressed=0;		// last key pressed in the window
+static int pause=0;					// 1 if in `pause' mode
+static int singlestep=0;			// 1 if single step key pressed
+static int writeframes=0;			// 1 if frame files to be written
+static dsFunctions *gfn;
+static int frame = 1;
+
+float getTime (void)
+{
+	UnsignedWide ms;
+	
+	Microseconds(&ms);
+	return ms.lo / 1000000.0;
+}
+
+
+static void captureFrame (int num)
+{
+// TODO
+}
+
+static void reshape(int w, int h)
+{
+	width = w;
+	height = h;
+}
+
+static void draw(void)
+{
+	dsDrawFrame (width,height,gfn,pause && !singlestep);
+	singlestep = 0;
+	glutSwapBuffers();
+	
+	if (pause==0 && writeframes) {
+      captureFrame (frame);
+      frame++;
+    }
+}
+
+static void idle(void)
+{
+	static float lasttime=0;
+	float t;
+	
+	// Try to maintain a reasonable rate (good enough for testing anyway)
+	t = getTime();
+	if (lasttime < t) {
+		lasttime = t+0.005;
+		draw();
+	}
+}
+
+static void key(unsigned char key, int x, int y)
+{
+	if (!glutGetModifiers()) {
+		
+		if (key >= ' ' && key <= 126 && gfn->command) gfn->command (key);
+	
+	// GLUT_ACTIVE_CTRL doesn't seem to be working, so we use Alt
+	} else if (glutGetModifiers()&GLUT_ACTIVE_ALT) {
+		
+		switch (key) {
+		case 't': case 'T':
+			dsSetTextures (dsGetTextures() ^ 1);
+			break;
+		case 's': case 'S':
+			dsSetShadows (dsGetShadows() ^ 1);
+			break;
+		case 'p': case 'P':
+			pause ^= 1;
+			singlestep = 0;
+			break;
+		case 'o': case 'O':
+			if (pause) singlestep = 1;
+			break;
+		case 'v': case 'V': {
+			float xyz[3],hpr[3];
+			dsGetViewpoint (xyz,hpr);
+			printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
+					xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
+			break;
+	      }
+	    // No case 'X' - Quit works through the Mac system menu, or cmd-q
+		case 'w': case 'W':
+			writeframes ^= 1;
+			if (writeframes) printf ("Write frames not done yet!\n");// TODO
+				break;
+		}
+	}
+		
+    last_key_pressed = key;
+}
+
+static int mx=0,my=0; 	// mouse position
+static int mode = 0;	// mouse button bits
+  
+static void MouseDown(int button, int state, int x, int y)
+{
+	if(button == GLUT_LEFT_BUTTON)
+	{
+		if(state == GLUT_DOWN)
+			mode |= 1;
+		else if(state == GLUT_UP)
+			mode &= (~1);
+	}
+	else if (button == GLUT_MIDDLE_BUTTON)
+	{
+		if(state == GLUT_DOWN)
+			mode |= 3;
+		else if(state == GLUT_UP)
+			mode &= (~3);
+	}
+	else if (button == GLUT_RIGHT_BUTTON)
+	{
+		if(state == GLUT_DOWN)
+			mode |= 2;
+		else if(state == GLUT_UP)
+			mode &= (~2);
+	}
+	
+	mx = x;
+	my = y;
+}
+
+static void MouseMove(int x, int y)
+{
+	dsMotion (mode, x - mx, y - my);
+	mx = x;
+	my = y;	
+}
+
+static void createMainWindow (int _width, int _height)
+{
+	// So GLUT doesn't complain
+	int argc = 0;
+	char **argv = NULL;
+	
+	// initialize variables
+	width = _width;
+	height = _height;
+	last_key_pressed = 0;
+
+	if (width < 1 || height < 1) dsDebug (0,"bad window width or height");
+	
+	glutInit(&argc, argv);
+	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+	glutInitWindowSize(_width, _height);
+	glutInitWindowPosition(100, 100);
+	glutCreateWindow("ODE Simulation");
+	
+	glutKeyboardFunc(key);
+	glutMotionFunc(MouseMove);
+	glutMouseFunc(MouseDown);
+	glutReshapeFunc(reshape);
+	glutDisplayFunc(idle);
+	glutIdleFunc(idle);
+}
+
+void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
+			int initial_pause)
+{	
+	SIOUXSettings.initializeTB     = false;
+	SIOUXSettings.standalone       = false;
+	SIOUXSettings.setupmenus       = false;
+	SIOUXSettings.autocloseonquit  = true;
+	SIOUXSettings.asktosaveonclose = false;
+		
+	gfn = fn;
+	pause = initial_pause;
+
+	printf (
+			"\n"
+			"Simulation test environment v%d.%02d\n"
+			"   Option-P : pause / unpause (or say `-pause' on command line).\n"
+			"   Option-O : single step when paused.\n"
+			"   Option-T : toggle textures (or say `-notex' on command line).\n"
+			"   Option-S : toggle shadows (or say `-noshadow' on command line).\n"
+			"   Option-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
+			"   Option-W : write frames to ppm files: frame/frameNNN.ppm\n"
+			"\n"
+			"Change the camera position by clicking + dragging in the window.\n"
+			"   Left button - pan and tilt.\n"
+			"   Right button - forward and sideways.\n"
+			"   Left + Right button (or middle button) - sideways and up.\n"
+			"\n",DS_VERSION >> 8,DS_VERSION & 0xff);
+	
+	createMainWindow (window_width, window_height);
+	dsStartGraphics (window_width,window_height,fn);
+	
+	if (fn->start) fn->start();
+	
+	glutMainLoop();
+	
+	if (fn->stop) fn->stop();
+	dsStopGraphics();
+}
+
+extern "C" void dsStop(){ }// GLUT/MSL hooks into the system to exit
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/gl.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/gl.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/gl.h	(revision 216)
@@ -0,0 +1,2 @@
+// A little hackaround (Apple use / in the FILENAME, which doesn't work when following DOS paths)
+#include <gl.h>
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/glu.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/glu.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/GL/glu.h	(revision 216)
@@ -0,0 +1,2 @@
+// A little hackaround (Apple use / in the FILENAME, which doesn't work when following DOS paths)
+#include <glu.h>
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/ode/config.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/ode/config.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/include/ode/config.h	(revision 216)
@@ -0,0 +1,52 @@
+/* This file has been manually hacked together for the Mac CFM Carbon build - Frank. */
+
+#ifndef _ODE_CONFIG_H_
+#define _ODE_CONFIG_H_
+
+/* standard system headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include <alloca.h>
+#include <float.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* #define PENTIUM 1 -- not a pentium */
+
+/* integer types (we assume int >= 32 bits) */
+typedef char int8;
+typedef unsigned char uint8;
+typedef int int32;
+typedef unsigned int uint32;
+
+/* an integer type that we can safely cast a pointer to and from without loss of bits. */
+typedef unsigned int intP;
+
+#ifdef PRECISION_DOUBLE
+
+ /*select the base floating point type*/
+ #define dDOUBLE 1
+
+ /* the floating point infinity */
+ #define dInfinity DBL_MAX
+
+#else
+
+ /* select the base floating point type */
+ #define dSINGLE 1
+
+ /* the floating point infinity */
+ #define dInfinity FLT_MAX
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stability1.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stability1.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stability1.cpp	(revision 216)
@@ -0,0 +1,289 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCappedCylinder dsDrawCappedCylinderD
+#endif
+
+
+// some constants
+
+#define DENSITY (5.0)		// density of all objects
+
+// dynamics and collision objects
+
+struct MyObject {
+  dBodyID body;		// the body
+  dGeomID geom;		// geometry representing this body
+};
+
+static dWorldID world;
+static dSpaceID space;
+static MyObject fallingObject;
+static dGeomID  box1, box2;
+static dJointGroupID contactgroup;
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+  // if (o1->body && o2->body) return;
+
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnected (b1,b2)) return;
+
+  dContact contact[4];			// up to 3 contacts per box
+  for (i=0; i<4; i++) {
+    contact[i].surface.mode = dContactBounce; //dContactMu2;
+    contact[i].surface.mu = dInfinity;
+    contact[i].surface.mu2 = 0;
+    contact[i].surface.bounce = 0.5;
+    contact[i].surface.bounce_vel = 0.1;
+  }
+  if (int numc = dCollide (o1,o2,4,&contact[0].geom,sizeof(dContact))) {
+    // dMatrix3 RI;
+    // dRSetIdentity (RI);
+    // const dReal ss[3] = {0.02,0.02,0.02};
+    for (i=0; i<numc; i++) {
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+      // dsDrawBox (contact[i].geom.pos,RI,ss);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {-4.0f, 0.0f, 3.0f};
+  static float hpr[3] = {0.0f,-15.0f,0.0f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("To drop another object, press:\n");
+  printf ("   b for box.\n");
+  printf ("   s for sphere.\n");
+  printf ("   c for cylinder.\n");
+  printf ("To select an object, press space.\n");
+}
+
+
+char locase (char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+  else return c;
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+    int i,k;
+    dReal sides[3];
+    dMass m;
+
+    cmd = locase (cmd);
+    if (cmd == 'b' || cmd == 's' || cmd == 'c') {
+        // Destroy the currently falling object and replace it by an instance of the requested type
+        if (fallingObject.body) {
+            dBodyDestroy (fallingObject.body);
+            dGeomDestroy (fallingObject.geom);
+            memset (&fallingObject, 0, sizeof(fallingObject));
+        }
+
+        fallingObject.body = dBodyCreate (world);
+        for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+        // Start out centered above the V-gap
+        dBodySetPosition (fallingObject.body, 0,0,5);
+
+#if 0
+        dMatrix3 R;
+        dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+                            dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+        dBodySetRotation (fallingObject.body,R);
+        dBodySetData (fallingObject.body,(void*) i);
+#endif
+        
+        if (cmd == 'b') {
+            dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+            fallingObject.geom = dCreateBox (space,sides[0],sides[1],sides[2]);
+        }
+        else if (cmd == 'c') {
+            sides[0] *= 0.5;
+            dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
+            fallingObject.geom = dCreateCCylinder (space,sides[0],sides[1]);
+        }
+        else if (cmd == 's') {
+            sides[0] *= 0.5;
+            dMassSetSphere (&m,DENSITY,sides[0]);
+            fallingObject.geom = dCreateSphere (space,sides[0]);
+        }
+
+        dGeomSetBody (fallingObject.geom,fallingObject.body);
+
+        dBodySetMass (fallingObject.body,&m);
+    }
+}
+
+
+// draw a geom
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R)
+{
+  if (!g) return;
+  if (!pos) pos = dGeomGetPosition (g);
+  if (!R) R = dGeomGetRotation (g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass) {
+    dVector3 sides;
+    dGeomBoxGetLengths (g,sides);
+    dsDrawBox (pos,R,sides);
+  }
+  else if (type == dSphereClass) {
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+  }
+  else if (type == dCCylinderClass) {
+    dReal radius,length;
+    dGeomCCylinderGetParams (g,&radius,&length);
+    dsDrawCappedCylinder (pos,R,length,radius);
+  }
+  /*
+  else if (type == dGeomTransformClass) {
+    dGeomID g2 = dGeomTransformGetGeom (g);
+    const dReal *pos2 = dGeomGetPosition (g2);
+    const dReal *R2 = dGeomGetRotation (g2);
+    dVector3 actual_pos;
+    dMatrix3 actual_R;
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+    actual_pos[0] += pos[0];
+    actual_pos[1] += pos[1];
+    actual_pos[2] += pos[2];
+    dMULTIPLY0_333 (actual_R,R,R2);
+    drawGeom (g2,actual_pos,actual_R);
+  }
+   */
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  dsSetColor (0,0,2);
+  dSpaceCollide (space,0,&nearCallback);
+  if (!pause) dWorldStep (world,0.0005);
+
+  // remove all contact joints
+  dJointGroupEmpty (contactgroup);
+
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+
+  // draw the falling object
+  dsSetColor (1,0,0);
+  drawGeom (fallingObject.geom,0,0);
+
+  // draw the constraining boxes
+  dsSetColor(0.8, 1, 0.8);
+  drawGeom (box1,0,0);
+  drawGeom (box2,0,0);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+
+  world = dWorldCreate();
+  space = dHashSpaceCreate();
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  dWorldSetCFM (world,1e-5);
+  dCreatePlane (space,0,0,1,0);
+  memset (&fallingObject,0,sizeof(fallingObject));
+
+  // Create two flat boxes, just slightly off vertical and a bit apart for stuff to fall in between.
+  // Don't create bodies for these boxes -- they'll be immovable instead.
+  {
+      dReal sides[3];
+      dMatrix3 R;
+      
+      sides[0] = 4;
+      sides[1] = 0.2;
+      sides[2] = 3;
+
+      box1 = dCreateBox (space,sides[0],sides[1],sides[2]);
+      dGeomSetPosition (box1, 0, sides[1], sides[2]/2);
+      dRFromAxisAndAngle (R, 1, 0, 0, -0.1);
+      dGeomSetRotation (box1, R);
+      
+      box2 = dCreateBox (space,sides[0],sides[1],sides[2]);
+      dGeomSetPosition (box2, 0, -sides[1], sides[2]/2);
+      dRFromAxisAndAngle (R, 1, 0, 0, 0.1);
+      dGeomSetRotation (box2, R);
+  }
+  
+  // Pretend to drop a box to start
+  command('b');
+  
+  // run simulation
+  dsSimulationLoop (argc,argv,640,480,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stacktest.c
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stacktest.c	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Mac_CFMCarbon/mac_source/ode/test/test_stacktest.c	(revision 216)
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <glut.h>
+#include "ode.h"
+
+#define NUMBODIES 80
+
+#define USE_SPHERE 0
+#define USE_HELIX 1
+#define USE_TORQUE 1
+#define USE_WEIRD_MATRIX_OPS 0
+
+#define CONTACTS 1
+
+dWorldID aWorld;
+dSpaceID aSpace;
+float cycle = 0, fade;
+dJointGroupID aContactGroup;
+dBodyID bodies[NUMBODIES];
+dGeomID geoms[NUMBODIES];
+GLfloat colors[NUMBODIES][4];
+unsigned int contactsThisFrame;
+
+void kglTransformByODEGeom(dGeomID geom) {
+  const dReal *p = dGeomGetPosition(geom);
+  const dReal *R = dGeomGetRotation(geom);
+  GLdouble glm[16];
+
+  glm[0]  = R[0]; glm[1]  = R[4]; glm[2]  = R[8]; glm[3]  = 0;
+  glm[4]  = R[1]; glm[5]  = R[5]; glm[6]  = R[9]; glm[7]  = 0;
+  glm[8]  = R[2]; glm[9]  = R[6]; glm[10] = R[10];glm[11] = 0;
+  glm[12] = p[0]; glm[13] = p[1]; glm[14] = p[2]; glm[15] = 1;
+   
+  glMultMatrixd(glm);
+}
+
+static void odeNearCallback(void *data, dGeomID g1, dGeomID g2) {
+  dBodyID b1 = dGeomGetBody(g1), 
+          b2 = dGeomGetBody(g2);
+  dContact contact[CONTACTS];
+  int contactsUsed, i;
+
+  if (b1 && b2 && dAreConnected(b1, b2)) return;
+
+  contactsUsed = dCollide(g1, g2, CONTACTS, &contact[0].geom,
+    sizeof(dContact));
+  if (contactsUsed > CONTACTS) contactsUsed = CONTACTS;
+
+  for (i = 0; i < contactsUsed; i++) {
+    contact[i].surface.mode = 0;
+    contact[i].surface.mu = 20.0;
+    
+    dJointAttach(dJointCreateContact(aWorld, aContactGroup,
+      &(contact[i])), b1, b2);
+    contactsThisFrame++;
+  }
+}
+
+void myGlutResize(int w, int h) {
+  glViewport(0, 0, w, h);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(45.0, (GLfloat)w / h, 1.0, 120.0);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glTranslatef(0, -6, -20);
+}
+
+void myGlutIdle(void) {
+  const float step = 1.0/120;
+  int i;
+
+  cycle = fmod(cycle + step / 4, 1);
+  fade = fabs(cycle * 2 - 1);
+
+  contactsThisFrame = 0;
+  dSpaceCollide(aSpace, NULL, &odeNearCallback);
+  //printf("%u\n", contactsThisFrame);
+  dWorldStep(aWorld, step);
+  dJointGroupEmpty(aContactGroup);
+
+  for (i = 0; i < NUMBODIES; i++) {
+    const dReal *cvel = dBodyGetLinearVel(bodies[i]);
+    dBodyAddForce(bodies[i],
+      -cvel[0] * 0.5,
+      -cvel[1] * 0.5,
+      -cvel[2] * 0.5
+    );
+  }
+
+  glutPostRedisplay();
+}
+
+void myGlutDisplay(void) {
+  int i;
+
+  glClearColor(fade * 0.15, 0, 0, 1);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  
+  if (USE_WEIRD_MATRIX_OPS) glPushMatrix();
+  for (i = 0; i < NUMBODIES; i++) {
+    if (!USE_WEIRD_MATRIX_OPS) glPushMatrix();
+    kglTransformByODEGeom(geoms[i]);
+    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colors[i]);
+    glColor3f(fade * 1.5, 0, 0);
+#if USE_SPHERE
+    glRotatef(90, 1, 0, 0);
+    glutSolidSphere(0.5, 9, 6);
+    glDisable(GL_LIGHTING);
+    glutWireSphere(0.5, 9, 6);
+#else
+    glutSolidCube(1);
+    glDisable(GL_LIGHTING);
+    glutWireCube(1);
+#endif
+    glEnable(GL_LIGHTING);
+    if (!USE_WEIRD_MATRIX_OPS) glPopMatrix();
+  }
+  if (USE_WEIRD_MATRIX_OPS) glPopMatrix();
+  
+  glutSwapBuffers();
+}
+
+int main(int argc, char **argv) {
+	printf("Initializing GLUT\n");
+
+  glutInit(&argc, argv);                
+  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+  glutInitWindowSize(400, 300);
+  glutInitWindowPosition(100, 100);
+  glutCreateWindow("ODE Crash Test");
+  
+  glutDisplayFunc(myGlutDisplay);
+  glutReshapeFunc(myGlutResize);
+  glutIdleFunc(myGlutIdle);
+
+  glPolygonOffset(1, 1);
+  glDepthFunc(GL_LEQUAL);
+  glEnable(GL_POLYGON_OFFSET_FILL);
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_CULL_FACE);
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+  myGlutResize(400, 300);
+
+  printf("Creating ODE world\n");
+  aWorld = dWorldCreate();
+  aSpace = dHashSpaceCreate();
+  aContactGroup = dJointGroupCreate(0);
+  dCreatePlane(aSpace, 0, 1, 0, 0);
+  dWorldSetGravity(aWorld, 0, -9.81, 0);
+  dWorldSetERP(aWorld, 0.4);
+  dWorldSetCFM(aWorld, 1e-10);
+  
+  printf("Creating objects\n");
+  {
+    int i;
+    dMass mass;
+    
+    dMassSetBox(&mass, 1.0, 1, 1, 1);
+
+    for (i = 0; i < NUMBODIES; i++) {
+      float fraction = (float)i / NUMBODIES;
+    
+      bodies[i] = dBodyCreate(aWorld);
+      dBodySetMass(bodies[i], &mass);
+#if USE_SPHERE
+      geoms[i] = dCreateSphere(aSpace, 0.5);
+#else
+      geoms[i] = dCreateBox(aSpace, 1, 1, 1);
+#endif
+      dGeomSetBody(geoms[i], bodies[i]);
+    
+      if (USE_HELIX) {
+        float r     = (i % 3 - 1) * (1.5+4*(1 - fraction)),
+              theta = (float)i / 4;
+        dBodySetPosition(bodies[i],
+          sin(theta) * r, 
+          (float)i + 1,
+          cos(theta) * r
+        );
+      } else {
+        dBodySetPosition(bodies[i], 0, (float)i * 2 + 1, 0);
+      }
+      if (USE_TORQUE) dBodyAddTorque(bodies[i], fraction*10, fraction*20, fraction*30);
+      
+      colors[i][0] = fraction;
+      colors[i][1] = 1 - fraction;
+      colors[i][2] = 1 - fabs(fraction * 2 - 1);
+      colors[i][3] = 1;
+    }
+  }
+
+  printf("Starting simulation\n");
+  glutMainLoop();
+	
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/AssemblyInfo.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/AssemblyInfo.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/AssemblyInfo.cs	(revision 216)
@@ -0,0 +1,18 @@
+﻿using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Drawstuff.NET")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Ode.NET")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("b2a39dd4-dd67-4e8a-af70-d3b412da8850")]
+[assembly: AssemblyVersion("0.7.0.0")]
+[assembly: AssemblyFileVersion("0.7.0.0")]
+[assembly: CLSCompliantAttribute(true)]
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/Drawstuff.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/Drawstuff.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/Drawstuff.cs	(revision 216)
@@ -0,0 +1,58 @@
+using System;
+using System.Runtime.InteropServices;
+using Ode.NET;
+
+namespace Drawstuff.NET
+{
+#if dDOUBLE
+	using dReal = System.Double;
+#else
+	using dReal = System.Single;
+#endif
+
+	public static class ds
+	{
+		public const int VERSION = 2;
+
+		public enum Texture
+		{
+			None,
+			Wood
+		}
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate void CallbackFunction(int arg);
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Functions
+		{
+			public int version;
+			public CallbackFunction start;
+			public CallbackFunction step;
+			public CallbackFunction command;
+			public CallbackFunction stop;
+			public string path_to_textures;
+		}
+
+		[DllImport("drawstuff", EntryPoint="dsDrawBox")]
+		public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides);
+
+		[DllImport("drawstuff", EntryPoint = "dsDrawCapsule")]
+		public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius);
+
+		[DllImport("drawstuff", EntryPoint = "dsDrawConvex")]
+		public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
+
+		[DllImport("drawstuff", EntryPoint="dsSetColor")]
+		public static extern void SetColor(float red, float green, float blue);
+
+		[DllImport("drawstuff", EntryPoint="dsSetTexture")]
+		public static extern void SetTexture(Texture texture);
+
+		[DllImport("drawstuff", EntryPoint="dsSetViewpoint")]
+		public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr);
+
+		[DllImport("drawstuff", EntryPoint="dsSimulationLoop")]
+		public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn);
+	}
+}
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/premake.lua
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/premake.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Drawstuff/premake.lua	(revision 216)
@@ -0,0 +1,19 @@
+package.name = "Drawstuff.NET"
+package.kind = "dll"
+package.language = "c#"
+
+if (options["with-doubles"]) then
+  package.defines = { "dDOUBLE" }
+else
+  package.defines = { "dSINGLE " }
+end
+
+package.links = {
+  "System",
+  "Ode.NET"
+}
+
+package.files = {
+  "AssemblyInfo.cs",
+  "Drawstuff.cs"
+}
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/AssemblyInfo.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/AssemblyInfo.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/AssemblyInfo.cs	(revision 216)
@@ -0,0 +1,18 @@
+﻿using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Ode.NET")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Ode.NET")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("1347a35e-c32b-4ff6-8064-7d10b2cc113b")]
+[assembly: AssemblyVersion("0.7.0.0")]
+[assembly: AssemblyFileVersion("0.7.0.0")]
+[assembly: CLSCompliantAttribute(true)]
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/Ode.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/Ode.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/Ode.cs	(revision 216)
@@ -0,0 +1,1732 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace Ode.NET
+{
+#if dDOUBLE
+	using dReal = System.Double;
+#else
+	using dReal = System.Single;
+#endif
+
+	public static class d
+	{
+		public static dReal Infinity = dReal.MaxValue;
+
+		#region Flags and Enumerations
+
+		[Flags]
+		public enum ContactFlags : int
+		{
+			Mu2 = 0x001,
+			FDir1 = 0x002,
+			Bounce = 0x004,
+			SoftERP = 0x008,
+			SoftCFM = 0x010,
+			Motion1 = 0x020,
+			Motion2 = 0x040,
+			Slip1 = 0x080,
+			Slip2 = 0x100,
+			Approx0 = 0x0000,
+			Approx1_1 = 0x1000,
+			Approx1_2 = 0x2000,
+			Approx1 = 0x3000
+		}
+
+		public enum GeomClassID : int
+		{
+			SphereClass,
+			BoxClass,
+			CapsuleClass,
+			CylinderClass,
+			PlaneClass,
+			RayClass,
+			ConvexClass,
+			GeomTransformClass,
+			TriMeshClass,
+			HeightfieldClass,
+			FirstSpaceClass,
+			SimpleSpaceClass = FirstSpaceClass,
+			HashSpaceClass,
+			QuadTreeSpaceClass,
+			LastSpaceClass = QuadTreeSpaceClass,
+			FirstUserClass,
+			LastUserClass = FirstUserClass + MaxUserClasses - 1,
+			NumClasses,
+			MaxUserClasses = 4
+		}
+
+		public enum JointType : int
+		{
+			None,
+			Ball,
+			Hinge,
+			Slider,
+			Contact,
+			Universal,
+			Hinge2,
+			Fixed,
+			Null,
+			AMotor,
+			LMotor,
+			Plane2D
+		}
+
+		public enum JointParam : int
+		{
+			LoStop,
+			HiStop,
+			Vel,
+			FMax,
+			FudgeFactor,
+			Bounce,
+			CFM,
+			StopERP,
+			StopCFM,
+			SuspensionERP,
+			SuspensionCFM,
+			LoStop2 = 256,
+			HiStop2,
+			Vel2,
+			FMax2,
+			FudgeFactor2,
+			Bounce2,
+			CFM2,
+			StopERP2,
+			StopCFM2,
+			SuspensionERP2,
+			SuspensionCFM2,
+			LoStop3 = 512,
+			HiStop3,
+			Vel3,
+			FMax3,
+			FudgeFactor3,
+			Bounce3,
+			CFM3,
+			StopERP3,
+			StopCFM3,
+			SuspensionERP3,
+			SuspensionCFM3
+		}
+
+		#endregion
+
+		#region Callbacks
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate int AABBTestFn(IntPtr o1, IntPtr o2, ref AABB aabb);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate int ColliderFn(IntPtr o1, IntPtr o2, int flags, out ContactGeom contact, int skip);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate void GetAABBFn(IntPtr geom, out AABB aabb);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate ColliderFn GetColliderFnFn(int num);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate void GeomDtorFn(IntPtr o);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount);
+
+		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+		public delegate int TriRayCallback(IntPtr trimesh, IntPtr ray, int triangleIndex, dReal u, dReal v);
+
+		#endregion
+
+		#region Structs
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct AABB
+		{
+			public dReal MinX, MaxX;
+			public dReal MinY, MaxY;
+			public dReal MinZ, MaxZ;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Contact
+		{
+			public SurfaceParameters surface;
+			public ContactGeom geom;
+			public Vector3 fdir1;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct ContactGeom
+		{
+			public static readonly int SizeOf = Marshal.SizeOf(typeof(ContactGeom));
+
+			public Vector3 pos;
+			public Vector3 normal;
+			public dReal depth;
+			public IntPtr g1;
+			public IntPtr g2;
+			public int side1;
+			public int side2;
+		}
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct GeomClass
+		{
+			public int bytes;
+			public GetColliderFnFn collider;
+			public GetAABBFn aabb;
+			public AABBTestFn aabb_test;
+			public GeomDtorFn dtor;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct JointFeedback 
+		{
+			public Vector3 f1;
+			public Vector3 t1;
+			public Vector3 f2;
+			public Vector3 t2;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Mass
+		{
+			public dReal mass;
+			public Vector4 c;
+			public Matrix3 I;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Matrix3
+		{
+			public Matrix3(dReal m00, dReal m10, dReal m20, dReal m01, dReal m11, dReal m21, dReal m02, dReal m12, dReal m22)
+			{
+				M00 = m00;  M10 = m10;  M20 = m20;  _m30 = 0.0f;
+				M01 = m01;  M11 = m11;  M21 = m21;  _m31 = 0.0f;
+				M02 = m02;  M12 = m12;  M22 = m22;  _m32 = 0.0f;
+			}
+			public dReal M00, M10, M20;
+			private dReal _m30;
+			public dReal M01, M11, M21;
+			private dReal _m31;
+			public dReal M02, M12, M22;
+			private dReal _m32;
+		}
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Matrix4
+		{
+			public Matrix4(dReal m00, dReal m10, dReal m20, dReal m30,
+				dReal m01, dReal m11, dReal m21, dReal m31,
+				dReal m02, dReal m12, dReal m22, dReal m32,
+				dReal m03, dReal m13, dReal m23, dReal m33)
+			{
+				M00 = m00; M10 = m10; M20 = m20; M30 = m30;
+				M01 = m01; M11 = m11; M21 = m21; M31 = m31;
+				M02 = m02; M12 = m12; M22 = m22; M32 = m32;
+				M03 = m03; M13 = m13; M23 = m23; M33 = m33;
+			}
+			public dReal M00, M10, M20, M30;
+			public dReal M01, M11, M21, M31;
+			public dReal M02, M12, M22, M32;
+			public dReal M03, M13, M23, M33;
+		}
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Quaternion
+		{
+			public dReal W, X, Y, Z;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct SurfaceParameters
+		{
+			public ContactFlags mode;
+			public dReal mu;
+			public dReal mu2;
+			public dReal bounce;
+			public dReal bounce_vel;
+			public dReal soft_erp;
+			public dReal soft_cfm;
+			public dReal motion1;
+			public dReal motion2;
+			public dReal slip1;
+			public dReal slip2;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Vector3
+		{
+			public Vector3(dReal x, dReal y, dReal z)
+			{
+				X = x;  Y = y;  Z = z;  _w = 0.0f;
+			}
+			public dReal X, Y, Z;
+			private dReal _w;
+		}
+
+
+		[StructLayout(LayoutKind.Sequential)]
+		public struct Vector4
+		{
+			public Vector4(dReal x, dReal y, dReal z, dReal w)
+			{
+				X = x;  Y = y;  Z = z;  W = w;
+			}
+			public dReal X, Y, Z, W;
+		}
+
+		#endregion
+
+		[DllImport("ode", EntryPoint = "dAreConnected"), SuppressUnmanagedCodeSecurity]
+		public static extern bool AreConnected(IntPtr b1, IntPtr b2);
+
+		[DllImport("ode", EntryPoint = "dAreConnectedExcluding"), SuppressUnmanagedCodeSecurity]
+		public static extern bool AreConnectedExcluding(IntPtr b1, IntPtr b2, JointType joint_type);
+
+		[DllImport("ode", EntryPoint = "dBodyAddForce"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddForce(IntPtr body, dReal fx, dReal fy, dReal fz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddForceAtPos"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddForceAtRelPos"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddRelForce"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddRelForce(IntPtr body, dReal fx, dReal fy, dReal fz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddRelForceAtPos"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddRelForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddRelForceAtRelPos"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddRelForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddRelTorque"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddRelTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
+
+		[DllImport("ode", EntryPoint = "dBodyAddTorque"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyAddTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
+
+		[DllImport("ode", EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyCopyPosition(IntPtr body, out Vector3 pos);
+
+		[DllImport("ode", EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyCopyPosition(IntPtr body, out dReal X);
+
+		[DllImport("ode", EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyCopyQuaternion(IntPtr body, out Quaternion quat);
+
+		[DllImport("ode", EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyCopyQuaternion(IntPtr body, out dReal X);
+
+		[DllImport("ode", EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyCopyRotation(IntPtr body, out Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyCopyRotation(IntPtr body, out dReal M00);
+
+		[DllImport("ode", EntryPoint = "dBodyCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr BodyCreate(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dBodyDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyDestroy(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyDisable"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyDisable(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyEnable"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyEnable(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal BodyGetAutoDisableAngularThreshold(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
+		public static extern bool BodyGetAutoDisableFlag(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal BodyGetAutoDisableLinearThreshold(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
+		public static extern int BodyGetAutoDisableSteps(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal BodyGetAutoDisableTime(IntPtr body);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetAngularVel"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* BodyGetAngularVelUnsafe(IntPtr body);
+		public static Vector3 BodyGetAngularVel(IntPtr body)
+		{
+			unsafe { return *(BodyGetAngularVelUnsafe(body)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dBodyGetData"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr BodyGetData(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
+		public static extern int BodyGetFiniteRotationMode(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyGetFiniteRotationAxis(IntPtr body, out Vector3 result);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetForce"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* BodyGetForceUnsafe(IntPtr body);
+		public static Vector3 BodyGetForce(IntPtr body)
+		{
+			unsafe { return *(BodyGetForceUnsafe(body)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dBodyGetGravityMode"), SuppressUnmanagedCodeSecurity]
+		public static extern bool BodyGetGravityMode(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetJoint"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr BodyGetJoint(IntPtr body, int index);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetLinearVel"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* BodyGetLinearVelUnsafe(IntPtr body);
+		public static Vector3 BodyGetLinearVel(IntPtr body)
+		{
+			unsafe { return *(BodyGetLinearVelUnsafe(body)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dBodyGetMass"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyGetMass(IntPtr body, out Mass mass);
+
+		[DllImport("ode", EntryPoint = "dBodyGetNumJoints"), SuppressUnmanagedCodeSecurity]
+		public static extern int BodyGetNumJoints(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodyGetPointVel"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyGetPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetPosition"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* BodyGetPositionUnsafe(IntPtr body);
+		public static Vector3 BodyGetPosition(IntPtr body)
+		{
+			unsafe { return *(BodyGetPositionUnsafe(body)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dBodyGetPosRelPoint"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyGetPosRelPoint(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Quaternion* BodyGetQuaternionUnsafe(IntPtr body);
+		public static Quaternion BodyGetQuaternion(IntPtr body)
+		{
+			unsafe { return *(BodyGetQuaternionUnsafe(body)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dBodyGetRelPointPos"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyGetRelPointPos(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dBodyGetRelPointVel"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyGetRelPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetRotation"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Matrix3* BodyGetRotationUnsafe(IntPtr body);
+		public static Matrix3 BodyGetRotation(IntPtr body)
+		{
+			unsafe { return *(BodyGetRotationUnsafe(body)); }
+		}
+#endif
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dBodyGetTorque"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* BodyGetTorqueUnsafe(IntPtr body);
+		public static Vector3 BodyGetTorque(IntPtr body)
+		{
+			unsafe { return *(BodyGetTorqueUnsafe(body)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dBodyIsEnabled"), SuppressUnmanagedCodeSecurity]
+		public static extern bool BodyIsEnabled(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodySetAngularVel"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAngularVel(IntPtr body, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dBodySetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAutoDisableAngularThreshold(IntPtr body, dReal angular_threshold);
+
+		[DllImport("ode", EntryPoint = "dBodySetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAutoDisableDefaults(IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dBodySetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAutoDisableFlag(IntPtr body, bool do_auto_disable);
+
+		[DllImport("ode", EntryPoint = "dBodySetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAutoDisableLinearThreshold(IntPtr body, dReal linear_threshold);
+
+		[DllImport("ode", EntryPoint = "dBodySetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAutoDisableSteps(IntPtr body, int steps);
+
+		[DllImport("ode", EntryPoint = "dBodySetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetAutoDisableTime(IntPtr body, dReal time);
+
+		[DllImport("ode", EntryPoint = "dBodySetData"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetData(IntPtr body, IntPtr data);
+
+		[DllImport("ode", EntryPoint = "dBodySetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetFiniteRotationMode(IntPtr body, int mode);
+
+		[DllImport("ode", EntryPoint = "dBodySetFiniteRotationModeAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetFiniteRotationModeAxis(IntPtr body, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dBodySetForce"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetForce(IntPtr body, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dBodySetGravityMode"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetGravityMode(IntPtr body, bool mode);
+
+		[DllImport("ode", EntryPoint = "dBodySetLinearVel"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetLinearVel(IntPtr body, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dBodySetMass"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetMass(IntPtr body, ref Mass mass);
+
+		[DllImport("ode", EntryPoint = "dBodySetPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetPosition(IntPtr body, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetQuaternion(IntPtr body, ref Quaternion q);
+
+		[DllImport("ode", EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetQuaternion(IntPtr body, ref dReal w);
+
+		[DllImport("ode", EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetRotation(IntPtr body, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetRotation(IntPtr body, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dBodySetTorque"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodySetTorque(IntPtr body, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dBodyVectorFromWorld"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyVectorFromWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dBodyVectorToWorld"), SuppressUnmanagedCodeSecurity]
+		public static extern void BodyVectorToWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dBoxBox"), SuppressUnmanagedCodeSecurity]
+		public static extern void BoxBox(ref Vector3 p1, ref Matrix3 R1,
+			ref Vector3 side1, ref Vector3 p2,
+			ref Matrix3 R2, ref Vector3 side2,
+			ref Vector3 normal, out dReal depth, out int return_code,
+			int maxc, out ContactGeom contact, int skip);
+
+		[DllImport("ode", EntryPoint = "dBoxTouchesBox"), SuppressUnmanagedCodeSecurity]
+		public static extern void BoxTouchesBox(ref Vector3 _p1, ref Matrix3 R1,
+			ref Vector3 side1, ref Vector3 _p2,
+			ref Matrix3 R2, ref Vector3 side2);
+
+		[DllImport("ode", EntryPoint = "dClosestLineSegmentPoints"), SuppressUnmanagedCodeSecurity]
+		public static extern void ClosestLineSegmentPoints(ref Vector3 a1, ref Vector3 a2, 
+			ref Vector3 b1, ref Vector3 b2, 
+			ref Vector3 cp1, ref Vector3 cp2);
+
+		[DllImport("ode", EntryPoint = "dCloseODE"), SuppressUnmanagedCodeSecurity]
+		public static extern void CloseODE();
+
+		[DllImport("ode", EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
+		public static extern int Collide(IntPtr o1, IntPtr o2, int flags, [In, Out] ContactGeom[] contact, int skip);
+
+		[DllImport("ode", EntryPoint = "dConnectingJoint"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr ConnectingJoint(IntPtr j1, IntPtr j2);
+
+		[DllImport("ode", EntryPoint = "dCreateBox"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateBox(IntPtr space, dReal lx, dReal ly, dReal lz);
+
+		[DllImport("ode", EntryPoint = "dCreateCapsule"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateCapsule(IntPtr space, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dCreateConvex"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
+
+		[DllImport("ode", EntryPoint = "dCreateCylinder"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateCylinder(IntPtr space, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dCreateHeightfield"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateHeightfield(IntPtr space, IntPtr data, int bPlaceable);
+
+		[DllImport("ode", EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateGeom(int classnum);
+
+		[DllImport("ode", EntryPoint = "dCreateGeomClass"), SuppressUnmanagedCodeSecurity]
+		public static extern int CreateGeomClass(ref GeomClass classptr);
+
+		[DllImport("ode", EntryPoint = "dCreateGeomTransform"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateGeomTransform(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dCreatePlane"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreatePlane(IntPtr space, dReal a, dReal b, dReal c, dReal d);
+
+		[DllImport("ode", EntryPoint = "dCreateRay"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateRay(IntPtr space, dReal length);
+
+		[DllImport("ode", EntryPoint = "dCreateSphere"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateSphere(IntPtr space, dReal radius);
+
+		[DllImport("ode", EntryPoint = "dCreateTriMesh"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr CreateTriMesh(IntPtr space, IntPtr data, 
+			TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback);
+
+		[DllImport("ode", EntryPoint = "dDot"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal Dot(ref dReal X0, ref dReal X1, int n);
+
+		[DllImport("ode", EntryPoint = "dDQfromW"), SuppressUnmanagedCodeSecurity]
+		public static extern void DQfromW(dReal[] dq, ref Vector3 w, ref Quaternion q);
+
+		[DllImport("ode", EntryPoint = "dFactorCholesky"), SuppressUnmanagedCodeSecurity]
+		public static extern int FactorCholesky(ref dReal A00, int n);
+
+		[DllImport("ode", EntryPoint = "dFactorLDLT"), SuppressUnmanagedCodeSecurity]
+		public static extern void FactorLDLT(ref dReal A, out dReal d, int n, int nskip);
+
+		[DllImport("ode", EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomBoxGetLengths(IntPtr geom, out Vector3 len);
+
+		[DllImport("ode", EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomBoxGetLengths(IntPtr geom, out dReal x);
+
+		[DllImport("ode", EntryPoint = "dGeomBoxPointDepth"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomBoxPointDepth(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomBoxSetLengths"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomBoxSetLengths(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomCapsuleGetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCapsuleGetParams(IntPtr geom, out dReal radius, out dReal length);
+
+		[DllImport("ode", EntryPoint = "dGeomCapsulePointDepth"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomCapsulePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomCapsuleSetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCapsuleSetParams(IntPtr geom, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dGeomClearOffset"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomClearOffset(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref Vector3 pos);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref dReal X);
+
+		[DllImport("ode", EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref Quaternion Q);
+
+		[DllImport("ode", EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref dReal X);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyPosition(IntPtr geom, out Vector3 pos);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyPosition(IntPtr geom, out dReal X);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyRotation(IntPtr geom, out Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyRotation(IntPtr geom, out dReal M00);
+
+		[DllImport("ode", EntryPoint = "dGeomCylinderGetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCylinderGetParams(IntPtr geom, out dReal radius, out dReal length);
+
+		[DllImport("ode", EntryPoint = "dGeomCylinderSetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCylinderSetParams(IntPtr geom, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dGeomDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomDestroy(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomDisable"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomDisable(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomEnable"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomEnable(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomGetAABB(IntPtr geom, out AABB aabb);
+
+		[DllImport("ode", EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomGetAABB(IntPtr geom, out dReal minX);
+
+		[DllImport("ode", EntryPoint = "dGeomGetBody"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomGetBody(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity]
+		public static extern int GeomGetCategoryBits(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomGetClassData(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity]
+		public static extern int GeomGetCollideBits(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity]
+		public static extern GeomClassID GeomGetClass(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomGetData"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomGetData(IntPtr geom);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dGeomGetOffsetPosition"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* GeomGetOffsetPositionUnsafe(IntPtr geom);
+		public static Vector3 GeomGetOffsetPosition(IntPtr geom)
+		{
+			unsafe { return *(GeomGetOffsetPositionUnsafe(geom)); }
+		}
+#endif
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dGeomGetOffsetRotation"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Matrix3* GeomGetOffsetRotationUnsafe(IntPtr geom);
+		public static Matrix3 GeomGetOffsetRotation(IntPtr geom)
+		{
+			unsafe { return *(GeomGetOffsetRotationUnsafe(geom)); }
+		}
+#endif
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dGeomGetPosition"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Vector3* GeomGetPositionUnsafe(IntPtr geom);
+		public static Vector3 GeomGetPosition(IntPtr geom)
+		{
+			unsafe { return *(GeomGetPositionUnsafe(geom)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q);
+
+		[DllImport("ode", EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dGeomGetRotation"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Matrix3* GeomGetRotationUnsafe(IntPtr geom);
+		public static Matrix3 GeomGetRotation(IntPtr geom)
+		{
+			unsafe { return *(GeomGetRotationUnsafe(geom)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dGeomGetSpace"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomGetSpace(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildByte(IntPtr d, byte[] pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildByte(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness,	int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildCallback(IntPtr d, IntPtr pUserData, HeightfieldGetHeight pCallback,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildShort(IntPtr d, ushort[] pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildShort(IntPtr d, short[] pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildShort(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, float[] pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomHeightfieldDataCreate();
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataDestroy(IntPtr d);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldDataSetBounds"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomHeightfieldGetHeightfieldData(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
+
+		[DllImport("ode", EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
+		public static extern bool GeomIsEnabled(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomIsOffset"), SuppressUnmanagedCodeSecurity]
+		public static extern bool GeomIsOffset(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomIsSpace"), SuppressUnmanagedCodeSecurity]
+		public static extern bool GeomIsSpace(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomPlaneGetParams(IntPtr geom, ref Vector4 result);
+
+		[DllImport("ode", EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomPlaneGetParams(IntPtr geom, ref dReal A);
+
+		[DllImport("ode", EntryPoint = "dGeomPlanePointDepth"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomPlanePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomPlaneSetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomPlaneSetParams(IntPtr plane, dReal a, dReal b, dReal c, dReal d);
+
+		[DllImport("ode", EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomRayGet(IntPtr ray, ref Vector3 start, ref Vector3 dir);
+
+		[DllImport("ode", EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomRayGet(IntPtr ray, ref dReal startX, ref dReal dirX);
+
+		[DllImport("ode", EntryPoint = "dGeomRayGetClosestHit"), SuppressUnmanagedCodeSecurity]
+		public static extern int GeomRayGetClosestHit(IntPtr ray);
+
+		[DllImport("ode", EntryPoint = "dGeomRayGetLength"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomRayGetLength(IntPtr ray);
+
+		[DllImport("ode", EntryPoint = "dGeomRayGetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomRayGetParams(IntPtr g, out int firstContact, out int backfaceCull);
+
+		[DllImport("ode", EntryPoint = "dGeomRaySet"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomRaySet(IntPtr ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz);
+
+		[DllImport("ode", EntryPoint = "dGeomRaySetClosestHit"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomRaySetClosestHit(IntPtr ray, int closestHit);
+
+		[DllImport("ode", EntryPoint = "dGeomRaySetLength"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomRaySetLength(IntPtr ray, dReal length);
+
+		[DllImport("ode", EntryPoint = "dGeomRaySetParams"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomRaySetParams(IntPtr ray, int firstContact, int backfaceCull);
+
+		[DllImport("ode", EntryPoint = "dGeomSetBody"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetBody(IntPtr geom, IntPtr body);
+
+		[DllImport("ode", EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetCategoryBits(IntPtr geom, int bits);
+
+		[DllImport("ode", EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetCollideBits(IntPtr geom, int bits);
+
+		[DllImport("ode", EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
+
+		[DllImport("ode", EntryPoint = "dGeomSetData"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetData(IntPtr geom, IntPtr data);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetPosition(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref Quaternion Q);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref dReal X);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetRotation(IntPtr geom, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetRotation(IntPtr geom, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetWorldPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetWorldPosition(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref Quaternion Q);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref dReal X);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dGeomSetPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetPosition(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetQuaternion(IntPtr geom, ref Quaternion quat);
+
+		[DllImport("ode", EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetQuaternion(IntPtr geom, ref dReal w);
+
+		[DllImport("ode", EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetRotation(IntPtr geom, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSetRotation(IntPtr geom, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dGeomSphereGetRadius"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomSphereGetRadius(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomSpherePointDepth"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal GeomSpherePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dGeomSphereSetRadius"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomSphereSetRadius(IntPtr geom, dReal radius);
+
+		[DllImport("ode", EntryPoint = "dGeomTransformGetCleanup"), SuppressUnmanagedCodeSecurity]
+		public static extern int GeomTransformGetCleanup(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomTransformGetGeom"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomTransformGetGeom(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomTransformGetInfo"), SuppressUnmanagedCodeSecurity]
+		public static extern int GeomTransformGetInfo(IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dGeomTransformSetCleanup"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTransformSetCleanup(IntPtr geom, int mode);
+
+		[DllImport("ode", EntryPoint = "dGeomTransformSetGeom"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTransformSetGeom(IntPtr geom, IntPtr obj);
+
+		[DllImport("ode", EntryPoint = "dGeomTransformSetInfo"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTransformSetInfo(IntPtr geom, int info);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
+			double[] vertices, int vertexStride, int vertexCount,
+			int[] indices, int indexCount, int triStride);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
+			IntPtr vertices, int vertexStride, int vertexCount,
+			IntPtr indices, int indexCount, int triStride);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildDouble1(IntPtr d,
+			double[] vertices, int vertexStride, int vertexCount,
+			int[] indices, int indexCount, int triStride,
+			double[] normals);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
+			IntPtr vertices, int vertexStride, int vertexCount,
+			IntPtr indices, int indexCount, int triStride,
+			IntPtr normals);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
+			dReal[] vertices, int vertexStride, int vertexCount,
+			int[] indices, int indexCount, int triStride);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
+			IntPtr vertices, int vertexStride, int vertexCount,
+			IntPtr indices, int indexCount, int triStride);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
+			dReal[] vertices, int vertexStride, int vertexCount,
+			int[] indices, int indexCount, int triStride,
+			dReal[] normals);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
+			IntPtr vertices, int vertexStride, int vertexCount,
+			IntPtr indices, int indexCount, int triStride,
+			IntPtr normals);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSimple(IntPtr d, 
+			float[] vertices, int vertexStride, int vertexCount,
+			int[] indices, int indexCount, int triStride);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
+			IntPtr vertices, int vertexStride, int vertexCount,
+			IntPtr indices, int indexCount, int triStride);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSimple1(IntPtr d, 
+			float[] vertices, int vertexStride, int vertexCount,
+			int[] indices, int indexCount, int triStride,
+			float[] normals);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
+			IntPtr vertices, int vertexStride, int vertexCount,
+			IntPtr indices, int indexCount, int triStride,
+			IntPtr normals);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshClearTCCache"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshClearTCCache(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomTriMeshDataCreate();
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataDestroy(IntPtr d);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataGet"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomTriMeshDataGet(IntPtr d, int data_id);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataPreprocess"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataPreprocess(IntPtr d);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataSet"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataSet(IntPtr d, int data_id, IntPtr in_data);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshDataUpdate"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshDataUpdate(IntPtr d);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshEnableTC"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshEnableTC(IntPtr g, int geomClass, bool enable);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetArrayCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern TriArrayCallback GeomTriMeshGetArrayCallback(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern TriCallback GeomTriMeshGetCallback(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetData"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomTriMeshGetData(IntPtr g);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetLastTransform"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static Matrix4* GeomTriMeshGetLastTransformUnsafe(IntPtr geom);
+		public static Matrix4 GeomTriMeshGetLastTransform(IntPtr geom)
+		{
+			unsafe { return *(GeomTriMeshGetLastTransformUnsafe(geom)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetPoint"), SuppressUnmanagedCodeSecurity]
+		public extern static void GeomTriMeshGetPoint(IntPtr g, int index, dReal u, dReal v, ref Vector3 outVec);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetRayCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern TriRayCallback GeomTriMeshGetRayCallback(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetTriangle"), SuppressUnmanagedCodeSecurity]
+		public extern static void GeomTriMeshGetTriangle(IntPtr g, int index, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetTriangleCount"), SuppressUnmanagedCodeSecurity]
+		public extern static int GeomTriMeshGetTriangleCount(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshGetTriMeshDataID"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr GeomTriMeshGetTriMeshDataID(IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshIsTCEnabled"), SuppressUnmanagedCodeSecurity]
+		public static extern bool GeomTriMeshIsTCEnabled(IntPtr g, int geomClass);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshSetArrayCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshSetArrayCallback(IntPtr g, TriArrayCallback arrayCallback);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshSetCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshSetCallback(IntPtr g, TriCallback callback);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshSetData"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshSetData(IntPtr g, IntPtr data);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref Matrix4 last_trans);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dGeomTriMeshSetRayCallback"), SuppressUnmanagedCodeSecurity]
+		public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback);
+
+		[DllImport("ode", EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr HashSpaceCreate(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dHashSpaceGetLevels"), SuppressUnmanagedCodeSecurity]
+		public static extern void HashSpaceGetLevels(IntPtr space, out int minlevel, out int maxlevel);
+
+		[DllImport("ode", EntryPoint = "dHashSpaceSetLevels"), SuppressUnmanagedCodeSecurity]
+		public static extern void HashSpaceSetLevels(IntPtr space, int minlevel, int maxlevel);
+
+		[DllImport("ode", EntryPoint = "dInfiniteAABB"), SuppressUnmanagedCodeSecurity]
+		public static extern void InfiniteAABB(IntPtr geom, out AABB aabb);
+
+		[DllImport("ode", EntryPoint = "dInitODE"), SuppressUnmanagedCodeSecurity]
+		public static extern void InitODE();
+
+		[DllImport("ode", EntryPoint = "dIsPositiveDefinite"), SuppressUnmanagedCodeSecurity]
+		public static extern int IsPositiveDefinite(ref dReal A, int n);
+
+		[DllImport("ode", EntryPoint = "dInvertPDMatrix"), SuppressUnmanagedCodeSecurity]
+		public static extern int InvertPDMatrix(ref dReal A, out dReal Ainv, int n);
+
+		[DllImport("ode", EntryPoint = "dJointAddAMotorTorques"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAddAMotorTorques(IntPtr joint, dReal torque1, dReal torque2, dReal torque3);
+
+		[DllImport("ode", EntryPoint = "dJointAddHingeTorque"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAddHingeTorque(IntPtr joint, dReal torque);
+
+		[DllImport("ode", EntryPoint = "dJointAddHinge2Torque"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAddHinge2Torques(IntPtr joint, dReal torque1, dReal torque2);
+
+		[DllImport("ode", EntryPoint = "dJointAddPRTorque"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAddPRTorque(IntPtr joint, dReal torque);
+
+		[DllImport("ode", EntryPoint = "dJointAddUniversalTorque"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAddUniversalTorques(IntPtr joint, dReal torque1, dReal torque2);
+
+		[DllImport("ode", EntryPoint = "dJointAddSliderForce"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAddSliderForce(IntPtr joint, dReal force);
+
+		[DllImport("ode", EntryPoint = "dJointAttach"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointAttach(IntPtr joint, IntPtr body1, IntPtr body2);
+
+		[DllImport("ode", EntryPoint = "dJointCreateAMotor"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateAMotor(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateBall"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateBall(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateContact(IntPtr world, IntPtr group, ref Contact contact);
+
+		[DllImport("ode", EntryPoint = "dJointCreateFixed"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateFixed(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateHinge"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateHinge(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateHinge2"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateHinge2(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateLMotor"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateLMotor(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateNull"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateNull(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreatePR"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreatePR(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreatePlane2D"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreatePlane2D(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateSlider"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateSlider(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointCreateUniversal"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointCreateUniversal(IntPtr world, IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointDestroy(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorAngle"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetAMotorAngle(IntPtr j, int anum);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorAngleRate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetAMotorAngleRate(IntPtr j, int anum);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetAMotorAxis(IntPtr j, int anum, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorAxisRel"), SuppressUnmanagedCodeSecurity]
+		public static extern int JointGetAMotorAxisRel(IntPtr j, int anum);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorMode"), SuppressUnmanagedCodeSecurity]
+		public static extern int JointGetAMotorMode(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
+		public static extern int JointGetAMotorNumAxes(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetAMotorParam"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetAMotorParam(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGetBallAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetBallAnchor(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetBallAnchor2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetBallAnchor2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetBody"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointGetBody(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetData"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointGetData(IntPtr j);
+
+#if !dNO_UNSAFE_CODE
+		[CLSCompliant(false)]
+		[DllImport("ode", EntryPoint = "dJointGetFeedback"), SuppressUnmanagedCodeSecurity]
+		public extern unsafe static JointFeedback* JointGetFeedbackUnsafe(IntPtr j);
+		public static JointFeedback JointGetFeedback(IntPtr j)
+		{
+			unsafe { return *(JointGetFeedbackUnsafe(j)); }
+		}
+#endif
+
+		[DllImport("ode", EntryPoint = "dJointGetHingeAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHingeAnchor(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHingeAngle"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHingeAngle(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetHingeAngleRate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHingeAngleRate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetHingeAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHingeAxis(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHingeParam"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHingeParam(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Angle1"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHinge2Angle1(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Angle1Rate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHinge2Angle1Rate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Angle2Rate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHinge2Angle2Rate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetHingeAnchor2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHingeAnchor2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHinge2Anchor(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Anchor2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHinge2Anchor2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHinge2Axis1(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetHinge2Axis2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetHinge2Param"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetHinge2Param(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGetLMotorAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetLMotorAxis(IntPtr j, int anum, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
+		public static extern int JointGetLMotorNumAxes(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetLMotorParam"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetLMotorParam(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGetPRAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetPRAnchor(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetPRAxis1"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetPRAxis1(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetPRAxis2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetPRAxis2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetPRParam"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetPRParam(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGetPRPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetPRPosition(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetPRPositionRate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetPRPositionRate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetSliderAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetSliderAxis(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetSliderParam"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetSliderParam(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGetSliderPosition"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetSliderPosition(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetSliderPositionRate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetSliderPositionRate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetType"), SuppressUnmanagedCodeSecurity]
+		public static extern JointType JointGetType(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetUniversalAnchor(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAnchor2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetUniversalAnchor2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAngle1"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetUniversalAngle1(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAngle1Rate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetUniversalAngle1Rate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAngle2"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetUniversalAngle2(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAngle2Rate"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetUniversalAngle2Rate(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAngles"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetUniversalAngles(IntPtr j, out dReal angle1, out dReal angle2);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetUniversalAxis1(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGetUniversalAxis2(IntPtr j, out Vector3 result);
+
+		[DllImport("ode", EntryPoint = "dJointGetUniversalParam"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal JointGetUniversalParam(IntPtr j, int parameter);
+
+		[DllImport("ode", EntryPoint = "dJointGroupCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr JointGroupCreate(int max_size);
+
+		[DllImport("ode", EntryPoint = "dJointGroupDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGroupDestroy(IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointGroupEmpty"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointGroupEmpty(IntPtr group);
+
+		[DllImport("ode", EntryPoint = "dJointSetAMotorAngle"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetAMotorAngle(IntPtr j, int anum, dReal angle);
+
+		[DllImport("ode", EntryPoint = "dJointSetAMotorAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetAMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetAMotorMode"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetAMotorMode(IntPtr j, int mode);
+
+		[DllImport("ode", EntryPoint = "dJointSetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetAMotorNumAxes(IntPtr group, int num);
+
+		[DllImport("ode", EntryPoint = "dJointSetAMotorParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetAMotorParam(IntPtr group, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetBallAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetBallAnchor(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetBallAnchor2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetBallAnchor2(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetData"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetData(IntPtr j, IntPtr data);
+
+		[DllImport("ode", EntryPoint = "dJointSetFeedback"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetFeedback(IntPtr j, out JointFeedback feedback);
+
+		[DllImport("ode", EntryPoint = "dJointSetFixed"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetFixed(IntPtr j);
+
+		[DllImport("ode", EntryPoint = "dJointSetHingeAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHingeAnchor(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetHingeAnchorDelta"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHingeAnchorDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
+
+		[DllImport("ode", EntryPoint = "dJointSetHingeAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHingeAxis(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetHingeParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHingeParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHinge2Anchor(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHinge2Axis1(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHinge2Axis2(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetHinge2Param"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetHinge2Param(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetLMotorAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetLMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetLMotorNumAxes(IntPtr j, int num);
+
+		[DllImport("ode", EntryPoint = "dJointSetLMotorParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetLMotorParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetPlane2DAngleParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPlane2DAngleParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetPlane2DXParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPlane2DXParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetPlane2DYParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPlane2DYParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetPRAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPRAnchor(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetPRAxis1"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPRAxis1(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetPRAxis2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPRAxis2(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetPRParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetPRParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetSliderAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetSliderAxis(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetSliderAxisDelta"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetSliderAxisDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
+
+		[DllImport("ode", EntryPoint = "dJointSetSliderParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetSliderParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dJointSetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetUniversalAnchor(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetUniversalAxis1(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetUniversalAxis2(IntPtr j, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dJointSetUniversalParam"), SuppressUnmanagedCodeSecurity]
+		public static extern void JointSetUniversalParam(IntPtr j, int parameter, dReal value);
+
+		[DllImport("ode", EntryPoint = "dLDLTAddTL"), SuppressUnmanagedCodeSecurity]
+		public static extern void LDLTAddTL(ref dReal L, ref dReal d, ref dReal a, int n, int nskip);
+
+		[DllImport("ode", EntryPoint = "dMassAdd"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassAdd(ref Mass a, ref Mass b);
+
+		[DllImport("ode", EntryPoint = "dMassAdjust"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassAdjust(ref Mass m, dReal newmass);
+
+		[DllImport("ode", EntryPoint = "dMassCheck"), SuppressUnmanagedCodeSecurity]
+		public static extern bool MassCheck(ref Mass m);
+
+		[DllImport("ode", EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassRotate(out Mass mass, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassRotate(out Mass mass, ref dReal M00);
+
+		[DllImport("ode", EntryPoint = "dMassSetBox"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetBox(out Mass mass, dReal density, dReal lx, dReal ly, dReal lz);
+
+		[DllImport("ode", EntryPoint = "dMassSetBoxTotal"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetBoxTotal(out Mass mass, dReal total_mass, dReal lx, dReal ly, dReal lz);
+
+		[DllImport("ode", EntryPoint = "dMassSetCapsule"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetCapsule(out Mass mass, dReal density, int direction, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dMassSetCapsuleTotal"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetCapsuleTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dMassSetCylinder"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetCylinder(out Mass mass, dReal density, int direction, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dMassSetCylinderTotal"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetCylinderTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
+
+		[DllImport("ode", EntryPoint = "dMassSetParameters"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetParameters(out Mass mass, dReal themass,
+			 dReal cgx, dReal cgy, dReal cgz,
+			 dReal i11, dReal i22, dReal i33,
+			 dReal i12, dReal i13, dReal i23);
+
+		[DllImport("ode", EntryPoint = "dMassSetSphere"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetSphere(out Mass mass, dReal density, dReal radius);
+
+		[DllImport("ode", EntryPoint = "dMassSetSphereTotal"), SuppressUnmanagedCodeSecurity]
+		public static extern void dMassSetSphereTotal(out Mass mass, dReal total_mass, dReal radius);
+
+		[DllImport("ode", EntryPoint = "dMassSetTrimesh"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetTrimesh(out Mass mass, dReal density, IntPtr g);
+
+		[DllImport("ode", EntryPoint = "dMassSetZero"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassSetZero(out Mass mass);
+
+		[DllImport("ode", EntryPoint = "dMassTranslate"), SuppressUnmanagedCodeSecurity]
+		public static extern void MassTranslate(out Mass mass, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
+		public static extern void Multiply0(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
+
+		[DllImport("ode", EntryPoint = "dMultiply1"), SuppressUnmanagedCodeSecurity]
+		public static extern void Multiply1(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
+
+		[DllImport("ode", EntryPoint = "dMultiply2"), SuppressUnmanagedCodeSecurity]
+		public static extern void Multiply2(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
+
+		[DllImport("ode", EntryPoint = "dQFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
+		public static extern void QFromAxisAndAngle(out Quaternion q, dReal ax, dReal ay, dReal az, dReal angle);
+
+		[DllImport("ode", EntryPoint = "dQfromR"), SuppressUnmanagedCodeSecurity]
+		public static extern void QfromR(out Quaternion q, ref Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dQMultiply0"), SuppressUnmanagedCodeSecurity]
+		public static extern void QMultiply0(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
+
+		[DllImport("ode", EntryPoint = "dQMultiply1"), SuppressUnmanagedCodeSecurity]
+		public static extern void QMultiply1(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
+
+		[DllImport("ode", EntryPoint = "dQMultiply2"), SuppressUnmanagedCodeSecurity]
+		public static extern void QMultiply2(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
+
+		[DllImport("ode", EntryPoint = "dQMultiply3"), SuppressUnmanagedCodeSecurity]
+		public static extern void QMultiply3(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
+
+		[DllImport("ode", EntryPoint = "dQSetIdentity"), SuppressUnmanagedCodeSecurity]
+		public static extern void QSetIdentity(out Quaternion q);
+
+		[DllImport("ode", EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref Vector3 center, ref Vector3 extents, int depth);
+
+		[DllImport("ode", EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref dReal centerX, ref dReal extentsX, int depth);
+
+		[DllImport("ode", EntryPoint = "dRandReal"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal RandReal();
+
+		[DllImport("ode", EntryPoint = "dRFrom2Axes"), SuppressUnmanagedCodeSecurity]
+		public static extern void RFrom2Axes(out Matrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz);
+
+		[DllImport("ode", EntryPoint = "dRFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
+		public static extern void RFromAxisAndAngle(out Matrix3 R, dReal x, dReal y, dReal z, dReal angle);
+
+		[DllImport("ode", EntryPoint = "dRFromEulerAngles"), SuppressUnmanagedCodeSecurity]
+		public static extern void RFromEulerAngles(out Matrix3 R, dReal phi, dReal theta, dReal psi);
+
+		[DllImport("ode", EntryPoint = "dRfromQ"), SuppressUnmanagedCodeSecurity]
+		public static extern void RfromQ(out Matrix3 R, ref Quaternion q);
+
+		[DllImport("ode", EntryPoint = "dRFromZAxis"), SuppressUnmanagedCodeSecurity]
+		public static extern void RFromZAxis(out Matrix3 R, dReal ax, dReal ay, dReal az);
+
+		[DllImport("ode", EntryPoint = "dRSetIdentity"), SuppressUnmanagedCodeSecurity]
+		public static extern void RSetIdentity(out Matrix3 R);
+
+		[DllImport("ode", EntryPoint = "dSetValue"), SuppressUnmanagedCodeSecurity]
+		public static extern void SetValue(out dReal a, int n);
+
+		[DllImport("ode", EntryPoint = "dSetZero"), SuppressUnmanagedCodeSecurity]
+		public static extern void SetZero(out dReal a, int n);
+
+		[DllImport("ode", EntryPoint = "dSimpleSpaceCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr SimpleSpaceCreate(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dSolveCholesky"), SuppressUnmanagedCodeSecurity]
+		public static extern void SolveCholesky(ref dReal L, out dReal b, int n);
+
+		[DllImport("ode", EntryPoint = "dSolveL1"), SuppressUnmanagedCodeSecurity]
+		public static extern void SolveL1(ref dReal L, out dReal b, int n, int nskip);
+
+		[DllImport("ode", EntryPoint = "dSolveL1T"), SuppressUnmanagedCodeSecurity]
+		public static extern void SolveL1T(ref dReal L, out dReal b, int n, int nskip);
+
+		[DllImport("ode", EntryPoint = "dSolveLDLT"), SuppressUnmanagedCodeSecurity]
+		public static extern void SolveLDLT(ref dReal L, ref dReal d, out dReal b, int n, int nskip);
+
+		[DllImport("ode", EntryPoint = "dSpaceAdd"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceAdd(IntPtr space, IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dSpaceClean"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceClean(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dSpaceCollide"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceCollide(IntPtr space, IntPtr data, NearCallback callback);
+
+		[DllImport("ode", EntryPoint = "dSpaceCollide2"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceCollide2(IntPtr space1, IntPtr space2, IntPtr data, NearCallback callback);
+
+		[DllImport("ode", EntryPoint = "dSpaceDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceDestroy(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dSpaceGetCleanup"), SuppressUnmanagedCodeSecurity]
+		public static extern bool SpaceGetCleanup(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dSpaceGetNumGeoms"), SuppressUnmanagedCodeSecurity]
+		public static extern int SpaceGetNumGeoms(IntPtr space);
+
+		[DllImport("ode", EntryPoint = "dSpaceGetGeom"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr SpaceGetGeom(IntPtr space, int i);
+
+		[DllImport("ode", EntryPoint = "dSpaceQuery"), SuppressUnmanagedCodeSecurity]
+		public static extern bool SpaceQuery(IntPtr space, IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dSpaceRemove"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceRemove(IntPtr space, IntPtr geom);
+
+		[DllImport("ode", EntryPoint = "dSpaceSetCleanup"), SuppressUnmanagedCodeSecurity]
+		public static extern void SpaceSetCleanup(IntPtr space, bool mode);
+
+		[DllImport("ode", EntryPoint = "dVectorScale"), SuppressUnmanagedCodeSecurity]
+		public static extern void VectorScale(out dReal a, ref dReal d, int n);
+
+		[DllImport("ode", EntryPoint = "dWorldCreate"), SuppressUnmanagedCodeSecurity]
+		public static extern IntPtr WorldCreate();
+
+		[DllImport("ode", EntryPoint = "dWorldDestroy"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldDestroy(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetAutoDisableAngularThreshold(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
+		public static extern bool WorldGetAutoDisableFlag(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetAutoDisableLinearThreshold(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
+		public static extern int WorldGetAutoDisableSteps(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetAutoDisableTime(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
+		public static extern int WorldGetAutoEnableDepthSF1(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetCFM"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetCFM(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetERP"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetERP(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldGetGravity(IntPtr world, out Vector3 gravity);
+
+		[DllImport("ode", EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldGetGravity(IntPtr world, out dReal X);
+
+		[DllImport("ode", EntryPoint = "dWorldGetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetContactMaxCorrectingVel(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetContactSurfaceLayer(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
+		public static extern int WorldGetQuickStepNumIterations(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldGetQuickStepW"), SuppressUnmanagedCodeSecurity]
+		public static extern dReal WorldGetQuickStepW(IntPtr world);
+
+		[DllImport("ode", EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out Vector3 force);
+
+		[DllImport("ode", EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out dReal forceX);
+
+		[DllImport("ode", EntryPoint = "dWorldQuickStep"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldQuickStep(IntPtr world, dReal stepsize);
+
+		[DllImport("ode", EntryPoint = "dWorldSetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetAutoDisableAngularThreshold(IntPtr world, dReal angular_threshold);
+
+		[DllImport("ode", EntryPoint = "dWorldSetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetAutoDisableFlag(IntPtr world, bool do_auto_disable);
+
+		[DllImport("ode", EntryPoint = "dWorldSetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetAutoDisableLinearThreshold(IntPtr world, dReal linear_threshold);
+
+		[DllImport("ode", EntryPoint = "dWorldSetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetAutoDisableSteps(IntPtr world, int steps);
+
+		[DllImport("ode", EntryPoint = "dWorldSetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetAutoDisableTime(IntPtr world, dReal time);
+
+		[DllImport("ode", EntryPoint = "dWorldSetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetAutoEnableDepthSF1(IntPtr world, int autoEnableDepth);
+
+		[DllImport("ode", EntryPoint = "dWorldSetCFM"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetCFM(IntPtr world, dReal cfm);
+
+		[DllImport("ode", EntryPoint = "dWorldSetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetContactMaxCorrectingVel(IntPtr world, dReal vel);
+
+		[DllImport("ode", EntryPoint = "dWorldSetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetContactSurfaceLayer(IntPtr world, dReal depth);
+
+		[DllImport("ode", EntryPoint = "dWorldSetERP"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetERP(IntPtr world, dReal erp);
+
+		[DllImport("ode", EntryPoint = "dWorldSetGravity"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetGravity(IntPtr world, dReal x, dReal y, dReal z);
+
+		[DllImport("ode", EntryPoint = "dWorldSetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetQuickStepNumIterations(IntPtr world, int num);
+
+		[DllImport("ode", EntryPoint = "dWorldSetQuickStepW"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldSetQuickStepW(IntPtr world, dReal over_relaxation);
+
+		[DllImport("ode", EntryPoint = "dWorldStep"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldStep(IntPtr world, dReal stepsize);
+
+		[DllImport("ode", EntryPoint = "dWorldStepFast1"), SuppressUnmanagedCodeSecurity]
+		public static extern void WorldStepFast1(IntPtr world, dReal stepsize, int maxiterations);
+	}
+}
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/premake.lua
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/premake.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Ode/premake.lua	(revision 216)
@@ -0,0 +1,31 @@
+package.name = "Ode.NET"
+package.kind = "dll"
+package.language = "c#"
+
+-- Build options
+
+  package.defines = { }
+
+  if (options["with-doubles"]) then
+    table.insert(package.defines, "dDOUBLE")
+  else
+    table.insert(package.defines, "dSINGLE")
+  end
+
+  if (options["no-unsafe"]) then
+    table.insert(package.defines, "dNO_UNSAFE_CODE")
+  else
+    package.buildflags = { "unsafe" }
+  end
+  
+
+-- Files & Libraries
+
+  package.files = {
+    "AssemblyInfo.cs",
+    "Ode.cs"
+  }
+
+  package.links = {
+    "System"
+  }
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/README.TXT
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/README.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/README.TXT	(revision 216)
@@ -0,0 +1,73 @@
+Ode.NET - .NET bindings for ODE
+Jason Perkins (starkos@gmail.com)
+
+ THIS IS A WORK IN PROGRESS! I'm not done yet!
+ 
+
+--------------------------------------------------------------------- 
+ INSTALLATION
+--------------------------------------------------------------------- 
+
+ Note that this binding uses a C# 2.0 feature (the
+ UnmanagedFunctionPointer attribute). You will need to use
+ Visual Studio 2005 (C# Express is fine) or Mono's gmcs
+ compiler.
+ 
+ Start by getting or building ODE as a shared library (DLL).
+ 
+ The simplest way to build the bindings is probably to create a 
+ new library assembly in your tool of choice and drop in the files
+ Ode/Ode.cs and Ode/AssemblyInfo.cs. Define the symbol`dDOUBLE` if 
+ you used double-precision math in your ode.dll. Build, done.
+ 
+ For testing purposes, I have also created bindings for the 
+ Drawstuff library and a C# version of the BoxStack demo. You can
+ throw all of these files into a console executable and run it to
+ see the demo.
+ 
+ If you happen to have Premake installed (http://premake.sf.net/),
+ you can generate build scripts for the library with:
+ 
+  premake --target (toolset)                 # for single precision
+  premake --with-doubles --target (toolset)  # for double precision
+
+ To build the test application too, use:
+ 
+  premake --with-tests --target (toolset)
+  
+ To build with Mono, you must add the --dotnet parameter to enable
+ support .NET 2.0:
+ 
+   premake --dotnet mono2 --target gnu
+   
+
+--------------------------------------------------------------------- 
+ USAGE
+--------------------------------------------------------------------- 
+
+ I have tried to keep things as close to the original C API as I can,
+ rather than forcing a class structure on everyone. Everything is
+ contained within the `Ode.NET` namespace inside a static class
+ named `d`. All ODE IDs are replaced with IntPtrs. A quick example:
+ 
+   using Ode.NET;
+   
+   IntPtr world = d.WorldCreate();
+   IntPtr body = d.BodyCreate(world);
+ 
+ Take a look at Tests/BoxStack.cs for a more complete example.
+ 
+ 
+--------------------------------------------------------------------- 
+ KNOWN ISSUES
+--------------------------------------------------------------------- 
+
+ I'm not done yet, so many functions are still missing.
+
+ It is not possible to implement dBodyGetPosition(), dBodyGetRotation(),
+ etc. without resorting to unsafe code, which I was trying to avoid.
+ This binding uses the .NET friendly dBodyCopyPosition(), 
+ dBodyCopyRotation(), etc. instead. 
+  
+ Collision response (contact joints) do not work when built under 
+ Mono as double-precision. I have not tried to track down why.
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Tests/BoxStack.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Tests/BoxStack.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Tests/BoxStack.cs	(revision 216)
@@ -0,0 +1,260 @@
+using System;
+using System.Collections.Generic;
+using Drawstuff.NET;
+
+namespace Ode.NET
+{
+#if dDOUBLE
+	using dReal = System.Double;
+#else
+	using dReal = System.Single;
+#endif
+
+	public class TestBoxStack
+	{
+		#region Description of convex shape
+
+		static dReal[] planes = 
+			{
+				1.0f, 0.0f, 0.0f, 0.25f,
+				0.0f, 1.0f, 0.0f, 0.25f,
+				0.0f, 0.0f, 1.0f, 0.25f,
+				0.0f, 0.0f, -1.0f, 0.25f,
+				0.0f, -1.0f, 0.0f, 0.25f,
+				-1.0f, 0.0f , 0.0f, 0.25f
+			};
+
+		static dReal[] points =
+			{
+				0.25f, 0.25f, 0.25f,
+				-0.25f, 0.25f, 0.25f,
+				0.25f, -0.25f, 0.25f,
+				-0.25f, -0.25f, 0.25f,
+				0.25f, 0.25f, -0.25f,
+				-0.25f,0.25f,-0.25f,
+				0.25f,-0.25f,-0.25f,
+				-0.25f,-0.25f,-0.25f,
+			};
+
+		static int[] polygons =
+		{
+			4, 0, 2, 6, 4,
+			4, 1, 0, 4, 5,
+			4, 0, 1, 3, 2,
+			4, 3, 1, 5, 7,
+			4, 2, 3, 7, 6,
+			4, 5, 4, 6, 7,
+		};
+
+		#endregion
+
+		const int NUM = 100;
+		const float DENSITY = 5.0f;
+		const int MAX_CONTACTS = 8;
+		
+		static IntPtr world;
+		static IntPtr space;
+		static IntPtr contactgroup;
+
+		static Queue<IntPtr> obj = new Queue<IntPtr>();
+
+		static d.Vector3 xyz = new d.Vector3(2.1640f, -1.3079f, 1.7600f);
+		static d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
+
+		static d.NearCallback nearCallback = near;
+		static d.ContactGeom[] contacts = new d.ContactGeom[MAX_CONTACTS];
+		static d.Contact contact;
+
+
+		// Called when window is opened - sets up viewpoint and prints usage
+		static void start(int unused)
+		{
+			ds.SetViewpoint(ref xyz, ref hpr);
+			Console.WriteLine("To drop another object, press:");
+			Console.WriteLine("   b for box.");
+			Console.WriteLine("   s for sphere.");
+			Console.WriteLine("   c for capsule.");
+			Console.WriteLine("   y for cylinder.");
+			Console.WriteLine("   v for a convex object.");
+			Console.WriteLine("   x for a composite object.");
+			Console.WriteLine("To select an object, press space.");
+			Console.WriteLine("To disable the selected object, press d.");
+			Console.WriteLine("To enable the selected object, press e.");
+			Console.WriteLine("To toggle showing the geom AABBs, press a.");
+			Console.WriteLine("To toggle showing the contact points, press t.");
+			Console.WriteLine("To toggle dropping from random position/orientation, press r.");
+			Console.WriteLine("To save the current state to 'state.dif', press 1.");
+		}
+
+
+		// Near callback - creates contact joints
+		static void near(IntPtr space, IntPtr g1, IntPtr g2)
+		{
+			IntPtr b1 = d.GeomGetBody(g1);
+			IntPtr b2 = d.GeomGetBody(g2);
+			if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
+				return;
+
+			int count = d.Collide(g1, g2, MAX_CONTACTS, contacts, d.ContactGeom.SizeOf);
+			for (int i = 0; i < count; ++i)
+			{
+				contact.geom = contacts[i];
+				IntPtr joint = d.JointCreateContact(world, contactgroup, ref contact);
+				d.JointAttach(joint, b1, b2);
+			}
+		}
+
+
+		// Adds a new object to the scene - attaches a body to the geom and
+		// sets the initial position and orientation
+		static void addObject(IntPtr geom, d.Mass mass)
+		{
+			// Create a body for this object
+			IntPtr body = d.BodyCreate(world);
+			d.GeomSetBody(geom, body);
+			d.BodySetMass(body, ref mass);
+			obj.Enqueue(geom);
+
+			// Set the position of the new object
+			d.Matrix3 R;
+			d.BodySetPosition(body, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() + 2);
+			d.RFromAxisAndAngle(out R, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() * 10 - 5);
+			d.BodySetRotation(body, ref R);
+
+			// Cap the total number of objects
+			if (obj.Count > NUM)
+			{
+				geom = obj.Dequeue();
+				body = d.GeomGetBody(geom);
+				d.BodyDestroy(body);
+				d.GeomDestroy(geom);
+			}
+		}
+
+
+		// Keyboard callback
+		static void command(int cmd)
+		{
+			IntPtr geom;
+			d.Mass mass;
+			d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);
+
+			Char ch = Char.ToLower((Char)cmd);
+			switch ((Char)ch)
+			{
+			case 'b':
+				d.MassSetBox(out mass, DENSITY, sides.X, sides.Y, sides.Z);
+				geom = d.CreateBox(space, sides.X, sides.Y, sides.Z);
+				addObject(geom, mass);
+				break;
+
+			case 'c':
+				sides.X *= 0.5f;
+				d.MassSetCapsule(out mass, DENSITY, 3, sides.X, sides.Y);
+				geom = d.CreateCapsule(space, sides.X, sides.Y);
+				addObject(geom, mass);
+				break;
+
+			case 'v':
+				d.MassSetBox(out mass, DENSITY, 0.25f, 0.25f, 0.25f);
+				geom = d.CreateConvex(space, planes, planes.Length / 4, points, points.Length / 3, polygons);
+				addObject(geom, mass);
+				break;
+			}
+		}
+
+
+		// Draw an object in the scene
+		static void drawGeom(IntPtr geom)
+		{
+			IntPtr body = d.GeomGetBody(geom);
+
+			d.Vector3 pos;
+			d.BodyCopyPosition(body, out pos);
+
+			d.Matrix3 R;
+			d.BodyCopyRotation(body, out R);
+
+			d.GeomClassID type = d.GeomGetClass(geom);
+			switch (type)
+			{
+			case d.GeomClassID.BoxClass:
+				d.Vector3 sides;
+				d.GeomBoxGetLengths(geom, out sides);
+				ds.DrawBox(ref pos, ref R, ref sides);
+				break;
+			case d.GeomClassID.CapsuleClass:
+				dReal radius, length;
+				d.GeomCapsuleGetParams(geom, out radius, out length);
+				ds.DrawCapsule(ref pos, ref R, length, radius);
+				break;
+			case d.GeomClassID.ConvexClass:
+				ds.DrawConvex(ref pos, ref R, planes, planes.Length / 4, points, points.Length / 3, polygons);
+				break;
+			}
+		}
+
+
+		// Called once per frame; updates the scene
+		static void step(int pause)
+		{
+			d.SpaceCollide(space, IntPtr.Zero, nearCallback);
+			if (pause == 0)
+				d.WorldQuickStep(world, 0.02f);
+			d.JointGroupEmpty(contactgroup);
+
+			ds.SetColor(1.0f, 1.0f, 0.0f);
+			ds.SetTexture(ds.Texture.Wood);
+
+			foreach (IntPtr geom in obj)
+			{
+				drawGeom(geom);
+			}
+		}
+
+
+		static void Main(string[] args)
+		{
+			// Setup pointers to drawstuff callback functions
+			ds.Functions fn;
+			fn.version = ds.VERSION;
+			fn.start = new ds.CallbackFunction(start);
+			fn.step = new ds.CallbackFunction(step);
+			fn.command = new ds.CallbackFunction(command);
+			fn.stop = null;
+			fn.path_to_textures = "../../../../drawstuff/textures";
+			if (args.Length > 0)
+			{
+				fn.path_to_textures = args[0];
+			}
+
+			// Set up contact response parameters
+			contact.surface.mode = d.ContactFlags.Bounce | d.ContactFlags.SoftCFM;
+			contact.surface.mu = d.Infinity;
+			contact.surface.mu2 = 0.0f;
+			contact.surface.bounce = 0.1f;
+			contact.surface.bounce_vel = 0.1f;
+			contact.surface.soft_cfm = 0.01f;
+
+			// Initialize the scene
+			world = d.WorldCreate();
+			space = d.HashSpaceCreate(IntPtr.Zero);
+			contactgroup = d.JointGroupCreate(0);
+			d.WorldSetGravity(world, 0.0f, 0.0f, -0.5f);
+			d.WorldSetCFM(world, 1e-5f);
+			d.WorldSetAutoDisableFlag(world, true);
+			d.WorldSetContactMaxCorrectingVel(world, 0.1f);
+			d.WorldSetContactSurfaceLayer(world, 0.001f);
+			d.CreatePlane(space, 0, 0, 1, 0);
+
+			// Run the scene
+			ds.SimulationLoop(args.Length, args, 352, 288, ref fn);
+
+			// Clean up
+			d.JointGroupDestroy(contactgroup);
+			d.SpaceDestroy(space);
+			d.WorldDestroy(world);
+			d.CloseODE();
+		}
+	}
+}
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/Tests/premake.lua
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/Tests/premake.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/Tests/premake.lua	(revision 216)
@@ -0,0 +1,27 @@
+-- This function creates the test packages
+function maketest(name)
+
+  package = newpackage()
+  package.name = name
+  package.kind = "exe"
+  package.language = "c#"
+
+  if (options["with-doubles"]) then
+    package.defines = { "dDOUBLE" }
+  else
+    package.defines = { "dSINGLE " }
+  end
+
+  package.links = { 
+    "System", 
+    "Ode.NET", 
+    "Drawstuff.NET" 
+  }
+
+  package.files = {
+    name .. ".cs"
+  }
+
+end
+
+maketest("BoxStack")
Index: /code/branches/ode/ode-0.9/contrib/Ode.NET/premake.lua
===================================================================
--- /code/branches/ode/ode-0.9/contrib/Ode.NET/premake.lua	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/Ode.NET/premake.lua	(revision 216)
@@ -0,0 +1,29 @@
+project.name = "Ode.NET"
+
+-- Target checking
+
+  if (target and target ~= "vs2005" and target ~= "gnu") then
+    error("Ode.NET requires a .NET 2.0 compiler")
+  end
+      
+
+-- Project options
+
+  addoption("with-doubles",  "Use double instead of float as base numeric type")
+  addoption("with-tests",    "Builds the test applications and DrawStuff library")
+  addoption("no-unsafe",     "Exclude functions using unsafe code (dBodyGetPosition, etc.)")
+
+
+-- Build settings
+
+  project.config["Debug"].bindir = "bin/Debug"
+  project.config["Release"].bindir = "bin/Release"
+  
+
+-- Packages
+
+  if (options["with-tests"]) then
+    dopackage("Tests")
+    dopackage("Drawstuff")
+  end
+  dopackage("Ode")
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/LICENSE-BSD.TXT
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/LICENSE-BSD.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/LICENSE-BSD.TXT	(revision 216)
@@ -0,0 +1,37 @@
+
+This is the BSD-style license for The ODE Model Processor
+----------------------------------------------------------
+
+The ODE Model Processor
+Copyright (c) 2007, Department Of Information Science,
+University of Otago, Dunedin, New Zealand.
+All rights reserved.
+
+Author: Richard Barrington <barri662@student.otago.ac.nz>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+Neither the names of the copyright owner nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/LICENSE.TXT
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/LICENSE.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/LICENSE.TXT	(revision 216)
@@ -0,0 +1,511 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor.sln
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor.sln	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor.sln	(revision 216)
@@ -0,0 +1,20 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C# Express 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OdeModelProcessor", "OdeModelProcessor\OdeModelProcessor.csproj", "{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.cs	(revision 216)
@@ -0,0 +1,354 @@
+/*
+ * The ODE Model Processor
+ * -----------------------
+ * 
+ * Copyright 2007, Department of Information Science,
+ * University of Otago, Dunedin, New Zealand.
+ * 
+ * Author: Richard Barrington <barri662@student.otago.ac.nz>
+ * 
+ * This is a Content Processor and Tag library written for use with
+ * Microsoft Visual C# 2005 Express Edition and Microsoft XNA Game 
+ * Studio Express 1.0.
+ * 
+ * It can be used to read .x model vertex and index data before 
+ * insertion into the content pipeline. This is used to build ODE
+ * Triangle Meshes which are then used for collision detection that
+ * is more accurate than the default XNA bounding boxes or spheres.
+ * 
+ * Usage is simple:
+ * Build the library and reference the DLL in your project.
+ * Add the DLL to the Content Pipeline
+ * Set the content processor for you .x models to OdeModelProcessor.
+ * 
+ * Create triangle meshes as follows:
+ * 1) Create a space, but only one for all of models.
+ * 2) Create a triangle data.
+ * 3) Load the model.
+ * 4) Retreive the tag from the model.
+ * 6) Build the triangle mesh by calling d.GeomTriMeshDataBuildSimple.
+ * 
+ * Eg:
+ * IntPtr space = d.SimpleSpaceCreate(IntPtr.Zero);
+ * IntPtr triangleData = d.GeomTriMeshDataCreate();
+ * Model obj = content.Load<Model>("Content\\mycube");
+ * OdeTag tag = (OdeTag)obj.Tag;
+ * IntPtr vertexArray = tag.getVertices();
+ * IntPtr indexArray = tag.getIndices();
+ * d.GeomTriMeshDataBuildSimple
+ * (
+ *     triangleData,
+ *     vertexArray, tag.getVertexStride(), tag.getVertexCount(),
+ *     indexArray, tag.getIndexCount(), tag.getIndexStride()
+ * );
+ * IntPtr triangleMesh = d.CreateTriMesh(space, triangleData, null, null, null);
+ * 
+ * You can load multiple models and test for collisions with something
+ * like this in the update method:
+ * 
+ * d.GeomSetPosition(odeTri1, obj1Position.X, obj1Position.Y, obj1Position.Z);
+ * d.GeomSetPosition(odeTri2, obj2Position.X, obj2Position.Y, obj2Position.Z);
+ * int numberOfContacts = d.Collide(odeTri1, odeTri2, ODE_CONTACTS,
+ *     contactGeom, d.ContactGeom.SizeOf);
+ * 
+ * Where odeTri1 and odeTri2 are triangle meshes you've created, obj1Position
+ * and obj2Position are the positions of your rendered models in the scene,
+ * ODE_CONTACTS is a constant defining the maximum number of contacts
+ * to test for, contactGeom is a d.ContactGeom[] of length ODE_CONTACTS.
+ * 
+ * If numberOfContacts is greater than 0, you have a collision.
+ * 
+ * Other ODE functions such as d.SpaceCollide() also work; see ODE.NET BoxTest.cs.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the same terms as the ODE and ODE.Net libraries.
+ * Specifically, the terms are one of EITHER:
+ * 
+ *   (1) The GNU Lesser General Public License as published by the Free
+ *       Software Foundation; either version 2.1 of the License, or (at
+ *       your option) any later version. The text of the GNU Lesser
+ *       General Public License is included with this library in the
+ *       file LICENSE.TXT.
+ * 
+ *   (2) The BSD-style license that is included with this library in
+ *       the file LICENSE-BSD.TXT.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.
+ * 
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Design;
+using Microsoft.Xna.Framework.Content.Pipeline;
+using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
+using Microsoft.Xna.Framework.Content.Pipeline.Processors;
+using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
+using Ode.NET;
+using System.Runtime.InteropServices;
+
+namespace OdeModelProcessor
+{
+    /*
+     * Container for vertex and index data in a format
+     * that ODE.Net can use
+     */
+    public class OdeTag
+    {
+
+        private float[] vertexData;
+        private int[] indexData;
+        private const int indexStride = (sizeof(int));
+        private const int vertexStride = (3 * sizeof(float));
+
+        /* Constructors */
+        public OdeTag()
+        {
+            vertexData = new float[0];
+            indexData = new int[0];
+        }
+        
+        public OdeTag(float[] vertexData, int[] indexData)
+        {
+            this.vertexData = vertexData;
+            this.indexData = indexData;
+        }
+        
+        /* Data setter */
+        public void setData(float[] vertexData, int[] indexData)
+        {
+            this.vertexData = vertexData;
+            this.indexData = indexData;
+        }
+
+        /* Data appenders */
+        public void appendVertexData(float[] vertexData)
+        {
+            int newVertexDataLength = vertexData.Length;
+            float[] tempVertexArray = new float[newVertexDataLength + this.vertexData.Length];
+            this.vertexData.CopyTo(tempVertexArray, 0);
+            vertexData.CopyTo(tempVertexArray, this.vertexData.Length);
+            this.vertexData = tempVertexArray;
+        }
+
+        public void appendIndexData(int[] indexData)
+        {
+            int newIndexDataLength = indexData.Length;
+            int[] tempIndexArray = new int[newIndexDataLength + this.indexData.Length];
+            this.indexData.CopyTo(tempIndexArray, 0);
+            indexData.CopyTo(tempIndexArray, this.indexData.Length);
+            this.indexData = tempIndexArray;
+        }
+
+        /* Data getters */
+        public float[] getVertexData()
+        {
+            return this.vertexData;
+        }
+
+        public int[] getIndexData()
+        {
+            return this.indexData;
+        }
+
+        /* Native data getters */
+        public IntPtr getVertices()
+        {
+            int count = getVertexData().Length;
+            int memsize = count * Marshal.SizeOf(getVertexData()[0].GetType());
+            IntPtr pointer = Marshal.AllocCoTaskMem(memsize);
+            Marshal.Copy(getVertexData(), 0, pointer, count);
+            return pointer;
+        }
+
+        public IntPtr getIndices()
+        {
+            int count = getIndexData().Length;
+            int memsize = count * Marshal.SizeOf(getIndexData()[0].GetType());
+            IntPtr pointer = Marshal.AllocCoTaskMem(memsize);
+            Marshal.Copy(getIndexData(), 0, pointer, count);
+            return pointer;
+        }
+
+        /* Count getters */
+        public int getVertexCount()
+        {
+            return vertexData.Length/3;
+        }
+
+        public int getIndexCount()
+        {
+            return indexData.Length;
+        }
+
+        /* Stride getters */
+        public int getVertexStride()
+        {
+            return vertexStride;
+        }
+
+        public int getIndexStride()
+        {
+            return indexStride;
+        }
+
+        /*
+         * Convienience method to build the mesh and return it. The triangleData
+         * is passed in to allow the calling application to delete it afterwards.
+         *
+         * Be sure to destroy the returned TriangleMesh in the client application.
+         * 
+         * Can't destroy the index and vertex arrays here though, so best to handle
+         * this manually - only use this method if nothing else makes sense.
+         */ 
+        public IntPtr getTriangleMesh(IntPtr space, IntPtr triangleData)
+        {
+            d.GeomTriMeshDataBuildSimple(
+                triangleData,
+                getVertices(), getVertexStride(), getVertexCount(),
+                getIndices(), getIndexCount(), getIndexStride()
+            );
+            return d.CreateTriMesh(space, triangleData, null, null, null);
+        }
+
+    }
+
+    /*
+     * Subclass of the XNA .x model processor, which creates and appends a tag
+     * containing vertex and index data for ODE.Net to use.
+     */ 
+    [ContentProcessor]
+    public class OdeModelProcessor : ModelProcessor
+    {
+        private OdeTag tag;
+        private int indexOffset = 0;
+
+        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
+        {
+            tag = new OdeTag();
+            GenerateVerticesRecursive( input );
+            ModelContent model = base.Process(input, context);
+            model.Tag = tag;
+            indexOffset = 0;
+            return model;
+        }
+
+        public void GenerateVerticesRecursive(NodeContent input)
+        {
+            
+            MeshContent mesh = input as MeshContent;
+            
+            if (mesh != null)
+            {
+                GeometryContentCollection gc = mesh.Geometry;
+                foreach (GeometryContent g in gc)
+                {
+                    VertexContent vc = g.Vertices;
+                    IndirectPositionCollection ipc = vc.Positions;
+                    IndexCollection ic = g.Indices;
+
+                    float[] vertexData = new float[ipc.Count * 3];
+                    for (int i = 0; i < ipc.Count; i++)
+                    {
+                        
+                        Vector3 v0 = ipc[i];
+                        vertexData[(i * 3) + 0] = v0.X;
+                        vertexData[(i * 3) + 1] = v0.Y;
+                        vertexData[(i * 3) + 2] = v0.Z;                        
+                        
+                    }
+
+                    int[] indexData = new int[ic.Count];
+                    for (int j = 0; j < ic.Count; j ++)
+                    {
+
+                        indexData[j] = ic[j] + indexOffset;
+
+                    }
+
+                    tag.appendVertexData(vertexData);
+                    tag.appendIndexData(indexData);
+                    indexOffset += ipc.Count;
+                }
+                
+            }
+
+            foreach (NodeContent child in input.Children)
+            {
+                GenerateVerticesRecursive(child);
+            }
+
+        }
+
+    }
+
+    /* Writer for the OdeTag class */
+    [ContentTypeWriter]
+    public class OdeTagWriter : ContentTypeWriter<OdeTag>
+    {
+
+        protected override void Write(ContentWriter output, OdeTag value)
+        {
+            float[] vertexData = value.getVertexData();
+            int[] indexData = value.getIndexData();
+            output.Write(vertexData.Length);
+            output.Write(indexData.Length);
+            for (int j = 0; j < vertexData.Length; j++)
+            {
+                output.Write(vertexData[j]);
+            }
+            for (int i = 0; i < indexData.Length; i++)
+            {
+                output.Write(indexData[i]);
+            }
+        }
+
+        public override string GetRuntimeType(TargetPlatform targetPlatform)
+        {
+            return typeof(OdeTag).AssemblyQualifiedName;
+        }
+
+        public override string GetRuntimeReader(TargetPlatform targetPlatform)
+        {
+            return "OdeModelProcessor.OdeTagReader, OdeModelProcessor, Version=1.0.0.0, Culture=neutral";
+        }
+
+    }
+
+    /* Reader for the OdeTag class */
+    public class OdeTagReader : ContentTypeReader<OdeTag>
+    {
+        protected override OdeTag Read(ContentReader input, OdeTag existingInstance)
+        {
+            float[] vertexData = new float[input.ReadInt32()];
+            int[] indexData = new int[input.ReadInt32()];
+            for (int j = 0; j < vertexData.Length; j++)
+            {
+                vertexData[j] = input.ReadSingle();
+            }
+            for (int i = 0; i < indexData.Length; i++)
+            {
+                indexData[i] = input.ReadInt32();
+            }
+
+            OdeTag tag = null;
+            if (existingInstance == null)
+            {
+                tag = new OdeTag(vertexData, indexData);
+            }
+            else
+            {
+                tag = existingInstance;
+                tag.setData(vertexData, indexData);
+            }
+            return tag;
+        }
+    }
+}
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.csproj
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.csproj	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/OdeModelProcessor.csproj	(revision 216)
@@ -0,0 +1,69 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{246F3075-FEE3-45F9-8CB6-47DADBFFD1F2}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>OdeModelProcessor</RootNamespace>
+    <AssemblyName>OdeModelProcessor</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>
+    </DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Microsoft.Xna.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86" />
+    <Reference Include="Ode.NET, Version=0.7.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\ODE\Ode.NET-0.8\bin\Release\Ode.NET.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="OdeModelProcessor.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+      <DependentUpon>Settings.settings</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/AssemblyInfo.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/AssemblyInfo.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/AssemblyInfo.cs	(revision 216)
@@ -0,0 +1,35 @@
+﻿using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OdeModelProcessor")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OdeModelProcessor")]
+[assembly: AssemblyCopyright("Copyright ©  2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("29c5609a-cd5f-480b-b4ef-5c11de022268")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.Designer.cs
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.Designer.cs	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.Designer.cs	(revision 216)
@@ -0,0 +1,26 @@
+﻿//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.832
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace OdeModelProcessor.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.settings
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.settings	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/OdeModelProcessor/Properties/Settings.settings	(revision 216)
@@ -0,0 +1,6 @@
+﻿<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+</SettingsFile>
Index: /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/README.TXT
===================================================================
--- /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/README.TXT	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/OdeModelProcessor/README.TXT	(revision 216)
@@ -0,0 +1,78 @@
+The ODE Model Processor
+-----------------------
+
+Copyright 2007, Department of Information Science,
+University of Otago, Dunedin, New Zealand.
+
+Author: Richard Barrington <barri662@student.otago.ac.nz>
+
+This is a Content Processor and Tag library written for use with
+Microsoft Visual C# 2005 Express Edition and Microsoft XNA Game 
+Studio Express 1.0.
+
+It can be used to read .x model vertex and index data before 
+insertion into the content pipeline. This is used to build ODE
+Triangle Meshes which are then used for collision detection that
+is more accurate than the default XNA bounding boxes or spheres.
+
+Usage is fairly simple:
+Build the library and reference the DLL in your project.
+Add the DLL to the Content Pipeline
+Set the content processor for you .x models to OdeModelProcessor.
+
+Create triangle meshes as follows:
+1) Create a space, but only one for all of models.
+2) Create a triangle data.
+3) Load the model.
+4) Retreive the tag from the model.
+6) Build the triangle mesh by calling d.GeomTriMeshDataBuildSimple.
+
+Eg:
+IntPtr space = d.SimpleSpaceCreate(IntPtr.Zero);
+IntPtr triangleData = d.GeomTriMeshDataCreate();
+Model obj = content.Load<Model>("Content\\mycube");
+OdeTag tag = (OdeTag)obj.Tag;
+IntPtr vertexArray = tag.getVertices();
+IntPtr indexArray = tag.getIndices();
+d.GeomTriMeshDataBuildSimple
+(
+	triangleData,
+	vertexArray, tag.getVertexStride(), tag.getVertexCount(),
+	indexArray, tag.getIndexCount(), tag.getIndexStride()
+);
+IntPtr triangleMesh = d.CreateTriMesh(space, triangleData, null, null, null);
+
+You can load multiple models and test for collisions with something
+like this in the update method:
+
+d.GeomSetPosition(odeTri1, obj1Position.X, obj1Position.Y, obj1Position.Z);
+d.GeomSetPosition(odeTri2, obj2Position.X, obj2Position.Y, obj2Position.Z);
+int numberOfContacts = d.Collide(odeTri1, odeTri2, ODE_CONTACTS,
+                           contactGeom, d.ContactGeom.SizeOf);
+
+Where odeTri1 and odeTri2 are triangle meshes you've created, obj1Position
+and obj2Position are the positions of your rendered models in the scene,
+ODE_CONTACTS is a constant defining the maximum number of contacts
+to test for, contactGeom is a d.ContactGeom[] of length ODE_CONTACTS.
+
+If numberOfContacts is greater than 0, you have a collision.
+
+Other ODE functions such as d.SpaceCollide() also work; see ODE.NET BoxTest.cs.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as the ODE and ODE.Net libraries.
+Specifically, the terms are one of EITHER:
+
+  (1) The GNU Lesser General Public License as published by the Free
+      Software Foundation; either version 2.1 of the License, or (at
+      your option) any later version. The text of the GNU Lesser
+      General Public License is included with this library in the
+      file LICENSE.TXT.
+
+  (2) The BSD-style license that is included with this library in
+      the file LICENSE-BSD.TXT.
+ 
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+LICENSE.TXT and LICENSE-BSD.TXT for more details.
Index: /code/branches/ode/ode-0.9/contrib/README
===================================================================
--- /code/branches/ode/ode-0.9/contrib/README	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/README	(revision 216)
@@ -0,0 +1,19 @@
+This directory contains ODE-related things that have been generously
+contributed by ODE's users. Why is this stuff here and not integrated
+into the main ODE source tree?  There may be several reasons:
+
+  * The author(s) and ODE maintainers(s) may not have had time to do
+    the job.
+
+  * It may not be finished.
+
+  * It may contribute functionality that is useful but not considered
+    to be part of ODE's core.
+
+No guarantees are made about the code in this directory - it may not
+be documented, it may not have been tested, and it may not even
+compile for you.
+
+Each package has its own subdirectory, with a README file in that
+directory explaining what the package is.
+
Index: /code/branches/ode/ode-0.9/contrib/TerrainAndCone/collision_std_internal.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/TerrainAndCone/collision_std_internal.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/TerrainAndCone/collision_std_internal.h	(revision 216)
@@ -0,0 +1,100 @@
+//Benoit CHAPEROT 2003-2004 www.jstarlab.com
+#ifndef _ODE_COLLISION_STD_INTERNAL_H_
+#define _ODE_COLLISION_STD_INTERNAL_H_
+
+#include <ode/common.h>
+#include "collision_kernel.h"
+
+struct dxSphere : public dxGeom {
+  dReal radius;		// sphere radius
+  dxSphere (dSpaceID space, dReal _radius);
+  void computeAABB();
+};
+
+
+struct dxBox : public dxGeom {
+  dVector3 side;	// side lengths (x,y,z)
+  dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz);
+  void computeAABB();
+};
+
+
+struct dxCCylinder : public dxGeom {
+  dReal radius,lz;	// radius, length along z axis
+  dxCCylinder (dSpaceID space, dReal _radius, dReal _length);
+  void computeAABB();
+};
+
+
+struct dxPlane : public dxGeom {
+  dReal p[4];
+  dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d);
+  void computeAABB();
+};
+
+struct dxCylinder : public dxGeom {
+  dReal radius,lz;	// radius, length along z axis
+  dxCylinder (dSpaceID space, dReal _radius, dReal _length);
+  void computeAABB();
+};
+
+struct dxCone : public dxGeom {
+  dReal radius,lz;
+  dxCone(dSpaceID space, dReal _radius,dReal _length);
+  ~dxCone();
+  void computeAABB();
+};
+
+struct dxRay : public dxGeom {
+  dReal length;
+  dxRay (dSpaceID space, dReal _length);
+  void computeAABB();
+};
+
+struct dxTerrainY : public dxGeom {
+  dReal m_vLength;
+  dReal *m_pHeights;
+  dReal m_vMinHeight;
+  dReal m_vMaxHeight;
+  dReal m_vNodeLength;
+  int	m_nNumNodesPerSide;
+  int	m_nNumNodesPerSideShift;
+  int	m_nNumNodesPerSideMask;
+  int	m_bFinite;
+  dxTerrainY(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable);
+  ~dxTerrainY();
+  void computeAABB();
+  dReal GetHeight(dReal x,dReal z);
+  dReal GetHeight(int x,int z);
+  int dCollideTerrainUnit(int x,int z,dxGeom *o2,int numMaxContacts,int flags,dContactGeom *contact, int skip);
+  bool IsOnTerrain(int nx,int nz,int w,dReal *pos);
+};
+
+struct dxTerrainZ : public dxGeom {
+  dReal m_vLength;
+  dReal *m_pHeights;
+  dReal m_vMinHeight;
+  dReal m_vMaxHeight;
+  dReal m_vNodeLength;
+  int	m_nNumNodesPerSide;
+  int	m_nNumNodesPerSideShift;
+  int	m_nNumNodesPerSideMask;
+  int	m_bFinite;
+  dxTerrainZ(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable);
+  ~dxTerrainZ();
+  void computeAABB();
+  dReal GetHeight(dReal x,dReal y);
+  dReal GetHeight(int x,int y);
+  int dCollideTerrainUnit(int x,int y,dxGeom *o2,int numMaxContacts,int flags,dContactGeom *contact, int skip);
+  bool IsOnTerrain(int nx,int ny,int w,dReal *pos);
+};
+
+#ifndef MIN
+#define MIN(a,b)	((a<b)?a:b)
+#endif
+
+#ifndef MAX
+#define MAX(a,b)	((a>b)?a:b)
+#endif
+
+#endif //_ODE_COLLISION_STD_INTERNAL_H_
Index: /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dCone.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dCone.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dCone.cpp	(revision 216)
@@ -0,0 +1,504 @@
+//Benoit CHAPEROT 2003-2004 www.jstarlab.com
+//some code inspired by Magic Software
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_std_internal.h"
+#include "collision_util.h"
+#include <drawstuff/drawstuff.h>
+#include "windows.h"
+#include "ode\ode.h"
+
+#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
+const dReal fEPSILON = 1e-9f;
+
+dxCone::dxCone (dSpaceID space, dReal _radius,dReal _length) :
+dxGeom (space,1)
+{
+	dAASSERT(_radius > 0.f);
+	dAASSERT(_length > 0.f);
+	type = dConeClass;
+	radius = _radius;
+	lz = _length;
+}
+
+dxCone::~dxCone()
+{
+}
+
+void dxCone::computeAABB()
+{
+  const dMatrix3& R = final_posr->R;
+  const dVector3& pos = final_posr->pos;
+
+	dReal xrange = dFabs(R[2]  * lz) + radius;
+	dReal yrange = dFabs(R[6]  * lz) + radius;
+	dReal zrange = dFabs(R[10] * lz) + radius;
+	aabb[0] = pos[0] - xrange;
+	aabb[1] = pos[0] + xrange;
+	aabb[2] = pos[1] - yrange;
+	aabb[3] = pos[1] + yrange;
+	aabb[4] = pos[2] - zrange;
+	aabb[5] = pos[2] + zrange;
+}
+
+dGeomID dCreateCone(dSpaceID space, dReal _radius,dReal _length)
+{
+	return new dxCone(space,_radius,_length);
+}
+
+void dGeomConeSetParams (dGeomID g, dReal _radius, dReal _length)
+{
+	dUASSERT (g && g->type == dConeClass,"argument not a cone");
+	dAASSERT (_radius > 0.f);
+	dAASSERT (_length > 0.f);
+  g->recomputePosr();
+	dxCone *c = (dxCone*) g;
+	c->radius = _radius;
+	c->lz = _length;
+	dGeomMoved (g);
+}
+
+
+void dGeomConeGetParams (dGeomID g, dReal *_radius, dReal *_length)
+{
+	dUASSERT (g && g->type == dConeClass,"argument not a cone");
+  g->recomputePosr();
+	dxCone *c = (dxCone*) g;
+	*_radius = c->radius;
+	*_length = c->lz;
+}
+
+//positive inside
+dReal dGeomConePointDepth(dGeomID g, dReal x, dReal y, dReal z)
+{
+	dUASSERT (g && g->type == dConeClass,"argument not a cone");
+
+   g->recomputePosr();
+	dxCone *cone = (dxCone*) g;
+
+	dVector3 tmp,q;
+	tmp[0] = x - cone->final_posr->pos[0];
+	tmp[1] = y - cone->final_posr->pos[1];
+	tmp[2] = z - cone->final_posr->pos[2];
+	dMULTIPLY1_331 (q,cone->final_posr->R,tmp);
+
+	dReal r = cone->radius;
+	dReal h = cone->lz;
+
+	dReal d0 = (r - r*q[2]/h) - dSqrt(q[0]*q[0]+q[1]*q[1]);
+	dReal d1 = q[2];
+	dReal d2 = h-q[2];
+	
+	if (d0 < d1) {
+    if (d0 < d2) return d0; else return d2;
+	}
+	else {
+	if (d1 < d2) return d1; else return d2;
+	}
+}
+
+//plane plane
+bool FindIntersectionPlanePlane(const dReal Plane0[4], const dReal Plane1[4],
+	dVector3 LinePos,dVector3 LineDir)
+{
+    // If Cross(N0,N1) is zero, then either planes are parallel and separated
+    // or the same plane.  In both cases, 'false' is returned.  Otherwise,
+    // the intersection line is
+    //
+    //   L(t) = t*Cross(N0,N1) + c0*N0 + c1*N1
+    //
+    // for some coefficients c0 and c1 and for t any real number (the line
+    // parameter).  Taking dot products with the normals,
+    //
+    //   d0 = Dot(N0,L) = c0*Dot(N0,N0) + c1*Dot(N0,N1)
+    //   d1 = Dot(N1,L) = c0*Dot(N0,N1) + c1*Dot(N1,N1)
+    //
+    // which are two equations in two unknowns.  The solution is
+    //
+    //   c0 = (Dot(N1,N1)*d0 - Dot(N0,N1)*d1)/det
+    //   c1 = (Dot(N0,N0)*d1 - Dot(N0,N1)*d0)/det
+    //
+    // where det = Dot(N0,N0)*Dot(N1,N1)-Dot(N0,N1)^2.
+/*
+    Real fN00 = rkPlane0.Normal().SquaredLength();
+    Real fN01 = rkPlane0.Normal().Dot(rkPlane1.Normal());
+    Real fN11 = rkPlane1.Normal().SquaredLength();
+    Real fDet = fN00*fN11 - fN01*fN01;
+
+    if ( Math::FAbs(fDet) < gs_fEpsilon )
+        return false;
+
+    Real fInvDet = 1.0f/fDet;
+    Real fC0 = (fN11*rkPlane0.Constant() - fN01*rkPlane1.Constant())*fInvDet;
+    Real fC1 = (fN00*rkPlane1.Constant() - fN01*rkPlane0.Constant())*fInvDet;
+
+    rkLine.Direction() = rkPlane0.Normal().Cross(rkPlane1.Normal());
+    rkLine.Origin() = fC0*rkPlane0.Normal() + fC1*rkPlane1.Normal();
+    return true;
+*/
+	dReal fN00 = dLENGTHSQUARED(Plane0);
+    dReal fN01 = dDOT(Plane0,Plane1);
+    dReal fN11 = dLENGTHSQUARED(Plane1);
+    dReal fDet = fN00*fN11 - fN01*fN01;
+
+    if ( fabs(fDet) < fEPSILON)
+        return false;
+
+    dReal fInvDet = 1.0f/fDet;
+    dReal fC0 = (fN11*Plane0[3] - fN01*Plane1[3])*fInvDet;
+    dReal fC1 = (fN00*Plane1[3] - fN01*Plane0[3])*fInvDet;
+
+    dCROSS(LineDir,=,Plane0,Plane1);
+	dNormalize3(LineDir);
+
+	dVector3 Temp0,Temp1;
+	dOPC(Temp0,*,Plane0,fC0);
+	dOPC(Temp1,*,Plane1,fC1);
+	dOP(LinePos,+,Temp0,Temp1);
+
+    return true;
+}
+
+//plane ray
+bool FindIntersectionPlaneRay(const dReal Plane[4],
+					  const dVector3 &LinePos,const dVector3 &LineDir,
+					  dReal &u,dVector3 &Pos)
+{
+/*
+	u = (A*X1 + B*Y1 + C*Z1 + D) / (A*(X1-X2) + B*(Y1-Y2)+C*(Z1-Z2))	
+*/	
+	dReal fDet = -dDot(Plane,LineDir,3);
+
+	if ( fabs(fDet) < fEPSILON)
+        return false;
+
+	u = (dDot(Plane,LinePos,3) - Plane[3]) / fDet;
+	dOPC(Pos,*,LineDir,u);
+	dOPE(Pos,+=,LinePos);
+
+	return true;
+}
+
+int SolveQuadraticPolynomial(dReal a,dReal b,dReal c,dReal &x0,dReal &x1)
+{
+	dReal d = b*b - 4*a*c;
+	int NumRoots = 0;
+	dReal dr;
+
+	if (d < 0.f)
+		return NumRoots;
+
+	if (d == 0.f)
+	{
+		NumRoots = 1;
+		dr = 0.f;
+	}
+	else
+	{
+		NumRoots = 2;
+		dr = sqrtf(d);
+	}
+
+	x0 = (-b -dr) / (2.f * a);
+	x1 = (-b +dr) / (2.f * a);
+
+	return NumRoots;
+}
+/*
+const int VALID_INTERSECTION	= 1<<0;
+const int POS_TEST_FAILEDT0		= 1<<0;
+const int POS_TEST_FAILEDT1		= 1<<1;
+*/
+int ProcessConeRayIntersectionPoint(	dReal r,dReal h,
+										const dVector3 &q,const dVector3 &v,dReal t,
+										dVector3 &p,
+										dVector3 &n,
+										int &f)
+{
+	dOPC(p,*,v,t);
+	dOPE(p,+=,q);
+	n[0] = 2*p[0];
+	n[1] = 2*p[1];
+	n[2] = -2*p[2]*r*r/(h*h);
+
+	f = 0;
+	if (p[2] > h)	return 0;
+	if (p[2] < 0)	return 0;
+	if (t > 1)		return 0;
+	if (t < 0)		return 0;
+
+	return 1;
+}
+
+//cone ray
+//line in cone space (position,direction)
+//distance from line position (direction normalized)(if any)
+//return the number of intersection
+int FindIntersectionConeRay(dReal r,dReal h,	
+					 const dVector3 &q,const dVector3 &v,dContactGeom *pContact)
+{
+	dVector3 qp,vp;
+	dOPE(qp,=,q);
+	dOPE(vp,=,v);
+	qp[2] = h-q[2];
+	vp[2] = -v[2];
+	dReal ts = (r/h);
+	ts *= ts;
+	dReal a = vp[0]*vp[0] + vp[1]*vp[1] - ts*vp[2]*vp[2];
+	dReal b = 2.f*qp[0]*vp[0] + 2.f*qp[1]*vp[1] - 2.f*ts*qp[2]*vp[2];
+	dReal c = qp[0]*qp[0] + qp[1]*qp[1] - ts*qp[2]*qp[2];
+
+/*
+	dReal a = v[0]*v[0] + v[1]*v[1] - (v[2]*v[2]*r*r) / (h*h);
+	dReal b = 2.f*q[0]*v[0] + 2.f*q[1]*v[1] + 2.f*r*r*v[2]/h - 2*r*r*q[0]*v[0]/(h*h);
+	dReal c = q[0]*q[0] + q[1]*q[1] + 2*r*r*q[2]/h - r*r*q[2]/(h*h) - r*r;
+*/
+	int nNumRoots=SolveQuadraticPolynomial(a,b,c,pContact[0].depth,pContact[1].depth);
+	int flag = 0;
+
+	dContactGeom ValidContact[2];
+
+	int nNumValidContacts = 0;
+	for (int i=0;i<nNumRoots;i++)
+	{
+		if (ProcessConeRayIntersectionPoint(r,h,q,v,pContact[i].depth,pContact[i].pos,
+			pContact[i].normal,flag))
+		{
+			ValidContact[nNumValidContacts] = pContact[i];
+			nNumValidContacts++;
+		}
+	}
+
+	dOP(qp,+,q,v);
+
+	if ((nNumValidContacts < 2) && (v[2] != 0.f))
+	{
+		dReal d = (0.f-q[2]) / (v[2]); 
+		if ((d>=0) && (d<=1))
+		{
+			dOPC(vp,*,v,d);
+			dOP(qp,+,q,vp);
+
+			if (qp[0]*qp[0]+qp[1]*qp[1] < r*r)
+			{
+				dOPE(ValidContact[nNumValidContacts].pos,=,qp);
+				ValidContact[nNumValidContacts].normal[0] = 0.f;
+				ValidContact[nNumValidContacts].normal[1] = 0.f;
+				ValidContact[nNumValidContacts].normal[2] = -1.f;
+				ValidContact[nNumValidContacts].depth = d;
+				nNumValidContacts++;
+			}
+		}
+	}
+
+	if (nNumValidContacts == 2)
+	{
+		if (ValidContact[0].depth > ValidContact[1].depth)
+		{
+			pContact[0] = ValidContact[1];
+			pContact[1] = ValidContact[0];
+		}
+		else
+		{
+			pContact[0] = ValidContact[0];
+			pContact[1] = ValidContact[1];
+		}
+	}
+	else if (nNumValidContacts == 1)
+	{
+		pContact[0] = ValidContact[0];
+	}
+
+	return nNumValidContacts;
+}
+
+int dCollideConePlane (dxGeom *o1, dxGeom *o2, int flags,
+						 dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dConeClass);
+	dIASSERT (o2->type == dPlaneClass);
+	dxCone *cone = (dxCone*) o1;
+	dxPlane *plane = (dxPlane*) o2;
+
+	contact->g1 = o1;
+	contact->g2 = o2;
+
+	dVector3 p0,p1,pp0,pp1;
+	dOPE(p0,=,cone->final_posr->pos);
+	p1[0] = cone->final_posr->R[0*4+2] * cone->lz + p0[0];
+	p1[1] = cone->final_posr->R[1*4+2] * cone->lz + p0[1];
+	p1[2] = cone->final_posr->R[2*4+2] * cone->lz + p0[2];
+
+	dReal u;
+	FindIntersectionPlaneRay(plane->p,p0,plane->p,u,pp0);
+	FindIntersectionPlaneRay(plane->p,p1,plane->p,u,pp1);
+
+	if (dDISTANCE(pp0,pp1) < fEPSILON)
+	{
+		p1[0] = cone->final_posr->R[0*4+0] * cone->lz + p0[0];
+		p1[1] = cone->final_posr->R[1*4+0] * cone->lz + p0[1];
+		p1[2] = cone->final_posr->R[2*4+0] * cone->lz + p0[2];
+		FindIntersectionPlaneRay(plane->p,p1,plane->p,u,pp1);
+		dIASSERT(dDISTANCE(pp0,pp1) >= fEPSILON);
+	}
+	dVector3 h,r0,r1;
+	h[0] = cone->final_posr->R[0*4+2];
+	h[1] = cone->final_posr->R[1*4+2];
+	h[2] = cone->final_posr->R[2*4+2];
+	
+	dOP(r0,-,pp0,pp1);
+	dCROSS(r1,=,h,r0);
+	dCROSS(r0,=,r1,h);
+	dNormalize3(r0);
+	dOPEC(h,*=,cone->lz);
+	dOPEC(r0,*=,cone->radius);
+
+	dVector3 p[3];
+	dOP(p[0],+,cone->final_posr->pos,h);
+	dOP(p[1],+,cone->final_posr->pos,r0);
+	dOP(p[2],-,cone->final_posr->pos,r0);
+	
+	int numMaxContacts = flags & 0xffff;
+	if (numMaxContacts == 0) 
+		numMaxContacts = 1;
+
+	int n=0;
+	for (int i=0;i<3;i++)
+	{
+		dReal d = dGeomPlanePointDepth(o2, p[i][0], p[i][1], p[i][2]);
+
+		if (d>0.f)
+		{
+			CONTACT(contact,n*skip)->g1 = o1;
+			CONTACT(contact,n*skip)->g2 = o2;
+			dOPE(CONTACT(contact,n*skip)->normal,=,plane->p); 
+			dOPE(CONTACT(contact,n*skip)->pos,=,p[i]); 
+			CONTACT(contact,n*skip)->depth = d;
+			n++;
+
+			if (n == numMaxContacts)
+				return n;
+		}
+	}
+	
+	return n;
+}
+
+int dCollideRayCone (dxGeom *o1, dxGeom *o2, int flags,
+						 dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dRayClass);
+	dIASSERT (o2->type == dConeClass);
+	dxRay *ray = (dxRay*) o1;
+	dxCone *cone = (dxCone*) o2;
+
+	contact->g1 = o1;
+	contact->g2 = o2;
+
+	dVector3 tmp,q,v;
+	tmp[0] = ray->final_posr->pos[0] - cone->final_posr->pos[0];
+	tmp[1] = ray->final_posr->pos[1] - cone->final_posr->pos[1];
+	tmp[2] = ray->final_posr->pos[2] - cone->final_posr->pos[2];
+	dMULTIPLY1_331 (q,cone->final_posr->R,tmp);
+	tmp[0] = ray->final_posr->R[0*4+2] * ray->length;
+	tmp[1] = ray->final_posr->R[1*4+2] * ray->length;
+	tmp[2] = ray->final_posr->R[2*4+2] * ray->length;
+	dMULTIPLY1_331 (v,cone->final_posr->R,tmp);
+
+	dReal r = cone->radius;
+	dReal h = cone->lz;
+
+	dContactGeom Contact[2];
+
+	if (FindIntersectionConeRay(r,h,q,v,Contact))
+	{
+		dMULTIPLY0_331(contact->normal,cone->final_posr->R,Contact[0].normal);
+		dMULTIPLY0_331(contact->pos,cone->final_posr->R,Contact[0].pos);
+		dOPE(contact->pos,+=,cone->final_posr->pos);
+		contact->depth = Contact[0].depth * dLENGTH(v);
+/*
+		dMatrix3 RI;
+		dRSetIdentity (RI);
+		dVector3 ss;
+		ss[0] = 0.01f;
+		ss[1] = 0.01f;
+		ss[2] = 0.01f;
+
+		dsSetColorAlpha (1,0,0,0.8f);
+		dsDrawBox(contact->pos,RI,ss);
+*/		
+		return 1;
+	}
+
+	return 0;
+}
+
+int dCollideConeSphere(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dConeClass);
+	dIASSERT (o2->type == dSphereClass);
+	dxCone		*cone = (dxCone*) o1;
+	
+	dxSphere ASphere(0,cone->radius);
+	dGeomSetRotation(&ASphere,cone->final_posr->R);
+	dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]);
+
+	return dCollideSphereSphere(&ASphere, o2, flags, contact, skip);
+}
+
+int dCollideConeBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dConeClass);
+	dIASSERT (o2->type == dBoxClass);
+	dxCone		*cone = (dxCone*) o1;
+	
+	dxSphere ASphere(0,cone->radius);
+	dGeomSetRotation(&ASphere,cone->final_posr->R);
+	dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]);
+
+	return dCollideSphereBox(&ASphere, o2, flags, contact, skip);
+}
+
+int dCollideCCylinderCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dCCylinderClass);
+	dIASSERT (o2->type == dConeClass);
+	dxCone		*cone = (dxCone*) o2;
+	
+	dxSphere ASphere(0,cone->radius);
+	dGeomSetRotation(&ASphere,cone->final_posr->R);
+	dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]);
+
+	return dCollideCCylinderSphere(o1, &ASphere, flags, contact, skip);
+}
+
+extern int dCollideSTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+
+int dCollideTriMeshCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dTriMeshClass);
+	dIASSERT (o2->type == dConeClass);
+	dxCone		*cone = (dxCone*) o2;
+
+	dxSphere ASphere(0,cone->radius);
+	dGeomSetRotation(&ASphere,cone->final_posr->R);
+	dGeomSetPosition(&ASphere,cone->final_posr->pos[0],cone->final_posr->pos[1],cone->final_posr->pos[2]);
+
+	return dCollideSTL(o1, &ASphere, flags, contact, skip);
+}
+
+
+	
+
+
Index: /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dTerrainY.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dTerrainY.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dTerrainY.cpp	(revision 216)
@@ -0,0 +1,662 @@
+//Benoit CHAPEROT 2003-2004 www.jstarlab.com
+//some code inspired by Magic Software
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_std_internal.h"
+#include "collision_util.h"
+//#include <drawstuff/drawstuff.h>
+#include "windows.h"
+#include "ode\ode.h"
+
+#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
+#define MAXCONTACT 10
+#define TERRAINTOL 0.0f
+
+static bool IsAPowerOfTwo(int f)
+{
+	dAASSERT(f!=0);
+	while ((f&1) != 1)	
+		f >>= 1;
+
+	return (f == 1);
+}
+
+static int GetPowerOfTwo(int f)
+{
+	dAASSERT(f!=0);
+	int n = 0;
+	while ((f&1) != 1)
+	{
+		n++;
+		f >>= 1;
+	}
+	
+	return n;
+}
+
+dxTerrainY::dxTerrainY (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) :
+dxGeom (space,bPlaceable)
+{
+	dIASSERT(IsAPowerOfTwo(nNumNodesPerSide));
+	dIASSERT(pHeights);
+	dIASSERT(vLength > 0.f);
+	dIASSERT(nNumNodesPerSide > 0);
+	type = dTerrainYClass;
+	m_vLength = vLength;
+	m_pHeights = new dReal[nNumNodesPerSide * nNumNodesPerSide];
+	dIASSERT(m_pHeights);
+	m_nNumNodesPerSide = nNumNodesPerSide;
+	m_vNodeLength = m_vLength / m_nNumNodesPerSide;
+	m_nNumNodesPerSideShift = GetPowerOfTwo(m_nNumNodesPerSide);
+	m_nNumNodesPerSideMask  = m_nNumNodesPerSide - 1;
+	m_vMinHeight = dInfinity;
+	m_vMaxHeight = -dInfinity;
+	m_bFinite = bFinite;
+
+	for (int i=0;i<nNumNodesPerSide * nNumNodesPerSide;i++)
+	{
+		m_pHeights[i] = pHeights[i];
+		if (m_pHeights[i] < m_vMinHeight)	m_vMinHeight = m_pHeights[i];
+		if (m_pHeights[i] > m_vMaxHeight)	m_vMaxHeight = m_pHeights[i];
+	}
+}
+
+dxTerrainY::~dxTerrainY()
+{
+	dIASSERT(m_pHeights);
+	delete [] m_pHeights;
+}
+
+void dxTerrainY::computeAABB()
+{
+	if (m_bFinite)
+	{
+		if (gflags & GEOM_PLACEABLE)
+		{
+			dReal dx[6],dy[6],dz[6];
+			dx[0] = 0;
+			dx[1] = final_posr->R[0] * m_vLength;
+			dx[2] = final_posr->R[1] * m_vMinHeight;
+			dx[3] = final_posr->R[1] * m_vMaxHeight;
+			dx[4] = 0;
+			dx[5] = final_posr->R[2] * m_vLength;
+
+			dy[0] = 0;
+			dy[1] = final_posr->R[4] * m_vLength;
+			dy[2] = final_posr->R[5] * m_vMinHeight;
+			dy[3] = final_posr->R[5] * m_vMaxHeight;
+			dy[4] = 0;
+			dy[5] = final_posr->R[6] * m_vLength;
+
+			dz[0]  = 0;
+			dz[1]  = final_posr->R[8] * m_vLength;
+			dz[2]  = final_posr->R[9] * m_vMinHeight;
+			dz[3]  = final_posr->R[9] * m_vMaxHeight;
+			dz[4]  = 0;
+			dz[5]  = final_posr->R[10] * m_vLength;
+
+			aabb[0] = final_posr->pos[0] + MIN(dx[0],dx[1]) + MIN(dx[2],dx[3]) + MIN(dx[4],dx[5]);
+			aabb[1] = final_posr->pos[0] + MAX(dx[0],dx[1]) + MAX(dx[2],dx[3]) + MAX(dx[4],dx[5]);
+			aabb[2] = final_posr->pos[1] + MIN(dy[0],dy[1]) + MIN(dy[2],dy[3]) + MIN(dy[4],dy[5]);
+			aabb[3] = final_posr->pos[1] + MAX(dy[0],dy[1]) + MAX(dy[2],dy[3]) + MAX(dy[4],dy[5]);
+			aabb[4] = final_posr->pos[2] + MIN(dz[0],dz[1]) + MIN(dz[2],dz[3]) + MIN(dz[4],dz[5]);
+			aabb[5] = final_posr->pos[2] + MAX(dz[0],dz[1]) + MAX(dz[2],dz[3]) + MAX(dz[4],dz[5]);
+		}
+		else
+		{
+			aabb[0] = 0;
+			aabb[1] = m_vLength;
+			aabb[2] = m_vMinHeight;
+			aabb[3] = m_vMaxHeight;
+			aabb[4] = 0;
+			aabb[5] = m_vLength;
+		}
+	}
+	else
+	{
+		if (gflags & GEOM_PLACEABLE)
+		{
+			aabb[0] = -dInfinity;
+			aabb[1] = dInfinity;
+			aabb[2] = -dInfinity;
+			aabb[3] = dInfinity;
+			aabb[4] = -dInfinity;
+			aabb[5] = dInfinity;
+		}
+		else
+		{
+			aabb[0] = -dInfinity;
+			aabb[1] = dInfinity;
+			aabb[2] = m_vMinHeight;
+			aabb[3] = m_vMaxHeight;
+			aabb[4] = -dInfinity;
+			aabb[5] = dInfinity;
+		}
+	}
+}
+
+dReal dxTerrainY::GetHeight(int x,int z)
+{
+	return m_pHeights[	(((unsigned int)(z) & m_nNumNodesPerSideMask) << m_nNumNodesPerSideShift)
+					+	 ((unsigned int)(x) & m_nNumNodesPerSideMask)];
+}
+
+dReal dxTerrainY::GetHeight(dReal x,dReal z)
+{
+	int nX		= int(floor(x / m_vNodeLength));
+	int nZ		= int(floor(z / m_vNodeLength));
+	dReal dx	= (x - (dReal(nX) * m_vNodeLength)) / m_vNodeLength;
+	dReal dz	= (z - (dReal(nZ) * m_vNodeLength)) / m_vNodeLength;
+	dIASSERT((dx >= 0.f) && (dx <= 1.f));
+	dIASSERT((dz >= 0.f) && (dz <= 1.f));
+
+	dReal y,y0;
+	
+	if (dx + dz < 1.f)
+	{
+		y0	= GetHeight(nX,nZ);
+		y	= y0	
+			+ (GetHeight(nX+1,nZ) - y0) * dx
+			+ (GetHeight(nX,nZ+1) - y0) * dz;
+	}
+	else
+	{
+		y0	= GetHeight(nX+1,nZ+1);
+		y	= y0	
+			+ (GetHeight(nX+1,nZ) - y0) * (1.f - dz)
+			+ (GetHeight(nX,nZ+1) - y0) * (1.f - dx);
+	}
+
+	return y;	
+}
+
+bool dxTerrainY::IsOnTerrain(int nx,int nz,int w,dReal *pos)
+{
+	dVector3 Min,Max;
+	Min[0] = nx * m_vNodeLength;
+	Min[2] = nz * m_vNodeLength;
+	Max[0] = (nx+1) * m_vNodeLength;
+	Max[2] = (nz+1) * m_vNodeLength;
+	dReal Tol = m_vNodeLength * TERRAINTOL;
+	
+	if ((pos[0]<Min[0]-Tol) || (pos[0]>Max[0]+Tol))
+		return false;
+
+	if ((pos[2]<Min[2]-Tol) || (pos[2]>Max[2]+Tol))
+		return false;
+
+	dReal dx	= (pos[0] - (dReal(nx) * m_vNodeLength)) / m_vNodeLength;
+	dReal dz	= (pos[2] - (dReal(nz) * m_vNodeLength)) / m_vNodeLength;
+
+	if ((w == 0) && (dx + dz > 1.f+TERRAINTOL))
+		return false;
+
+	if ((w == 1) && (dx + dz < 1.f-TERRAINTOL))
+		return false;
+
+	return true;
+}
+
+dGeomID dCreateTerrainY(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable)
+{
+	return new dxTerrainY(space, pHeights,vLength,nNumNodesPerSide,bFinite,bPlaceable);
+}
+
+dReal dGeomTerrainYPointDepth (dGeomID g, dReal x, dReal y, dReal z)
+{
+	dUASSERT (g && g->type == dTerrainYClass,"argument not a terrain");
+  g->recomputePosr();
+	dxTerrainY *t = (dxTerrainY*) g;
+	return t->GetHeight(x,z) - y;
+}
+
+typedef dReal dGetDepthFn(dGeomID g, dReal x, dReal y, dReal z);
+#define RECOMPUTE_RAYNORMAL
+//#define DO_RAYDEPTH
+
+#define DMESS(A)	\
+			dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).",	\
+					x,z,A,	\
+					pContact->depth,	\
+					dGeomSphereGetRadius(o2),		\
+					pContact->pos[0],	\
+					pContact->pos[1],	\
+					pContact->pos[2],	\
+					pContact->normal[0],	\
+					pContact->normal[1],	\
+					pContact->normal[2]);
+/*
+(y is up)
+
+A-B-E.x
+|/|
+C-D
+|
+F
+.
+z
+*/
+int dxTerrainY::dCollideTerrainUnit(
+	int x,int z,dxGeom *o2,int numMaxContacts,
+	int flags,dContactGeom *contact, int skip)
+{
+	dColliderFn *CollideRayN;
+	dColliderFn *CollideNPlane;
+	dGetDepthFn *GetDepth;
+	int numContacts = 0;
+	int numPlaneContacts = 0;
+	int i;
+	
+	if (numContacts == numMaxContacts)
+		return numContacts;
+
+	dContactGeom PlaneContact[MAXCONTACT];
+	flags = (flags & 0xffff0000) | MAXCONTACT;
+	
+	switch (o2->type)
+	{
+	case dSphereClass:
+		CollideRayN		= dCollideRaySphere;
+		CollideNPlane	= dCollideSpherePlane;
+		GetDepth		= dGeomSpherePointDepth;
+		break;
+	case dBoxClass:
+		CollideRayN		= dCollideRayBox;
+		CollideNPlane	= dCollideBoxPlane;
+		GetDepth		= dGeomBoxPointDepth;
+		break;
+	case dCCylinderClass:
+		CollideRayN		= dCollideRayCCylinder;
+		CollideNPlane	= dCollideCCylinderPlane;
+		GetDepth		= dGeomCCylinderPointDepth;
+		break;
+	case dRayClass:
+		CollideRayN		= NULL;
+		CollideNPlane	= dCollideRayPlane;
+		GetDepth		= NULL;
+		break;
+	case dConeClass:
+		CollideRayN		= dCollideRayCone;
+		CollideNPlane	= dCollideConePlane;
+		GetDepth		= dGeomConePointDepth;
+		break;
+	default:
+		dIASSERT(0);
+	}
+
+	dReal Plane[4],lBD,lCD,lBC;
+	dVector3 A,B,C,D,BD,CD,BC,AB,AC;
+	A[0] = x * m_vNodeLength;
+	A[2] = z* m_vNodeLength;
+	A[1] = GetHeight(x,z);
+	B[0] = (x+1) * m_vNodeLength;
+	B[2] = z * m_vNodeLength;
+	B[1] = GetHeight(x+1,z);
+	C[0] = x * m_vNodeLength;
+	C[2] = (z+1) * m_vNodeLength;
+	C[1] = GetHeight(x,z+1);
+	D[0] = (x+1) * m_vNodeLength;
+	D[2] = (z+1) * m_vNodeLength;
+	D[1] = GetHeight(x+1,z+1);
+
+	dOP(BC,-,C,B);
+	lBC = dLENGTH(BC);
+	dOPEC(BC,/=,lBC);
+
+	dOP(BD,-,D,B);
+	lBD = dLENGTH(BD);
+	dOPEC(BD,/=,lBD);
+
+	dOP(CD,-,D,C);
+	lCD = dLENGTH(CD);
+	dOPEC(CD,/=,lCD);
+
+	dOP(AB,-,B,A);
+	dNormalize3(AB);
+
+	dOP(AC,-,C,A);
+	dNormalize3(AC);
+
+	if (CollideRayN)
+	{
+#ifdef RECOMPUTE_RAYNORMAL
+		dVector3 E,F;
+		dVector3 CE,FB,AD;
+		dVector3 Normal[3];
+		E[0] = (x+2) * m_vNodeLength;
+		E[2] = z * m_vNodeLength;
+		E[1] = GetHeight(x+2,z);
+		F[0] = x * m_vNodeLength;
+		F[2] = (z+2) * m_vNodeLength;
+		F[1] = GetHeight(x,z+2);
+		dOP(AD,-,D,A);
+		dNormalize3(AD);
+		dOP(CE,-,E,C);
+		dNormalize3(CE);
+		dOP(FB,-,B,F);
+		dNormalize3(FB);
+
+		//BC
+		dCROSS(Normal[0],=,BC,AD);
+		dNormalize3(Normal[0]);
+
+		//BD
+		dCROSS(Normal[1],=,BD,CE);
+		dNormalize3(Normal[1]);
+
+		//CD
+		dCROSS(Normal[2],=,CD,FB);
+		dNormalize3(Normal[2]);
+#endif		
+		int nA[3],nB[3];
+		dContactGeom ContactA[3],ContactB[3];
+		dxRay rayBC(0,lBC);	
+		dGeomRaySet(&rayBC, B[0], B[1], B[2], BC[0], BC[1], BC[2]);
+		nA[0] = CollideRayN(&rayBC,o2,flags,&ContactA[0],sizeof(dContactGeom));
+		dGeomRaySet(&rayBC, C[0], C[1], C[2], -BC[0], -BC[1], -BC[2]);
+		nB[0] = CollideRayN(&rayBC,o2,flags,&ContactB[0],sizeof(dContactGeom));
+		
+		dxRay rayBD(0,lBD);	
+		dGeomRaySet(&rayBD, B[0], B[1], B[2], BD[0], BD[1], BD[2]);
+		nA[1] = CollideRayN(&rayBD,o2,flags,&ContactA[1],sizeof(dContactGeom));
+		dGeomRaySet(&rayBD, D[0], D[1], D[2], -BD[0], -BD[1], -BD[2]);
+		nB[1] = CollideRayN(&rayBD,o2,flags,&ContactB[1],sizeof(dContactGeom));
+	
+		dxRay rayCD(0,lCD);	
+		dGeomRaySet(&rayCD, C[0], C[1], C[2], CD[0], CD[1], CD[2]);
+		nA[2] = CollideRayN(&rayCD,o2,flags,&ContactA[2],sizeof(dContactGeom));
+		dGeomRaySet(&rayCD, D[0], D[1], D[2], -CD[0], -CD[1], -CD[2]);
+		nB[2] = CollideRayN(&rayCD,o2,flags,&ContactB[2],sizeof(dContactGeom));
+	
+		for (i=0;i<3;i++)
+		{
+			if (nA[i] & nB[i])
+			{
+				dContactGeom *pContact = CONTACT(contact,numContacts*skip);
+				pContact->pos[0] = (ContactA[i].pos[0] + ContactB[i].pos[0])/2;
+				pContact->pos[1] = (ContactA[i].pos[1] + ContactB[i].pos[1])/2;
+				pContact->pos[2] = (ContactA[i].pos[2] + ContactB[i].pos[2])/2;
+#ifdef RECOMPUTE_RAYNORMAL
+				pContact->normal[0] = -Normal[i][0];
+				pContact->normal[1] = -Normal[i][1];
+				pContact->normal[2] = -Normal[i][2];
+#else
+				pContact->normal[0] = (ContactA[i].normal[0] + ContactB[i].normal[0])/2;	//0.f;
+				pContact->normal[1] = (ContactA[i].normal[1] + ContactB[i].normal[1])/2;	//0.f;
+				pContact->normal[2] = (ContactA[i].normal[2] + ContactB[i].normal[2])/2;	//-1.f;
+				dNormalize3(pContact->normal);
+#endif
+#ifdef DO_RAYDEPTH
+				dxRay rayV(0,1000.f);
+				dGeomRaySet(&rayV,	pContact->pos[0],
+									pContact->pos[1],
+									pContact->pos[2],
+									-pContact->normal[0],
+									-pContact->normal[1],
+									-pContact->normal[2]);
+		
+				dContactGeom ContactV;
+				if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom)))
+				{
+					pContact->depth = ContactV.depth;
+					numContacts++;	
+				}
+#else
+
+            if (GetDepth == NULL)
+               {
+				   dxRay rayV(0,1000.f);
+				   dGeomRaySet(&rayV,	pContact->pos[0],
+									   pContact->pos[1],
+									   pContact->pos[2],
+									   -pContact->normal[0],
+									   -pContact->normal[1],
+									   -pContact->normal[2]);
+		
+				   dContactGeom ContactV;
+
+				   if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom)))
+				      {
+					   pContact->depth = ContactV.depth;
+					   numContacts++;	
+				      }
+               }
+            else
+               {
+				   pContact->depth =  GetDepth(o2,
+				      pContact->pos[0],
+				      pContact->pos[1],
+				      pContact->pos[2]);
+				   numContacts++;
+               }
+
+#endif
+				if (numContacts == numMaxContacts)
+					return numContacts;
+
+			}
+		}
+	}
+
+	dCROSS(Plane,=,AC,AB);
+	dNormalize3(Plane);
+	Plane[3] = Plane[0] * A[0] + Plane[1] * A[1] + Plane[2] * A[2];
+	dxPlane planeABC(0,Plane[0],Plane[1],Plane[2],Plane[3]);
+	numPlaneContacts = CollideNPlane(o2,&planeABC,flags,PlaneContact,sizeof(dContactGeom));
+
+	for (i=0;i<numPlaneContacts;i++)
+	{
+		if (IsOnTerrain(x,z,0,PlaneContact[i].pos))
+		{
+			dContactGeom *pContact = CONTACT(contact,numContacts*skip);
+			pContact->pos[0] = PlaneContact[i].pos[0];
+			pContact->pos[1] = PlaneContact[i].pos[1];
+			pContact->pos[2] = PlaneContact[i].pos[2];
+			pContact->normal[0] = -PlaneContact[i].normal[0];
+			pContact->normal[1] = -PlaneContact[i].normal[1];
+			pContact->normal[2] = -PlaneContact[i].normal[2];
+			pContact->depth = PlaneContact[i].depth;
+
+			//DMESS(0);
+			numContacts++;
+
+			if (numContacts == numMaxContacts)
+					return numContacts;
+		}
+	}
+
+	dCROSS(Plane,=,BD,CD);
+	dNormalize3(Plane);
+	Plane[3] = Plane[0] * D[0] + Plane[1] * D[1] + Plane[2] * D[2];
+	dxPlane planeDCB(0,Plane[0],Plane[1],Plane[2],Plane[3]);
+	numPlaneContacts = CollideNPlane(o2,&planeDCB,flags,PlaneContact,sizeof(dContactGeom));
+
+	for (i=0;i<numPlaneContacts;i++)
+	{
+		if (IsOnTerrain(x,z,1,PlaneContact[i].pos))
+		{
+			dContactGeom *pContact = CONTACT(contact,numContacts*skip);
+			pContact->pos[0] = PlaneContact[i].pos[0];
+			pContact->pos[1] = PlaneContact[i].pos[1];
+			pContact->pos[2] = PlaneContact[i].pos[2];
+			pContact->normal[0] = -PlaneContact[i].normal[0];
+			pContact->normal[1] = -PlaneContact[i].normal[1];
+			pContact->normal[2] = -PlaneContact[i].normal[2];
+			pContact->depth = PlaneContact[i].depth;
+			//DMESS(1);
+			numContacts++;
+
+			if (numContacts == numMaxContacts)
+					return numContacts;
+		}
+	}
+
+	return numContacts;
+}
+
+int dCollideTerrainY(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dTerrainYClass);
+	int i,j;
+
+	if ((flags & 0xffff) == 0)
+		flags = (flags & 0xffff0000) | 1;
+
+	int numMaxTerrainContacts = (flags & 0xffff);
+	dxTerrainY *terrain = (dxTerrainY*) o1;
+
+	dReal aabbbak[6];
+	int gflagsbak;
+
+	dVector3 pos0;
+	int numTerrainContacts = 0;
+
+	dxPosR *bak;
+   dxPosR X1;
+	
+	if (terrain->gflags & GEOM_PLACEABLE)
+	{
+		dOP(pos0,-,o2->final_posr->pos,terrain->final_posr->pos);
+		dMULTIPLY1_331(X1.pos,terrain->final_posr->R,pos0);
+		dMULTIPLY1_333(X1.R,terrain->final_posr->R,o2->final_posr->R);
+		bak = o2->final_posr;
+		o2->final_posr = &X1;
+		memcpy(aabbbak,o2->aabb,sizeof(dReal)*6);
+		gflagsbak = o2->gflags;
+		o2->computeAABB();
+	}
+
+	int nMinX	= int(floor(o2->aabb[0] / terrain->m_vNodeLength));
+	int nMaxX	= int(floor(o2->aabb[1] / terrain->m_vNodeLength)) + 1;
+	int nMinZ	= int(floor(o2->aabb[4] / terrain->m_vNodeLength));
+	int nMaxZ	= int(floor(o2->aabb[5] / terrain->m_vNodeLength)) + 1;
+
+	if (terrain->m_bFinite)
+	{
+		nMinX = MAX(nMinX,0);
+		nMaxX = MIN(nMaxX,terrain->m_nNumNodesPerSide);
+		nMinZ = MAX(nMinZ,0);
+		nMaxZ = MIN(nMaxZ,terrain->m_nNumNodesPerSide);
+
+		if ((nMinX >= nMaxX) || (nMinZ >= nMaxZ))
+			goto dCollideTerrainYExit;
+	}
+	
+	dVector3 AabbTop;
+	AabbTop[0] = (o2->aabb[0]+o2->aabb[1]) / 2;
+	AabbTop[2] = (o2->aabb[4]+o2->aabb[5]) / 2;
+	AabbTop[1] = o2->aabb[3];
+	if (o2->type != dRayClass)
+	{
+		dReal AabbTopDepth = terrain->GetHeight(AabbTop[0],AabbTop[2]) - AabbTop[1];
+		if (AabbTopDepth > 0.f)
+		{
+			contact->depth = AabbTopDepth;
+			dReal MaxDepth = (o2->aabb[3]-o2->aabb[2]) / 2;
+			if (contact->depth > MaxDepth)
+				contact->depth = MaxDepth;
+			contact->g1 = o1;
+			contact->g2 = o2;
+			dOPE(contact->pos,=,AabbTop);
+			contact->normal[0] = 0.f;
+			contact->normal[1] = -1.f;
+			contact->normal[2] = 0.f;
+
+			numTerrainContacts = 1;
+			goto dCollideTerrainYExit;
+		}
+	}
+		
+	for (i=nMinX;i<nMaxX;i++)
+	{
+		for (j=nMinZ;j<nMaxZ;j++)
+		{
+			numTerrainContacts += terrain->dCollideTerrainUnit(
+				i,j,o2,numMaxTerrainContacts - numTerrainContacts,
+				flags,CONTACT(contact,numTerrainContacts*skip),skip	);
+		}
+	}
+
+	dIASSERT(numTerrainContacts <= numMaxTerrainContacts);
+
+	for (i=0; i<numTerrainContacts; i++) 
+	{
+		CONTACT(contact,i*skip)->g1 = o1;
+		CONTACT(contact,i*skip)->g2 = o2;
+	}
+
+dCollideTerrainYExit:
+
+	if (terrain->gflags & GEOM_PLACEABLE)
+	{
+      o2->final_posr = bak;
+		memcpy(o2->aabb,aabbbak,sizeof(dReal)*6);
+		o2->gflags = gflagsbak;
+
+		for (i=0; i<numTerrainContacts; i++) 
+		{
+			dOPE(pos0,=,CONTACT(contact,i*skip)->pos);
+			dMULTIPLY0_331(CONTACT(contact,i*skip)->pos,terrain->final_posr->R,pos0);
+			dOP(CONTACT(contact,i*skip)->pos,+,CONTACT(contact,i*skip)->pos,terrain->final_posr->pos);
+
+			dOPE(pos0,=,CONTACT(contact,i*skip)->normal);
+			dMULTIPLY0_331(CONTACT(contact,i*skip)->normal,terrain->final_posr->R,pos0);
+		}
+	}
+
+	return numTerrainContacts;
+}
+/*
+void dsDrawTerrainY(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos)
+{
+	float A[3],B[3],C[3],D[3];
+	float R[12];
+	float pos[3];
+	if (pR)
+		memcpy(R,pR,sizeof(R));
+	else
+	{
+		memset(R,0,sizeof(R));
+		R[0] = 1.f;
+		R[5] = 1.f;
+		R[10] = 1.f;
+	}
+	
+	if (ppos)
+		memcpy(pos,ppos,sizeof(pos));
+	else
+		memset(pos,0,sizeof(pos));
+	
+	float vx,vz;
+	vx = vLength * x;
+	vz = vLength * z;
+	
+	int i;
+	for (i=0;i<nNumNodesPerSide;i++)
+	{
+		for (int j=0;j<nNumNodesPerSide;j++)
+		{
+			A[0] = i * vNodeLength + vx;
+			A[2] = j * vNodeLength + vz;
+			A[1] = GetHeight(i,j,nNumNodesPerSide,pHeights);
+			B[0] = (i+1) * vNodeLength + vx;
+			B[2] = j * vNodeLength + vz;
+			B[1] = GetHeight(i+1,j,nNumNodesPerSide,pHeights);
+			C[0] = i * vNodeLength + vx;
+			C[2] = (j+1) * vNodeLength + vz;
+			C[1] = GetHeight(i,j+1,nNumNodesPerSide,pHeights);
+			D[0] = (i+1) * vNodeLength + vx;
+			D[2] = (j+1) * vNodeLength + vz;
+			D[1] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights);
+			dsDrawTriangle(pos,R,C,B,A,1);
+			dsDrawTriangle(pos,R,D,B,C,1);
+		}
+	}
+}
+*/
Index: /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dTerrainZ.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dTerrainZ.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/TerrainAndCone/dTerrainZ.cpp	(revision 216)
@@ -0,0 +1,659 @@
+//Benoit CHAPEROT 2003-2004 www.jstarlab.com
+//some code inspired by Magic Software
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_std_internal.h"
+#include "collision_util.h"
+//#include <drawstuff/drawstuff.h>
+#include "windows.h"
+#include "ode\ode.h"
+
+#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
+#define MAXCONTACT 10
+#define TERRAINTOL 0.0f
+
+static bool IsAPowerOfTwo(int f)
+{
+	dAASSERT(f!=0);
+	while ((f&1) != 1)	
+		f >>= 1;
+
+	return (f == 1);
+}
+
+static int GetPowerOfTwo(int f)
+{
+	dAASSERT(f!=0);
+	int n = 0;
+	while ((f&1) != 1)
+	{
+		n++;
+		f >>= 1;
+	}
+	
+	return n;
+}
+
+dxTerrainZ::dxTerrainZ (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable) :
+dxGeom (space,bPlaceable)
+{
+	dIASSERT(IsAPowerOfTwo(nNumNodesPerSide));
+	dIASSERT(pHeights);
+	dIASSERT(vLength > 0.f);
+	dIASSERT(nNumNodesPerSide > 0);
+	type = dTerrainZClass;
+	m_vLength = vLength;
+	m_pHeights = new dReal[nNumNodesPerSide * nNumNodesPerSide];
+	dIASSERT(m_pHeights);
+	m_nNumNodesPerSide = nNumNodesPerSide;
+	m_vNodeLength = m_vLength / m_nNumNodesPerSide;
+	m_nNumNodesPerSideShift = GetPowerOfTwo(m_nNumNodesPerSide);
+	m_nNumNodesPerSideMask  = m_nNumNodesPerSide - 1;
+	m_vMinHeight = dInfinity;
+	m_vMaxHeight = -dInfinity;
+	m_bFinite = bFinite;
+
+	for (int i=0;i<nNumNodesPerSide * nNumNodesPerSide;i++)
+	{
+		m_pHeights[i] = pHeights[i];
+		if (m_pHeights[i] < m_vMinHeight)	m_vMinHeight = m_pHeights[i];
+		if (m_pHeights[i] > m_vMaxHeight)	m_vMaxHeight = m_pHeights[i];
+	}
+}
+
+dxTerrainZ::~dxTerrainZ()
+{
+	dIASSERT(m_pHeights);
+	delete [] m_pHeights;
+}
+
+void dxTerrainZ::computeAABB()
+{
+	if (m_bFinite)
+	{
+		if (gflags & GEOM_PLACEABLE)
+		{
+			dReal dx[6],dy[6],dz[6];
+			dx[0] = 0;
+			dx[1] = final_posr->R[0] * m_vLength;
+			dx[2] = 0;
+			dx[3] = final_posr->R[1] * m_vLength;
+			dx[4] = final_posr->R[2] * m_vMinHeight;
+			dx[5] = final_posr->R[2] * m_vMaxHeight;
+			
+			dy[0] = 0;
+			dy[1] = final_posr->R[4] * m_vLength;
+			dy[2] = 0;
+			dy[3] = final_posr->R[5] * m_vLength;
+			dy[4] = final_posr->R[6] * m_vMinHeight;
+			dy[5] = final_posr->R[6] * m_vMaxHeight;
+			
+			dz[0]  = 0;
+			dz[1]  = final_posr->R[8] * m_vLength;
+			dz[2]  = 0;
+			dz[3]  = final_posr->R[9] * m_vLength;
+			dz[4]  = final_posr->R[10] * m_vMinHeight;
+			dz[5]  = final_posr->R[10] * m_vMaxHeight;
+
+			aabb[0] = final_posr->pos[0] + MIN(dx[0],dx[1]) + MIN(dx[2],dx[3]) + MIN(dx[4],dx[5]);
+			aabb[1] = final_posr->pos[0] + MAX(dx[0],dx[1]) + MAX(dx[2],dx[3]) + MAX(dx[4],dx[5]);
+			aabb[2] = final_posr->pos[1] + MIN(dy[0],dy[1]) + MIN(dy[2],dy[3]) + MIN(dy[4],dy[5]);
+			aabb[3] = final_posr->pos[1] + MAX(dy[0],dy[1]) + MAX(dy[2],dy[3]) + MAX(dy[4],dy[5]);
+			aabb[4] = final_posr->pos[2] + MIN(dz[0],dz[1]) + MIN(dz[2],dz[3]) + MIN(dz[4],dz[5]);
+			aabb[5] = final_posr->pos[2] + MAX(dz[0],dz[1]) + MAX(dz[2],dz[3]) + MAX(dz[4],dz[5]);
+		}
+		else
+		{
+			aabb[0] = 0;
+			aabb[1] = m_vLength;
+			aabb[2] = 0;
+			aabb[3] = m_vLength;
+			aabb[4] = m_vMinHeight;
+			aabb[5] = m_vMaxHeight;
+		}
+	}
+	else
+	{
+		if (gflags & GEOM_PLACEABLE)
+		{
+			aabb[0] = -dInfinity;
+			aabb[1] = dInfinity;
+			aabb[2] = -dInfinity;
+			aabb[3] = dInfinity;
+			aabb[4] = -dInfinity;
+			aabb[5] = dInfinity;
+		}
+		else
+		{
+			aabb[0] = -dInfinity;
+			aabb[1] = dInfinity;
+			aabb[2] = -dInfinity;
+			aabb[3] = dInfinity;
+			aabb[4] = m_vMinHeight;
+			aabb[5] = m_vMaxHeight;
+		}
+	}
+}
+
+dReal dxTerrainZ::GetHeight(int x,int y)
+{
+	return m_pHeights[	(((unsigned int)(y) & m_nNumNodesPerSideMask) << m_nNumNodesPerSideShift)
+					+	 ((unsigned int)(x) & m_nNumNodesPerSideMask)];
+}
+
+dReal dxTerrainZ::GetHeight(dReal x,dReal y)
+{
+	int nX		= int(floor(x / m_vNodeLength));
+	int nY		= int(floor(y / m_vNodeLength));
+	dReal dx	= (x - (dReal(nX) * m_vNodeLength)) / m_vNodeLength;
+	dReal dy	= (y - (dReal(nY) * m_vNodeLength)) / m_vNodeLength;
+	dIASSERT((dx >= 0.f) && (dx <= 1.f));
+	dIASSERT((dy >= 0.f) && (dy <= 1.f));
+
+	dReal z,z0;
+	
+	if (dx + dy < 1.f)
+	{
+		z0	= GetHeight(nX,nY);
+		z	= z0	
+			+ (GetHeight(nX+1,nY) - z0) * dx
+			+ (GetHeight(nX,nY+1) - z0) * dy;
+	}
+	else
+	{
+		z0	= GetHeight(nX+1,nY+1);
+		z	= z0	
+			+ (GetHeight(nX+1,nY) - z0) * (1.f - dy)
+			+ (GetHeight(nX,nY+1) - z0) * (1.f - dx);
+	}
+
+	return z;	
+}
+
+bool dxTerrainZ::IsOnTerrain(int nx,int ny,int w,dReal *pos)
+{
+	dVector3 Min,Max;
+	Min[0] = nx * m_vNodeLength;
+	Min[1] = ny * m_vNodeLength;
+	Max[0] = (nx+1) * m_vNodeLength;
+	Max[1] = (ny+1) * m_vNodeLength;
+	dReal Tol = m_vNodeLength * TERRAINTOL;
+	
+	if ((pos[0]<Min[0]-Tol) || (pos[0]>Max[0]+Tol))
+		return false;
+
+	if ((pos[1]<Min[1]-Tol) || (pos[1]>Max[1]+Tol))
+		return false;
+
+	dReal dx	= (pos[0] - (dReal(nx) * m_vNodeLength)) / m_vNodeLength;
+	dReal dy	= (pos[1] - (dReal(ny) * m_vNodeLength)) / m_vNodeLength;
+
+	if ((w == 0) && (dx + dy > 1.f+TERRAINTOL))
+		return false;
+
+	if ((w == 1) && (dx + dy < 1.f-TERRAINTOL))
+		return false;
+
+	return true;
+}
+
+dGeomID dCreateTerrainZ(dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable)
+{
+	return new dxTerrainZ(space, pHeights,vLength,nNumNodesPerSide, bFinite, bPlaceable);
+}
+
+dReal dGeomTerrainZPointDepth (dGeomID g, dReal x, dReal y, dReal z)
+{
+	dUASSERT (g && g->type == dTerrainZClass,"argument not a terrain");
+  g->recomputePosr();
+	dxTerrainZ *t = (dxTerrainZ*) g;
+	return t->GetHeight(x,y) - z;
+}
+
+typedef dReal dGetDepthFn(dGeomID g, dReal x, dReal y, dReal z);
+#define RECOMPUTE_RAYNORMAL
+//#define DO_RAYDEPTH
+
+#define DMESS(A)	\
+			dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).",	\
+					x,y,A,	\
+					pContact->depth,	\
+					dGeomSphereGetRadius(o2),		\
+					pContact->pos[0],	\
+					pContact->pos[1],	\
+					pContact->pos[2],	\
+					pContact->normal[0],	\
+					pContact->normal[1],	\
+					pContact->normal[2]);
+/*
+(z is up)
+
+y
+.
+F
+|
+C-D
+|\|
+A-B-E.x
+*/
+int dxTerrainZ::dCollideTerrainUnit(
+	int x,int y,dxGeom *o2,int numMaxContacts,
+	int flags,dContactGeom *contact, int skip)
+{
+	dColliderFn *CollideRayN;
+	dColliderFn *CollideNPlane;
+	dGetDepthFn *GetDepth;
+	int numContacts = 0;
+	int numPlaneContacts = 0;
+	int i;
+	
+	if (numContacts == numMaxContacts)
+		return numContacts;
+
+	dContactGeom PlaneContact[MAXCONTACT];
+	flags = (flags & 0xffff0000) | MAXCONTACT;
+	
+	switch (o2->type)
+	{
+	case dSphereClass:
+		CollideRayN		= dCollideRaySphere;
+		CollideNPlane	= dCollideSpherePlane;
+		GetDepth		= dGeomSpherePointDepth;
+		break;
+	case dBoxClass:
+		CollideRayN		= dCollideRayBox;
+		CollideNPlane	= dCollideBoxPlane;
+		GetDepth		= dGeomBoxPointDepth;
+		break;
+	case dCCylinderClass:
+		CollideRayN		= dCollideRayCCylinder;
+		CollideNPlane	= dCollideCCylinderPlane;
+		GetDepth		= dGeomCCylinderPointDepth;
+		break;
+	case dRayClass:
+		CollideRayN		= NULL;
+		CollideNPlane	= dCollideRayPlane;
+		GetDepth		= NULL;
+		break;
+	case dConeClass:
+		CollideRayN		= dCollideRayCone;
+		CollideNPlane	= dCollideConePlane;
+		GetDepth		= dGeomConePointDepth;
+		break;
+	default:
+		dIASSERT(0);
+	}
+
+	dReal Plane[4],lBD,lCD,lBC;
+	dVector3 A,B,C,D,BD,CD,BC,AB,AC;
+	A[0] = x * m_vNodeLength;
+	A[1] = y * m_vNodeLength;
+	A[2] = GetHeight(x,y);
+	B[0] = (x+1) * m_vNodeLength;
+	B[1] = y * m_vNodeLength;
+	B[2] = GetHeight(x+1,y);
+	C[0] = x * m_vNodeLength;
+	C[1] = (y+1) * m_vNodeLength;
+	C[2] = GetHeight(x,y+1);
+	D[0] = (x+1) * m_vNodeLength;
+	D[1] = (y+1) * m_vNodeLength;
+	D[2] = GetHeight(x+1,y+1);
+
+	dOP(BC,-,C,B);
+	lBC = dLENGTH(BC);
+	dOPEC(BC,/=,lBC);
+
+	dOP(BD,-,D,B);
+	lBD = dLENGTH(BD);
+	dOPEC(BD,/=,lBD);
+
+	dOP(CD,-,D,C);
+	lCD = dLENGTH(CD);
+	dOPEC(CD,/=,lCD);
+
+	dOP(AB,-,B,A);
+	dNormalize3(AB);
+
+	dOP(AC,-,C,A);
+	dNormalize3(AC);
+
+	if (CollideRayN)
+	{
+#ifdef RECOMPUTE_RAYNORMAL
+		dVector3 E,F;
+		dVector3 CE,FB,AD;
+		dVector3 Normal[3];
+		E[0] = (x+2) * m_vNodeLength;
+		E[1] = y * m_vNodeLength;
+		E[2] = GetHeight(x+2,y);
+		F[0] = x * m_vNodeLength;
+		F[1] = (y+2) * m_vNodeLength;
+		F[2] = GetHeight(x,y+2);
+		dOP(AD,-,D,A);
+		dNormalize3(AD);
+		dOP(CE,-,E,C);
+		dNormalize3(CE);
+		dOP(FB,-,B,F);
+		dNormalize3(FB);
+
+		//BC
+		dCROSS(Normal[0],=,AD,BC);
+		dNormalize3(Normal[0]);
+
+		//BD
+		dCROSS(Normal[1],=,CE,BD);
+		dNormalize3(Normal[1]);
+
+		//CD
+		dCROSS(Normal[2],=,FB,CD);
+		dNormalize3(Normal[2]);
+#endif		
+		int nA[3],nB[3];
+		dContactGeom ContactA[3],ContactB[3];
+		dxRay rayBC(0,lBC);	
+		dGeomRaySet(&rayBC, B[0], B[1], B[2], BC[0], BC[1], BC[2]);
+		nA[0] = CollideRayN(&rayBC,o2,flags,&ContactA[0],sizeof(dContactGeom));
+		dGeomRaySet(&rayBC, C[0], C[1], C[2], -BC[0], -BC[1], -BC[2]);
+		nB[0] = CollideRayN(&rayBC,o2,flags,&ContactB[0],sizeof(dContactGeom));
+		
+		dxRay rayBD(0,lBD);	
+		dGeomRaySet(&rayBD, B[0], B[1], B[2], BD[0], BD[1], BD[2]);
+		nA[1] = CollideRayN(&rayBD,o2,flags,&ContactA[1],sizeof(dContactGeom));
+		dGeomRaySet(&rayBD, D[0], D[1], D[2], -BD[0], -BD[1], -BD[2]);
+		nB[1] = CollideRayN(&rayBD,o2,flags,&ContactB[1],sizeof(dContactGeom));
+	
+		dxRay rayCD(0,lCD);	
+		dGeomRaySet(&rayCD, C[0], C[1], C[2], CD[0], CD[1], CD[2]);
+		nA[2] = CollideRayN(&rayCD,o2,flags,&ContactA[2],sizeof(dContactGeom));
+		dGeomRaySet(&rayCD, D[0], D[1], D[2], -CD[0], -CD[1], -CD[2]);
+		nB[2] = CollideRayN(&rayCD,o2,flags,&ContactB[2],sizeof(dContactGeom));
+	
+		for (i=0;i<3;i++)
+		{
+			if (nA[i] & nB[i])
+			{
+				dContactGeom *pContact = CONTACT(contact,numContacts*skip);
+				pContact->pos[0] = (ContactA[i].pos[0] + ContactB[i].pos[0])/2;
+				pContact->pos[1] = (ContactA[i].pos[1] + ContactB[i].pos[1])/2;
+				pContact->pos[2] = (ContactA[i].pos[2] + ContactB[i].pos[2])/2;
+#ifdef RECOMPUTE_RAYNORMAL
+				pContact->normal[0] = -Normal[i][0];
+				pContact->normal[1] = -Normal[i][1];
+				pContact->normal[2] = -Normal[i][2];
+#else
+				pContact->normal[0] = (ContactA[i].normal[0] + ContactB[i].normal[0])/2;	//0.f;
+				pContact->normal[1] = (ContactA[i].normal[1] + ContactB[i].normal[1])/2;	//0.f;
+				pContact->normal[2] = (ContactA[i].normal[2] + ContactB[i].normal[2])/2;	//-1.f;
+				dNormalize3(pContact->normal);
+#endif
+#ifdef DO_RAYDEPTH
+				dxRay rayV(0,1000.f);
+				dGeomRaySet(&rayV,	pContact->pos[0],
+									pContact->pos[1],
+									pContact->pos[2],
+									-pContact->normal[0],
+									-pContact->normal[1],
+									-pContact->normal[2]);
+		
+				dContactGeom ContactV;
+				if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom)))
+				{
+					pContact->depth = ContactV.depth;
+					numContacts++;	
+				}
+#else
+            if (GetDepth == NULL)
+               {
+				   dxRay rayV(0,1000.f);
+				   dGeomRaySet(&rayV,	pContact->pos[0],
+									   pContact->pos[1],
+									   pContact->pos[2],
+									   -pContact->normal[0],
+									   -pContact->normal[1],
+									   -pContact->normal[2]);
+		
+				   dContactGeom ContactV;
+				   if (CollideRayN(&rayV,o2,flags,&ContactV,sizeof(dContactGeom)))
+				   {
+					   pContact->depth = ContactV.depth;
+					   numContacts++;	
+				   }
+               }
+            else
+               {
+				   pContact->depth =  GetDepth(o2,
+				   pContact->pos[0],
+				   pContact->pos[1],
+				   pContact->pos[2]);
+				   numContacts++;
+               }
+#endif
+				if (numContacts == numMaxContacts)
+					return numContacts;
+
+			}
+		}
+	}
+
+	dCROSS(Plane,=,AB,AC);
+	dNormalize3(Plane);
+	Plane[3] = Plane[0] * A[0] + Plane[1] * A[1] + Plane[2] * A[2];
+	dxPlane planeABC(0,Plane[0],Plane[1],Plane[2],Plane[3]);
+	numPlaneContacts = CollideNPlane(o2,&planeABC,flags,PlaneContact,sizeof(dContactGeom));
+
+	for (i=0;i<numPlaneContacts;i++)
+	{
+		if (IsOnTerrain(x,y,0,PlaneContact[i].pos))
+		{
+			dContactGeom *pContact = CONTACT(contact,numContacts*skip);
+			pContact->pos[0] = PlaneContact[i].pos[0];
+			pContact->pos[1] = PlaneContact[i].pos[1];
+			pContact->pos[2] = PlaneContact[i].pos[2];
+			pContact->normal[0] = -PlaneContact[i].normal[0];
+			pContact->normal[1] = -PlaneContact[i].normal[1];
+			pContact->normal[2] = -PlaneContact[i].normal[2];
+			pContact->depth = PlaneContact[i].depth;
+
+			//DMESS(0);
+			numContacts++;
+
+			if (numContacts == numMaxContacts)
+					return numContacts;
+		}
+	}
+
+	dCROSS(Plane,=,CD,BD);
+	dNormalize3(Plane);
+	Plane[3] = Plane[0] * D[0] + Plane[1] * D[1] + Plane[2] * D[2];
+	dxPlane planeDCB(0,Plane[0],Plane[1],Plane[2],Plane[3]);
+	numPlaneContacts = CollideNPlane(o2,&planeDCB,flags,PlaneContact,sizeof(dContactGeom));
+
+	for (i=0;i<numPlaneContacts;i++)
+	{
+		if (IsOnTerrain(x,y,1,PlaneContact[i].pos))
+		{
+			dContactGeom *pContact = CONTACT(contact,numContacts*skip);
+			pContact->pos[0] = PlaneContact[i].pos[0];
+			pContact->pos[1] = PlaneContact[i].pos[1];
+			pContact->pos[2] = PlaneContact[i].pos[2];
+			pContact->normal[0] = -PlaneContact[i].normal[0];
+			pContact->normal[1] = -PlaneContact[i].normal[1];
+			pContact->normal[2] = -PlaneContact[i].normal[2];
+			pContact->depth = PlaneContact[i].depth;
+			//DMESS(1);
+			numContacts++;
+
+			if (numContacts == numMaxContacts)
+					return numContacts;
+		}
+	}
+
+	return numContacts;
+}
+
+int dCollideTerrainZ(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dTerrainZClass);
+	int i,j;
+
+	if ((flags & 0xffff) == 0)
+		flags = (flags & 0xffff0000) | 1;
+
+	int numMaxTerrainContacts = (flags & 0xffff);
+	dxTerrainZ *terrain = (dxTerrainZ*) o1;
+
+	dReal aabbbak[6];
+	int gflagsbak;
+
+	dVector3 pos0;
+	int numTerrainContacts = 0;
+
+	dxPosR *bak;
+   dxPosR X1;
+
+	if (terrain->gflags & GEOM_PLACEABLE)
+	{
+		dOP(pos0,-,o2->final_posr->pos,terrain->final_posr->pos);
+		dMULTIPLY1_331(X1.pos,terrain->final_posr->R,pos0);
+		dMULTIPLY1_333(X1.R,terrain->final_posr->R,o2->final_posr->R);
+		bak = o2->final_posr;
+		o2->final_posr = &X1;
+		memcpy(aabbbak,o2->aabb,sizeof(dReal)*6);
+		gflagsbak = o2->gflags;
+		o2->computeAABB();
+	}
+
+	int nMinX	= int(floor(o2->aabb[0] / terrain->m_vNodeLength));
+	int nMaxX	= int(floor(o2->aabb[1] / terrain->m_vNodeLength)) + 1;
+	int nMinY	= int(floor(o2->aabb[2] / terrain->m_vNodeLength));
+	int nMaxY	= int(floor(o2->aabb[3] / terrain->m_vNodeLength)) + 1;
+
+	if (terrain->m_bFinite)
+	{
+		nMinX = MAX(nMinX,0);
+		nMaxX = MIN(nMaxX,terrain->m_nNumNodesPerSide);
+		nMinY = MAX(nMinY,0);
+		nMaxY = MIN(nMaxY,terrain->m_nNumNodesPerSide);
+
+		if ((nMinX >= nMaxX) || (nMinY >= nMaxY))
+			goto dCollideTerrainZExit;
+	}
+
+	dVector3 AabbTop;
+	AabbTop[0] = (o2->aabb[0]+o2->aabb[1]) / 2;
+	AabbTop[1] = (o2->aabb[2]+o2->aabb[3]) / 2;
+	AabbTop[2] = o2->aabb[5];
+	if (o2->type != dRayClass)
+	{
+		dReal AabbTopDepth = terrain->GetHeight(AabbTop[0],AabbTop[1]) - AabbTop[2];
+		if (AabbTopDepth > 0.f)
+		{
+			contact->depth = AabbTopDepth;
+			dReal MaxDepth = (o2->aabb[5]-o2->aabb[4]) / 2;
+			if (contact->depth > MaxDepth)
+				contact->depth = MaxDepth;
+			contact->g1 = o1;
+			contact->g2 = o2;
+			dOPE(contact->pos,=,AabbTop);
+			contact->normal[0] = 0.f;
+			contact->normal[1] = 0.f;
+			contact->normal[2] = -1.f;
+
+			numTerrainContacts = 1;
+			goto dCollideTerrainZExit;
+		}
+	}
+	
+	for (i=nMinX;i<nMaxX;i++)
+	{
+		for (j=nMinY;j<nMaxY;j++)
+		{
+			numTerrainContacts += terrain->dCollideTerrainUnit(
+				i,j,o2,numMaxTerrainContacts - numTerrainContacts,
+				flags,CONTACT(contact,numTerrainContacts*skip),skip	);
+		}
+	}
+
+	dIASSERT(numTerrainContacts <= numMaxTerrainContacts);
+
+	for (i=0; i<numTerrainContacts; i++) 
+	{
+		CONTACT(contact,i*skip)->g1 = o1;
+		CONTACT(contact,i*skip)->g2 = o2;
+	}
+
+dCollideTerrainZExit:
+
+	if (terrain->gflags & GEOM_PLACEABLE)
+	{
+      o2->final_posr = bak;
+		memcpy(o2->aabb,aabbbak,sizeof(dReal)*6);
+		o2->gflags = gflagsbak;
+
+		for (i=0; i<numTerrainContacts; i++) 
+		{
+			dOPE(pos0,=,CONTACT(contact,i*skip)->pos);
+			dMULTIPLY0_331(CONTACT(contact,i*skip)->pos,terrain->final_posr->R,pos0);
+			dOP(CONTACT(contact,i*skip)->pos,+,CONTACT(contact,i*skip)->pos,terrain->final_posr->pos);
+
+			dOPE(pos0,=,CONTACT(contact,i*skip)->normal);
+			dMULTIPLY0_331(CONTACT(contact,i*skip)->normal,terrain->final_posr->R,pos0);
+		}
+	}
+
+	return numTerrainContacts;
+}
+/*
+void dsDrawTerrainZ(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos)
+{
+	float A[3],B[3],C[3],D[3];
+	float R[12];
+	float pos[3];
+	if (pR)
+		memcpy(R,pR,sizeof(R));
+	else
+	{
+		memset(R,0,sizeof(R));
+		R[0] = 1.f;
+		R[5] = 1.f;
+		R[10] = 1.f;
+	}
+	
+	if (ppos)
+		memcpy(pos,ppos,sizeof(pos));
+	else
+		memset(pos,0,sizeof(pos));
+	
+	float vx,vz;
+	vx = vLength * x;
+	vz = vLength * z;
+	
+	int i;
+	for (i=0;i<nNumNodesPerSide;i++)
+	{
+		for (int j=0;j<nNumNodesPerSide;j++)
+		{
+			A[0] = i * vNodeLength + vx;
+			A[1] = j * vNodeLength + vz;
+			A[2] = GetHeight(i,j,nNumNodesPerSide,pHeights);
+			B[0] = (i+1) * vNodeLength + vx;
+			B[1] = j * vNodeLength + vz;
+			B[2] = GetHeight(i+1,j,nNumNodesPerSide,pHeights);
+			C[0] = i * vNodeLength + vx;
+			C[1] = (j+1) * vNodeLength + vz;
+			C[2] = GetHeight(i,j+1,nNumNodesPerSide,pHeights);
+			D[0] = (i+1) * vNodeLength + vx;
+			D[1] = (j+1) * vNodeLength + vz;
+			D[2] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights);
+			dsDrawTriangle(pos,R,C,A,B,1);
+			dsDrawTriangle(pos,R,D,C,B,1);
+		}
+	}
+}
+*/
Index: /code/branches/ode/ode-0.9/contrib/TerrainAndCone/readme.txt
===================================================================
--- /code/branches/ode/ode-0.9/contrib/TerrainAndCone/readme.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/TerrainAndCone/readme.txt	(revision 216)
@@ -0,0 +1,322 @@
+Benoit CHAPEROT 2003-2004 www.jstarlab.com
+Support for terrain and cones, collision and drawing.
+
+Terrains can be with z up (dTerrainZ) or y up (dTerrainY).
+Terrains are defined by a height field.
+Terrains are now placeable.
+Terrains can now be finite or infinite (repeat themselve in the x and (y or z) directions).
+
+Terrains can potentially collide with everything that collides with planes and rays; 
+see the switch statement.
+
+Cones currently collides only with terrain and planes and rays.
+Cones, with high radius to height ratios are perfect to simulate vehicle wheels on terrains.
+
+
+
+There was an error in the depths returned by dCollideTerrain.
+Plus now contacts are not sorted according to their depths.
+Contact sorting is now supposed to be done externally. 
+Not all dCollide functions seem to sort contacts according to depth.
+Requesting a high number of contacts, sorting them and then considering only the most significant contacts
+is a good way I think to improve stability.
+* Cones Collisions with spheres, boxes, ccylinder and trimesh are now roughly approximated using sphere collisions.
+
+You will need to complete the following operations (with ODE 0.039):
+
+*** add to folder ode\src:
+
+dCone.cpp        
+dTerrainY.cpp 
+dTerrainZ.cpp 
+collision_std_internal.h
+
+On linux => edit each .cpp file and comment out     #include "windows.h"    &    #include "ode\ode.h"
+
+
+*** add to drawstuff\src\drawstuff.cpp:
+
+static void drawCone(float l, float r)
+{
+  int i;
+  float tmp,ny,nz,a,ca,sa;
+  const int n = 24;	// number of sides to the cone (divisible by 4)
+
+  a = float(M_PI*2.0)/float(n);
+  sa = (float) sin(a);
+  ca = (float) cos(a);
+
+  // draw top
+  glShadeModel (GL_FLAT);
+  ny=1; nz=0;		  // normal vector = (0,ny,nz)
+  glBegin (GL_TRIANGLE_FAN);
+  glNormal3d (0,0,1);
+  glVertex3d (0,0,l);
+  for (i=0; i<=n; i++) {
+    if (i==1 || i==n/2+1)
+      setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
+    glNormal3d (ny*r,nz*r,0);
+    glVertex3d (ny*r,nz*r,0);
+    if (i==1 || i==n/2+1)
+      setColor (color[0],color[1],color[2],color[3]);
+
+    // rotate ny,nz
+    tmp = ca*ny - sa*nz;
+    nz = sa*ny + ca*nz;
+    ny = tmp;
+  }
+  glEnd();
+
+  // draw bottom
+  ny=1; nz=0;		  // normal vector = (0,ny,nz)
+  glBegin (GL_TRIANGLE_FAN);
+  glNormal3d (0,0,-1);
+  glVertex3d (0,0,0);
+  for (i=0; i<=n; i++) {
+    if (i==1 || i==n/2+1)
+      setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
+    glNormal3d (0,0,-1);
+    glVertex3d (ny*r,nz*r,0);
+    if (i==1 || i==n/2+1)
+      setColor (color[0],color[1],color[2],color[3]);
+
+    // rotate ny,nz
+    tmp = ca*ny + sa*nz;
+    nz = -sa*ny + ca*nz;
+    ny = tmp;
+  }
+  glEnd();
+}
+
+void dsDrawCone (const float pos[3], const float R[12], float length, float radius)
+{
+	if (current_state != 2) dsError ("drawing function called outside simulation loop");
+	setupDrawingMode();
+	glShadeModel (GL_SMOOTH);
+	setTransform (pos,R);
+	drawCone (length,radius);
+	glPopMatrix();
+	
+	if (use_shadows) {
+		setShadowDrawingMode();
+		setShadowTransform();
+		setTransform (pos,R);
+		drawCone (length,radius);
+		glPopMatrix();
+		glPopMatrix();
+		glDepthRange (0,1);
+	}
+}
+
+void dsDrawConeD (const double pos[3], const double R[12], float length, float radius)
+{
+  int i;
+  float pos2[3],R2[12];
+  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
+  for (i=0; i<12; i++) R2[i]=(float)R[i];
+  dsDrawCone(pos2,R2,length,radius);
+}
+
+static float GetHeight(int x,int y,int nNumNodesPerSide,float *pHeights)
+{
+	int nNumNodesPerSideMask = nNumNodesPerSide - 1;
+	return pHeights[	(((unsigned int)(y) & nNumNodesPerSideMask) * nNumNodesPerSide)
+					+	 ((unsigned int)(x) & nNumNodesPerSideMask)];
+}
+
+void dsDrawTerrainY(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos)
+{
+	float A[3],B[3],C[3],D[3];
+	float R[12];
+	float pos[3];
+	if (pR)
+		memcpy(R,pR,sizeof(R));
+	else
+	{
+		memset(R,0,sizeof(R));
+		R[0] = 1.f;
+		R[5] = 1.f;
+		R[10] = 1.f;
+	}
+	
+	if (ppos)
+		memcpy(pos,ppos,sizeof(pos));
+	else
+		memset(pos,0,sizeof(pos));
+	
+	float vx,vz;
+	vx = vLength * x;
+	vz = vLength * z;
+	
+	int i;
+	for (i=0;i<nNumNodesPerSide;i++)
+	{
+		for (int j=0;j<nNumNodesPerSide;j++)
+		{
+			A[0] = i * vNodeLength + vx;
+			A[2] = j * vNodeLength + vz;
+			A[1] = GetHeight(i,j,nNumNodesPerSide,pHeights);
+			B[0] = (i+1) * vNodeLength + vx;
+			B[2] = j * vNodeLength + vz;
+			B[1] = GetHeight(i+1,j,nNumNodesPerSide,pHeights);
+			C[0] = i * vNodeLength + vx;
+			C[2] = (j+1) * vNodeLength + vz;
+			C[1] = GetHeight(i,j+1,nNumNodesPerSide,pHeights);
+			D[0] = (i+1) * vNodeLength + vx;
+			D[2] = (j+1) * vNodeLength + vz;
+			D[1] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights);
+			dsDrawTriangle(pos,R,C,B,A,1);
+			dsDrawTriangle(pos,R,D,B,C,1);
+		}
+	}
+}
+
+void dsDrawTerrainZ(int x,int z,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos)
+{
+	float A[3],B[3],C[3],D[3];
+	float R[12];
+	float pos[3];
+	if (pR)
+		memcpy(R,pR,sizeof(R));
+	else
+	{
+		memset(R,0,sizeof(R));
+		R[0] = 1.f;
+		R[5] = 1.f;
+		R[10] = 1.f;
+	}
+	
+	if (ppos)
+		memcpy(pos,ppos,sizeof(pos));
+	else
+		memset(pos,0,sizeof(pos));
+	
+	float vx,vz;
+	vx = vLength * x;
+	vz = vLength * z;
+	
+	int i;
+	for (i=0;i<nNumNodesPerSide;i++)
+	{
+		for (int j=0;j<nNumNodesPerSide;j++)
+		{
+			A[0] = i * vNodeLength + vx;
+			A[1] = j * vNodeLength + vz;
+			A[2] = GetHeight(i,j,nNumNodesPerSide,pHeights);
+			B[0] = (i+1) * vNodeLength + vx;
+			B[1] = j * vNodeLength + vz;
+			B[2] = GetHeight(i+1,j,nNumNodesPerSide,pHeights);
+			C[0] = i * vNodeLength + vx;
+			C[1] = (j+1) * vNodeLength + vz;
+			C[2] = GetHeight(i,j+1,nNumNodesPerSide,pHeights);
+			D[0] = (i+1) * vNodeLength + vx;
+			D[1] = (j+1) * vNodeLength + vz;
+			D[2] = GetHeight(i+1,j+1,nNumNodesPerSide,pHeights);
+			dsDrawTriangle(pos,R,C,A,B,1);
+			dsDrawTriangle(pos,R,D,C,B,1);
+		}
+	}
+}
+
+*** add to include\drawstuff\drawstuff.h:
+void dsDrawCone (const float pos[3], const float R[12],	float length, float radius);
+void dsDrawConeD (const double pos[3], const double R[12], float length, float radius);
+void dsDrawTerrainY(int x,int y,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos);
+void dsDrawTerrainZ(int x,int y,float vLength,float vNodeLength,int nNumNodesPerSide,float *pHeights,const float *pR,const float *ppos);
+
+*** add in include\ode\collision.h line 77:
+/* class numbers - each geometry object needs a unique number */
+enum {
+  dSphereClass = 0,
+  dBoxClass,
+  dCCylinderClass,
+  dCylinderClass,
+  dPlaneClass,
+  dRayClass,
+  dGeomTransformClass,
+  dTriMeshClass,
+
+  dTerrainYClass,	//here
+  dTerrainZClass,	//here
+  dConeClass,		//here
+
+  dFirstSpaceClass,
+  dSimpleSpaceClass = dFirstSpaceClass,
+  dHashSpaceClass,
+  dQuadTreeSpaceClass,
+
+  dLastSpaceClass = dQuadTreeSpaceClass,
+
+  dFirstUserClass,
+  dLastUserClass = dFirstUserClass + dMaxUserClasses - 1,
+  dGeomNumClasses
+};
+
+dGeomID dCreateTerrainY (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable);
+dReal dGeomTerrainYPointDepth (dGeomID g, dReal x, dReal y, dReal z);
+dGeomID dCreateTerrainZ (dSpaceID space, dReal *pHeights,dReal vLength,int nNumNodesPerSide, int bFinite, int bPlaceable);
+dReal dGeomTerrainZPointDepth (dGeomID g, dReal x, dReal y, dReal z);
+
+dGeomID dCreateCone(dSpaceID space, dReal radius, dReal length);
+void dGeomConeSetParams (dGeomID cone, dReal radius, dReal length);
+void dGeomConeGetParams (dGeomID cone, dReal *radius, dReal *length);
+dReal dGeomConePointDepth(dGeomID g, dReal x, dReal y, dReal z);
+
+*** add in include\ode\odemath.h:
+#define dOP(a,op,b,c) \
+  (a)[0] = ((b)[0]) op ((c)[0]); \
+  (a)[1] = ((b)[1]) op ((c)[1]); \
+  (a)[2] = ((b)[2]) op ((c)[2]);
+#define dOPC(a,op,b,c) \
+  (a)[0] = ((b)[0]) op (c); \
+  (a)[1] = ((b)[1]) op (c); \
+  (a)[2] = ((b)[2]) op (c);
+#define dOPE(a,op,b) \
+  (a)[0] op ((b)[0]); \
+  (a)[1] op ((b)[1]); \
+  (a)[2] op ((b)[2]);
+#define dOPEC(a,op,c) \
+  (a)[0] op (c); \
+  (a)[1] op (c); \
+  (a)[2] op (c);
+#define dLENGTH(a) \
+	(dSqrt( ((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]) ));
+#define dLENGTHSQUARED(a) \
+	(((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]));
+
+*** add in ode\src\collision_kernel.cpp function  'static void initColliders()'  next to other 'setCollider' calls:
+  setCollider (dTerrainYClass,dSphereClass,&dCollideTerrainY);
+  setCollider (dTerrainYClass,dBoxClass,&dCollideTerrainY);
+  setCollider (dTerrainYClass,dCCylinderClass,&dCollideTerrainY);
+  setCollider (dTerrainYClass,dRayClass,&dCollideTerrainY);
+  setCollider (dTerrainYClass,dConeClass,&dCollideTerrainY);
+
+  setCollider (dTerrainZClass,dSphereClass,&dCollideTerrainZ);
+  setCollider (dTerrainZClass,dBoxClass,&dCollideTerrainZ);
+  setCollider (dTerrainZClass,dCCylinderClass,&dCollideTerrainZ);
+  setCollider (dTerrainZClass,dRayClass,&dCollideTerrainZ);
+  setCollider (dTerrainZClass,dConeClass,&dCollideTerrainZ);
+
+  setCollider (dRayClass,dConeClass,&dCollideRayCone);
+  setCollider (dConeClass,dPlaneClass,&dCollideConePlane);
+  setCollider (dConeClass,dSphereClass,&dCollideConeSphere);
+  setCollider (dConeClass,dBoxClass,&dCollideConeBox);
+  setCollider (dCCylinderClass,dConeClass,&dCollideCCylinderCone);
+  setCollider (dTriMeshClass,dConeClass,&dCollideTriMeshCone);
+
+*** add in ode\src\collision_std.h:
+int dCollideTerrainY(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip);
+int dCollideTerrainZ(dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip);
+
+int dCollideConePlane (dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip);
+int dCollideRayCone (dxGeom *o1, dxGeom *o2, int flags,dContactGeom *contact, int skip);
+int dCollideConeSphere(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideConeBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideCCylinderCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideTriMeshCone(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+
+*** add dCone.cpp, dTerrainY.cpp and dTerrainZ.cpp to the the ODE_SRC variable in the makefile
+On Linux => add dCone.cpp, dTerrainY.cpp and dTerrainZ.cpp to the the libode_a_SOURCES variable in the ode/src/Makefile.am file.
+
+*** now you can now test using file test_boxstackb.cpp (to add in folder ode\test).
+
Index: /code/branches/ode/ode-0.9/contrib/TerrainAndCone/test_boxstackb.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/TerrainAndCone/test_boxstackb.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/TerrainAndCone/test_boxstackb.cpp	(revision 216)
@@ -0,0 +1,1375 @@
+/*************************************************************************
+
+
+*																		 *
+
+
+* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.		 *
+
+
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org 		 *
+
+
+*																		 *
+
+
+* This library is free software; you can redistribute it and/or		 *
+
+
+* modify it under the terms of EITHER: 								 *
+
+
+*	 (1) The GNU Lesser General Public License as published by the Free  *
+
+
+*		 Software Foundation; either version 2.1 of the License, or (at  *
+
+
+*		 your option) any later version. The text of the GNU Lesser 	 *
+
+
+*		 General Public License is included with this library in the	 *
+
+
+*		 file LICENSE.TXT.												 *
+
+
+*	 (2) The BSD-style license that is included with this library in	 *
+
+
+*		 the file LICENSE-BSD.TXT.										 *
+
+
+*																		 *
+
+
+* This library is distributed in the hope that it will be useful,		 *
+
+
+* but WITHOUT ANY WARRANTY; without even the implied warranty of		 *
+
+
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files	 *
+
+
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.					 *
+
+
+*																		 *
+
+
+*************************************************************************/
+
+
+
+
+
+#include <ode/ode.h>
+
+
+#include <drawstuff/drawstuff.h>
+
+
+
+
+
+#ifdef _MSC_VER
+
+
+#pragma warning(disable:4244 4305)	// for VC++, no precision loss complaints
+
+
+#endif
+
+
+
+
+
+// select correct drawing functions
+
+
+
+
+
+#ifdef dDOUBLE
+
+
+#define dsDrawBox dsDrawBoxD
+
+
+#define dsDrawSphere dsDrawSphereD
+
+
+#define dsDrawCylinder dsDrawCylinderD
+
+
+#define dsDrawCappedCylinder dsDrawCappedCylinderD
+
+
+#endif
+
+
+
+
+
+
+
+
+// some constants
+
+
+
+
+
+const dReal vTerrainLength = 4.f;
+
+
+const dReal vTerrainHeight = 0.5f;
+
+
+const int TERRAINNODES = 4;
+
+
+dReal pTerrainHeights[TERRAINNODES*TERRAINNODES];
+
+
+
+
+
+dGeomID terrainZ = NULL;
+
+
+dGeomID terrainY = NULL;
+
+
+
+
+
+#define NUM 20			// max number of objects
+
+
+#define DENSITY (5.0)		// density of all objects
+
+
+#define GPB 3			// maximum number of geometries per body
+
+
+#define MAX_CONTACTS 4		// maximum number of contact points per body
+
+
+
+
+
+
+
+
+// dynamics and collision objects
+
+
+
+
+
+struct MyObject {
+
+
+	dBodyID body; 		// the body
+
+
+	dGeomID geom[GPB];		// geometries representing this body
+
+
+};
+
+
+
+
+
+static int num=0;		// number of objects in simulation
+
+
+static int nextobj=0;		// next object to recycle if num==NUM
+
+
+static dWorldID world;
+
+
+static dSpaceID space;
+
+
+static MyObject obj[NUM];
+
+
+static dJointGroupID contactgroup;
+
+
+static int selected = -1;	// selected object
+
+
+static int show_aabb = 0;	// show geom AABBs?
+
+
+static int show_contacts = 0;	// show contact points?
+
+
+static int random_pos = 1;	// drop objects from random position?
+
+
+
+
+
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+
+
+// potentially colliding.
+
+
+
+
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+
+
+{
+
+
+	int i;
+
+
+	// if (o1->body && o2->body) return;
+
+
+	
+
+
+	// exit without doing anything if the two bodies are connected by a joint
+
+
+	dBodyID b1 = dGeomGetBody(o1);
+
+
+	dBodyID b2 = dGeomGetBody(o2);
+
+
+	if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+
+
+	
+
+
+	dContact contact[MAX_CONTACTS];	// up to MAX_CONTACTS contacts per box-box
+
+
+	for (i=0; i<MAX_CONTACTS; i++) {
+
+
+		contact[i].surface.mode = dContactBounce | dContactApprox1;	//dContactSoftCFM;
+
+
+		contact[i].surface.mu = dInfinity;
+
+
+		contact[i].surface.mu2 = 0;
+
+
+		contact[i].surface.bounce = 0.1;
+
+
+		contact[i].surface.bounce_vel = 0.1;
+
+
+		contact[i].surface.soft_cfm = 0.01;
+
+
+	}
+
+
+	if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
+
+
+		sizeof(dContact))) {
+
+
+		dMatrix3 RI;
+
+
+		dRSetIdentity (RI);
+
+
+		const dReal ss[3] = {0.02,0.02,0.02};
+
+
+		for (i=0; i<numc; i++) {
+
+
+			dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+
+
+			dJointAttach (c,b1,b2);
+
+
+			if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
+
+
+		}
+
+
+	}
+
+
+}
+
+
+
+
+
+
+
+
+// start simulation - set viewpoint
+
+
+
+
+
+static void start()
+
+
+{
+
+
+	static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+
+
+	static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+
+
+	dsSetViewpoint (xyz,hpr);
+
+
+	printf ("To drop another object, press:\n");
+
+
+	printf ("   b for box.\n");
+
+
+	printf ("   s for sphere.\n");
+
+
+	printf ("   c for cylinder.\n");
+
+
+	printf ("   x for a composite object.\n");
+
+
+	printf ("To select an object, press space.\n");
+
+
+	printf ("To disable the selected object, press d.\n");
+
+
+	printf ("To enable the selected object, press e.\n");
+
+
+	printf ("To toggle showing the geom AABBs, press a.\n");
+
+
+	printf ("To toggle showing the contact points, press t.\n");
+
+
+	printf ("To toggle dropping from random position/orientation, press r.\n");
+
+
+}
+
+
+
+
+
+
+
+
+char locase (char c)
+
+
+{
+
+
+	if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+
+
+	else return c;
+
+
+}
+
+
+
+
+
+
+
+
+// called when a key pressed
+
+
+
+
+
+static void command (int cmd)
+
+
+{
+
+
+	int i,j,k;
+
+
+	dReal sides[3];
+
+
+	dMass m;
+
+
+	
+
+
+	cmd = locase (cmd);
+
+
+	if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x'
+
+
+		/* || cmd == 'l' */) {
+
+
+		if (num < NUM) {
+
+
+			i = num;
+
+
+			num++;
+
+
+		}
+
+
+		else {
+
+
+			i = nextobj;
+
+
+			nextobj++;
+
+
+			if (nextobj >= num) nextobj = 0;
+
+
+			
+
+
+			// destroy the body and geoms for slot i
+
+
+			dBodyDestroy (obj[i].body);
+
+
+			for (k=0; k < GPB; k++) {
+
+
+				if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+
+
+			}
+
+
+			memset (&obj[i],0,sizeof(obj[i]));
+
+
+		}
+
+
+		
+
+
+		obj[i].body = dBodyCreate (world);
+
+
+		for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+
+		
+
+
+		dMatrix3 R;
+
+
+		if (random_pos) {
+
+
+			dBodySetPosition (obj[i].body,
+
+
+				dRandReal()*2-1,dRandReal()*2+1,dRandReal()+3);
+
+
+			dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+
+
+				dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+
+
+		}
+
+
+		else {
+
+
+			dReal maxheight = 0;
+
+
+			for (k=0; k<num; k++) {
+
+
+				const dReal *pos = dBodyGetPosition (obj[k].body);
+
+
+				if (pos[2] > maxheight) maxheight = pos[2];
+
+
+			}
+
+
+			dBodySetPosition (obj[i].body, 0,maxheight+1,maxheight+3);
+
+
+			dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
+
+
+		}
+
+
+		dBodySetRotation (obj[i].body,R);
+
+
+		dBodySetData (obj[i].body,(void*) i);
+
+
+		
+
+
+		if (cmd == 'b') {
+
+
+			dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+
+
+			obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+
+
+		}
+
+
+		else if (cmd == 'c') {
+
+
+			sides[0] *= 0.5;
+
+
+			dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
+
+
+			obj[i].geom[0] = dCreateCCylinder (space,sides[0],sides[1]);
+
+
+		}
+
+
+		/*
+
+
+		// cylinder option not yet implemented
+
+
+		else if (cmd == 'l') {
+
+
+		sides[1] *= 0.5;
+
+
+		dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
+
+
+		obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
+
+
+		}
+
+
+		*/
+
+
+		else if (cmd == 's') {
+
+
+			sides[0] *= 0.5;
+
+
+			dMassSetSphere (&m,DENSITY,sides[0]);
+
+
+			obj[i].geom[0] = dCreateSphere (space,sides[0]);
+
+
+		}
+
+
+		else if (cmd == 'x') {
+
+
+			dGeomID g2[GPB];		// encapsulated geometries
+
+
+			dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+
+			
+
+
+			// start accumulating masses for the encapsulated geometries
+
+
+			dMass m2;
+
+
+			dMassSetZero (&m);
+
+
+			
+
+
+			// set random delta positions
+
+
+			for (j=0; j<GPB; j++) {
+
+
+				for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+
+
+			}
+
+
+			
+
+
+			for (k=0; k<GPB; k++) {
+
+
+				obj[i].geom[k] = dCreateGeomTransform (space);
+
+
+				dGeomTransformSetCleanup (obj[i].geom[k],1);
+
+
+				if (k==0) {
+
+
+					dReal radius = dRandReal()*0.25+0.05;
+
+
+					g2[k] = dCreateSphere (0,radius);
+
+
+					dMassSetSphere (&m2,DENSITY,radius);
+
+
+				}
+
+
+				else if (k==1) {
+
+
+					g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+
+
+					dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+
+
+				}
+
+
+				else {
+
+
+					dReal radius = dRandReal()*0.1+0.05;
+
+
+					dReal length = dRandReal()*1.0+0.1;
+
+
+					g2[k] = dCreateCCylinder (0,radius,length);
+
+
+					dMassSetCappedCylinder (&m2,DENSITY,3,radius,length);
+
+
+				}
+
+
+				dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+
+				
+
+
+				// set the transformation (adjust the mass too)
+
+
+				dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+
+
+				dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+
+
+				dMatrix3 Rtx;
+
+
+				dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+
+
+					dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+
+
+				dGeomSetRotation (g2[k],Rtx);
+
+
+				dMassRotate (&m2,Rtx);
+
+
+				
+
+
+				// add to the total mass
+
+
+				dMassAdd (&m,&m2);
+
+
+			}
+
+
+			
+
+
+			// move all encapsulated objects so that the center of mass is (0,0,0)
+
+
+			for (k=0; k<2; k++) {
+
+
+				dGeomSetPosition (g2[k],
+
+
+					dpos[k][0]-m.c[0],
+
+
+					dpos[k][1]-m.c[1],
+
+
+					dpos[k][2]-m.c[2]);
+
+
+			}
+
+
+			dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+
+
+		}
+
+
+		
+
+
+		for (k=0; k < GPB; k++) {
+
+
+			if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+
+
+		}
+
+
+		
+
+
+		dBodySetMass (obj[i].body,&m);
+
+
+  }
+
+
+  
+
+
+  if (cmd == ' ') {
+
+
+	  selected++;
+
+
+	  if (selected >= num) selected = 0;
+
+
+	  if (selected < 0) selected = 0;
+
+
+  }
+
+
+  else if (cmd == 'd' && selected >= 0 && selected < num) {
+
+
+	  dBodyDisable (obj[selected].body);
+
+
+  }
+
+
+  else if (cmd == 'e' && selected >= 0 && selected < num) {
+
+
+	  dBodyEnable (obj[selected].body);
+
+
+  }
+
+
+  else if (cmd == 'a') {
+
+
+	  show_aabb ^= 1;
+
+
+  }
+
+
+  else if (cmd == 't') {
+
+
+	  show_contacts ^= 1;
+
+
+  }
+
+
+  else if (cmd == 'r') {
+
+
+	  random_pos ^= 1;
+
+
+  }
+
+
+}
+
+
+
+
+
+
+
+
+// draw a geom
+
+
+
+
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
+
+
+{
+
+
+	int i;
+
+
+	
+
+
+	if (!g) return;
+
+
+	if (!pos) pos = dGeomGetPosition (g);
+
+
+	if (!R) R = dGeomGetRotation (g);
+
+
+	
+
+
+	int type = dGeomGetClass (g);
+
+
+	if (type == dBoxClass) {
+
+
+		dVector3 sides;
+
+
+		dGeomBoxGetLengths (g,sides);
+
+
+		dsDrawBox (pos,R,sides);
+
+
+	}
+
+
+	else if (type == dSphereClass) {
+
+
+		dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+
+
+	}
+
+
+	else if (type == dCCylinderClass) {
+
+
+		dReal radius,length;
+
+
+		dGeomCCylinderGetParams (g,&radius,&length);
+
+
+		dsDrawCappedCylinder (pos,R,length,radius);
+
+
+	}
+
+
+	/*
+
+
+	// cylinder option not yet implemented
+
+
+	else if (type == dCylinderClass) {
+
+
+	dReal radius,length;
+
+
+	dGeomCylinderGetParams (g,&radius,&length);
+
+
+	dsDrawCylinder (pos,R,length,radius);
+
+
+	}
+
+
+	*/
+
+
+	else if (type == dGeomTransformClass) {
+
+
+		dGeomID g2 = dGeomTransformGetGeom (g);
+
+
+		const dReal *pos2 = dGeomGetPosition (g2);
+
+
+		const dReal *R2 = dGeomGetRotation (g2);
+
+
+		dVector3 actual_pos;
+
+
+		dMatrix3 actual_R;
+
+
+		dMULTIPLY0_331 (actual_pos,R,pos2);
+
+
+		actual_pos[0] += pos[0];
+
+
+		actual_pos[1] += pos[1];
+
+
+		actual_pos[2] += pos[2];
+
+
+		dMULTIPLY0_333 (actual_R,R,R2);
+
+
+		drawGeom (g2,actual_pos,actual_R,0);
+
+
+	}
+
+
+	
+
+
+	if (show_aabb) {
+
+
+		// draw the bounding box for this geom
+
+
+		dReal aabb[6];
+
+
+		dGeomGetAABB (g,aabb);
+
+
+		dVector3 bbpos;
+
+
+		for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+
+
+		dVector3 bbsides;
+
+
+		for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
+
+
+		dMatrix3 RI;
+
+
+		dRSetIdentity (RI);
+
+
+		dsSetColorAlpha (1,0,0,0.5);
+
+
+		dsDrawBox (bbpos,RI,bbsides);
+
+
+	}
+
+
+}
+
+
+
+
+
+
+
+
+// simulation loop
+
+
+
+
+
+static void simLoop (int pause)
+
+
+{
+
+
+	dsSetColor (0,0,2);
+
+
+	dSpaceCollide (space,0,&nearCallback);
+
+
+	if (!pause) dWorldStep (world,0.05);
+
+
+
+
+
+	dAASSERT(terrainY);
+
+
+	dAASSERT(terrainZ);
+
+
+	dsSetColor (0,1,0);
+
+
+	dsDrawTerrainY(0,0,vTerrainLength,vTerrainLength/TERRAINNODES,TERRAINNODES,pTerrainHeights,dGeomGetRotation(terrainY),dGeomGetPosition(terrainY));
+
+
+	dsDrawTerrainZ(0,0,vTerrainLength,vTerrainLength/TERRAINNODES,TERRAINNODES,pTerrainHeights,dGeomGetRotation(terrainZ),dGeomGetPosition(terrainZ));
+
+
+
+
+
+	if (show_aabb) 
+
+
+	{
+
+
+		dReal aabb[6];
+
+
+		dGeomGetAABB (terrainY,aabb);
+
+
+		dVector3 bbpos;
+
+
+		int i;
+
+
+		for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+
+
+		dVector3 bbsides;
+
+
+		for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
+
+
+		dMatrix3 RI;
+
+
+		dRSetIdentity (RI);
+
+
+		dsSetColorAlpha (1,0,0,0.5);
+
+
+		dsDrawBox (bbpos,RI,bbsides);
+
+
+
+
+
+		dGeomGetAABB (terrainZ,aabb);
+
+
+		for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+
+
+		for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
+
+
+		dsDrawBox (bbpos,RI,bbsides);
+
+
+	}
+
+
+
+
+
+	dsSetColor (1,1,0);
+
+
+	
+
+
+	// remove all contact joints
+
+
+	dJointGroupEmpty (contactgroup);
+
+
+	
+
+
+	dsSetColor (1,1,0);
+
+
+	dsSetTexture (DS_WOOD);
+
+
+	for (int i=0; i<num; i++) {
+
+
+		for (int j=0; j < GPB; j++) {
+
+
+			if (i==selected) {
+
+
+				dsSetColor (0,0.7,1);
+
+
+			}
+
+
+			else if (! dBodyIsEnabled (obj[i].body)) {
+
+
+				dsSetColor (1,0,0);
+
+
+			}
+
+
+			else {
+
+
+				dsSetColor (1,1,0);
+
+
+			}
+
+
+			drawGeom (obj[i].geom[j],0,0,show_aabb);
+
+
+		}
+
+
+	}
+
+
+}
+
+
+
+
+
+
+
+
+int main (int argc, char **argv)
+
+
+{
+
+
+	// setup pointers to drawstuff callback functions
+
+
+	dsFunctions fn;
+
+
+	fn.version = DS_VERSION;
+
+
+	fn.start = &start;
+
+
+	fn.step = &simLoop;
+
+
+	fn.command = &command;
+
+
+	fn.stop = 0;
+
+
+	fn.path_to_textures = "../../drawstuff/textures";
+
+
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+	
+
+
+	// create world
+
+
+	
+
+
+	world = dWorldCreate();
+
+
+	space = dHashSpaceCreate (0);
+
+
+	contactgroup = dJointGroupCreate (0);
+
+
+	dWorldSetGravity (world,0,0,-0.5); //-0.5
+
+
+	dWorldSetCFM (world,1e-5);
+
+
+	dCreatePlane (space,0,0,1,0);
+
+
+	memset (obj,0,sizeof(obj));
+
+
+
+
+
+	for (int i=0;i<TERRAINNODES*TERRAINNODES;i++)	pTerrainHeights[i] = vTerrainHeight * dRandReal();
+
+
+	terrainY = dCreateTerrainY(space,pTerrainHeights,vTerrainLength,TERRAINNODES,1,1);
+
+
+	terrainZ = dCreateTerrainZ(space,pTerrainHeights,vTerrainLength,TERRAINNODES,1,1);
+
+
+
+
+
+	dMatrix3 R;
+
+
+	dRFromZAxis(R, 0.2f, 0.2f, 0.2f);
+
+
+	dGeomSetPosition(terrainY,0.f,0.f,0.5f);
+
+
+	dGeomSetRotation(terrainY,R);
+
+
+	dGeomSetPosition(terrainZ,0.f,0.f,0.5f);
+
+
+	dGeomSetRotation(terrainZ,R);
+
+
+
+
+
+	// run simulation
+
+
+	dsSimulationLoop (argc,argv,352,288,&fn);
+
+
+	
+
+
+	dJointGroupDestroy (contactgroup);
+
+
+	dSpaceDestroy (space);
+
+
+	dWorldDestroy (world);
+
+
+	
+
+
+	return 0;
+
+
+}
+
+
Index: /code/branches/ode/ode-0.9/contrib/dCylinder/dCylinder.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dCylinder/dCylinder.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dCylinder/dCylinder.cpp	(revision 216)
@@ -0,0 +1,1445 @@
+#include <ode/ode.h>
+#include "dCylinder.h"
+// given a pointer `p' to a dContactGeom, return the dContactGeom at
+// p + skip bytes.
+
+struct dxCylinder {	// cylinder
+  dReal radius,lz;	// radius, length along y axis //
+};
+
+int dCylinderClassUser = -1;
+
+#define NUMC_MASK (0xffff)
+
+#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////circleIntersection//////////////////////////////////////////////////
+//this does following:
+//takes two circles as normals to planes n1,n2, center points cp1,cp2,and radiuses r1,r2
+//finds line on which circles' planes intersect
+//finds four points O1,O2 - intersection between the line and sphere with center cp1 radius r1
+//					O3,O4 - intersection between the line and sphere with center cp2 radius r2
+//returns false if there is no intersection
+//computes distances O1-O3, O1-O4, O2-O3, O2-O4
+//in "point" returns mean point between intersection points with smallest distance
+/////////////////////////////////////////////////////////////////////////////////////////////////
+inline bool circleIntersection(const dReal* n1,const dReal* cp1,dReal r1,const dReal* n2,const dReal* cp2,dReal r2,dVector3 point){
+dReal c1=dDOT14(cp1,n1);
+dReal c2=dDOT14(cp2,n2);
+dReal cos=dDOT44(n1,n2);
+dReal cos_2=cos*cos;
+dReal sin_2=1-cos_2;
+dReal p1=(c1-c2*cos)/sin_2;
+dReal p2=(c2-c1*cos)/sin_2;
+dVector3 lp={p1*n1[0]+p2*n2[0],p1*n1[4]+p2*n2[4],p1*n1[8]+p2*n2[8]};
+dVector3 n;
+dCROSS144(n,=,n1,n2);
+dVector3 LC1={lp[0]-cp1[0],lp[1]-cp1[1],lp[2]-cp1[2]};
+dVector3 LC2={lp[0]-cp2[0],lp[1]-cp2[1],lp[2]-cp2[2]};
+dReal A,B,C,B_A,B_A_2,D;
+dReal t1,t2,t3,t4;
+A=dDOT(n,n);
+B=dDOT(LC1,n);
+C=dDOT(LC1,LC1)-r1*r1;
+B_A=B/A;
+B_A_2=B_A*B_A;
+D=B_A_2-C;
+if(D<0.f){	//somewhat strange solution 
+			//- it is needed to set some 
+			//axis to sepparate cylinders
+			//when their edges approach
+	t1=-B_A+sqrtf(-D);
+	t2=-B_A-sqrtf(-D);
+//	return false;
+	}
+else{
+t1=-B_A-sqrtf(D);
+t2=-B_A+sqrtf(D);
+}
+B=dDOT(LC2,n);
+C=dDOT(LC2,LC2)-r2*r2;
+B_A=B/A;
+B_A_2=B_A*B_A;
+D=B_A_2-C;
+
+if(D<0.f) {
+	t3=-B_A+sqrtf(-D);
+	t4=-B_A-sqrtf(-D);
+//	return false;
+	}
+else{
+t3=-B_A-sqrtf(D);
+t4=-B_A+sqrtf(D);
+}
+dVector3 O1={lp[0]+n[0]*t1,lp[1]+n[1]*t1,lp[2]+n[2]*t1};
+dVector3 O2={lp[0]+n[0]*t2,lp[1]+n[1]*t2,lp[2]+n[2]*t2};
+
+dVector3 O3={lp[0]+n[0]*t3,lp[1]+n[1]*t3,lp[2]+n[2]*t3};
+dVector3 O4={lp[0]+n[0]*t4,lp[1]+n[1]*t4,lp[2]+n[2]*t4};
+
+dVector3 L1_3={O3[0]-O1[0],O3[1]-O1[1],O3[2]-O1[2]};
+dVector3 L1_4={O4[0]-O1[0],O4[1]-O1[1],O4[2]-O1[2]};
+
+dVector3 L2_3={O3[0]-O2[0],O3[1]-O2[1],O3[2]-O2[2]};
+dVector3 L2_4={O4[0]-O2[0],O4[1]-O2[1],O4[2]-O2[2]};
+
+
+dReal l1_3=dDOT(L1_3,L1_3);
+dReal l1_4=dDOT(L1_4,L1_4);
+
+dReal l2_3=dDOT(L2_3,L2_3);
+dReal l2_4=dDOT(L2_4,L2_4);
+
+
+if (l1_3<l1_4)
+	if(l2_3<l2_4)
+		if(l1_3<l2_3)
+			{
+			//l1_3;
+			point[0]=0.5f*(O1[0]+O3[0]);
+			point[1]=0.5f*(O1[1]+O3[1]);
+			point[2]=0.5f*(O1[2]+O3[2]);
+			}
+		else{
+			//l2_3;
+			point[0]=0.5f*(O2[0]+O3[0]);
+			point[1]=0.5f*(O2[1]+O3[1]);
+			point[2]=0.5f*(O2[2]+O3[2]);
+			}
+	else
+		if(l1_3<l2_4)
+			{
+			//l1_3;
+			point[0]=0.5f*(O1[0]+O3[0]);
+			point[1]=0.5f*(O1[1]+O3[1]);
+			point[2]=0.5f*(O1[2]+O3[2]);
+			}
+		else{
+			//l2_4;
+			point[0]=0.5f*(O2[0]+O4[0]);
+			point[1]=0.5f*(O2[1]+O4[1]);
+			point[2]=0.5f*(O2[2]+O4[2]);
+			}
+
+else
+	if(l2_3<l2_4)
+		if(l1_4<l2_3)
+			{
+			//l1_4;
+			point[0]=0.5f*(O1[0]+O4[0]);
+			point[1]=0.5f*(O1[1]+O4[1]);
+			point[2]=0.5f*(O1[2]+O4[2]);
+			}
+		else{
+			//l2_3;
+			point[0]=0.5f*(O2[0]+O3[0]);
+			point[1]=0.5f*(O2[1]+O3[1]);
+			point[2]=0.5f*(O2[2]+O3[2]);
+			}
+	else
+		if(l1_4<l2_4)
+			{
+			//l1_4;
+			point[0]=0.5f*(O1[0]+O4[0]);
+			point[1]=0.5f*(O1[1]+O4[1]);
+			point[2]=0.5f*(O1[2]+O4[2]);
+			}
+		else{
+			//l2_4;
+			point[0]=0.5f*(O2[0]+O4[0]);
+			point[1]=0.5f*(O2[1]+O4[1]);
+			point[2]=0.5f*(O2[2]+O4[2]);
+			}
+
+return true;
+}
+
+
+
+
+void lineClosestApproach (const dVector3 pa, const dVector3 ua,
+				 const dVector3 pb, const dVector3 ub,
+				 dReal *alpha, dReal *beta)
+{
+  dVector3 p;
+  p[0] = pb[0] - pa[0];
+  p[1] = pb[1] - pa[1];
+  p[2] = pb[2] - pa[2];
+  dReal uaub = dDOT(ua,ub);
+  dReal q1 =  dDOT(ua,p);
+  dReal q2 = -dDOT(ub,p);
+  dReal d = 1-uaub*uaub;
+  if (d <= 0) {
+    // @@@ this needs to be made more robust
+    *alpha = 0;
+    *beta  = 0;
+  }
+  else {
+    d = dRecip(d);
+    *alpha = (q1 + uaub*q2)*d;
+    *beta  = (uaub*q1 + q2)*d;
+  }
+}
+
+
+// @@@ some stuff to optimize here, reuse code in contact point calculations.
+
+extern "C" int dCylBox (const dVector3 p1, const dMatrix3 R1,
+			const dReal radius,const dReal lz, const dVector3 p2,
+			const dMatrix3 R2, const dVector3 side2,
+			dVector3 normal, dReal *depth, int *code,
+			int maxc, dContactGeom *contact, int skip)
+{
+  dVector3 p,pp,normalC;
+  const dReal *normalR = 0;
+  dReal B1,B2,B3,R11,R12,R13,R21,R22,R23,R31,R32,R33,
+    Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l,sQ21,sQ22,sQ23;
+  int i,invert_normal;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p[0] = p2[0] - p1[0];
+  p[1] = p2[1] - p1[1];
+  p[2] = p2[2] - p1[2];
+  dMULTIPLY1_331 (pp,R1,p);		// get pp = p relative to body 1
+
+  // get side lengths / 2
+  //A1 =radius; A2 = lz*REAL(0.5); A3 = radius;
+  dReal hlz=lz/2.f;
+  B1 = side2[0]*REAL(0.5); B2 = side2[1]*REAL(0.5); B3 = side2[2]*REAL(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 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13);
+  Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23);
+  Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33);
+
+  
+  //   * see if the axis separates the box with cylinder. 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 TEST(expr1,expr2,norm,cc) \
+  s2 = dFabs(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 = cylinder ax u2
+ //used when a box vertex touches a flat face of the cylinder
+  TEST (pp[1],(hlz + B1*Q21 + B2*Q22 + B3*Q23),R1+1,0);
+
+
+  // separating axis = box axis v1,v2,v3
+  //used when cylinder edge touches box face
+  //there is two ways to compute sQ: sQ21=sqrtf(1.f-Q21*Q21); or sQ21=sqrtf(Q23*Q23+Q22*Q22); 
+  //if we did not need Q23 and Q22 the first way might be used to quiken the routine but then it need to 
+  //check if Q21<=1.f, becouse it may slightly exeed 1.f.
+
+ 
+  sQ21=sqrtf(Q23*Q23+Q22*Q22);
+  TEST (dDOT41(R2+0,p),(radius*sQ21 + hlz*Q21 + B1),R2+0,1);
+
+  sQ22=sqrtf(Q23*Q23+Q21*Q21);
+  TEST (dDOT41(R2+1,p),(radius*sQ22 + hlz*Q22 + B2),R2+1,2);
+
+  sQ23=sqrtf(Q22*Q22+Q21*Q21);
+  TEST (dDOT41(R2+2,p),(radius*sQ23 + hlz*Q23 + B3),R2+2,3);
+
+ 
+#undef TEST
+#define TEST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = dFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  if (s2 > s) { \
+      s = s2; \
+	  normalR = 0; \
+      normalC[0] = (n1); normalC[1] = (n2); normalC[2] = (n3); \
+      invert_normal = ((expr1) < 0); \
+      *code = (cc); \
+    } 
+ 
+
+
+// separating axis is a normal to the cylinder axis passing across the nearest box vertex
+//used when a box vertex touches the lateral surface of the cylinder
+
+dReal proj,boxProj,cos,sin,cos1,cos3;
+dVector3 tAx,Ax,pb;
+{
+//making Ax which is perpendicular to cyl ax to box position//
+proj=dDOT14(p2,R1+1)-dDOT14(p1,R1+1);
+
+Ax[0]=p2[0]-p1[0]-R1[1]*proj;
+Ax[1]=p2[1]-p1[1]-R1[5]*proj;
+Ax[2]=p2[2]-p1[2]-R1[9]*proj;
+dNormalize3(Ax);
+//using Ax find box vertex which is nearest to the cylinder axis
+	dReal sign;
+    
+    for (i=0; i<3; i++) pb[i] = p2[i];
+    sign = (dDOT14(Ax,R2+0) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) pb[i] += sign * B1 * R2[i*4];
+    sign = (dDOT14(Ax,R2+1) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) pb[i] += sign * B2 * R2[i*4+1];
+    sign = (dDOT14(Ax,R2+2) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) pb[i] += sign * B3 * R2[i*4+2];
+
+//building axis which is normal to cylinder ax to the nearest box vertex
+proj=dDOT14(pb,R1+1)-dDOT14(p1,R1+1);
+
+Ax[0]=pb[0]-p1[0]-R1[1]*proj;
+Ax[1]=pb[1]-p1[1]-R1[5]*proj;
+Ax[2]=pb[2]-p1[2]-R1[9]*proj;
+dNormalize3(Ax);
+}
+
+boxProj=dFabs(dDOT14(Ax,R2+0)*B1)+
+		dFabs(dDOT14(Ax,R2+1)*B2)+
+		dFabs(dDOT14(Ax,R2+2)*B3);
+
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(radius+boxProj),Ax[0],Ax[1],Ax[2],4);
+
+
+//next three test used to handle collisions between cylinder circles and box ages
+proj=dDOT14(p1,R2+0)-dDOT14(p2,R2+0);
+
+tAx[0]=-p1[0]+p2[0]+R2[0]*proj;
+tAx[1]=-p1[1]+p2[1]+R2[4]*proj;
+tAx[2]=-p1[2]+p2[2]+R2[8]*proj;
+dNormalize3(tAx);
+
+//now tAx is normal to first ax of the box to cylinder center
+//making perpendicular to tAx lying in the plane which is normal to the cylinder axis
+//it is tangent in the point where projection of tAx on cylinder's ring intersect edge circle
+
+cos=dDOT14(tAx,R1+0);
+sin=dDOT14(tAx,R1+2);
+tAx[0]=R1[2]*cos-R1[0]*sin;
+tAx[1]=R1[6]*cos-R1[4]*sin;
+tAx[2]=R1[10]*cos-R1[8]*sin;
+
+
+//use cross between tAx and first ax of the box as separating axix 
+
+dCROSS114(Ax,=,tAx,R2+0);
+dNormalize3(Ax);
+
+boxProj=dFabs(dDOT14(Ax,R2+1)*B2)+
+		dFabs(dDOT14(Ax,R2+0)*B1)+
+		dFabs(dDOT14(Ax,R2+2)*B3);
+
+  cos=dFabs(dDOT14(Ax,R1+1));
+  cos1=dDOT14(Ax,R1+0);
+  cos3=dDOT14(Ax,R1+2);
+  sin=sqrtf(cos1*cos1+cos3*cos3);
+
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(sin*radius+cos*hlz+boxProj),Ax[0],Ax[1],Ax[2],5);
+
+
+//same thing with the second axis of the box
+proj=dDOT14(p1,R2+1)-dDOT14(p2,R2+1);
+
+tAx[0]=-p1[0]+p2[0]+R2[1]*proj;
+tAx[1]=-p1[1]+p2[1]+R2[5]*proj;
+tAx[2]=-p1[2]+p2[2]+R2[9]*proj;
+dNormalize3(tAx);
+
+
+cos=dDOT14(tAx,R1+0);
+sin=dDOT14(tAx,R1+2);
+tAx[0]=R1[2]*cos-R1[0]*sin;
+tAx[1]=R1[6]*cos-R1[4]*sin;
+tAx[2]=R1[10]*cos-R1[8]*sin;
+
+dCROSS114(Ax,=,tAx,R2+1);
+dNormalize3(Ax);
+
+boxProj=dFabs(dDOT14(Ax,R2+0)*B1)+
+		dFabs(dDOT14(Ax,R2+1)*B2)+
+		dFabs(dDOT14(Ax,R2+2)*B3);
+
+  cos=dFabs(dDOT14(Ax,R1+1));
+  cos1=dDOT14(Ax,R1+0);
+  cos3=dDOT14(Ax,R1+2);
+  sin=sqrtf(cos1*cos1+cos3*cos3);
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(sin*radius+cos*hlz+boxProj),Ax[0],Ax[1],Ax[2],6);
+
+//same thing with the third axis of the box
+proj=dDOT14(p1,R2+2)-dDOT14(p2,R2+2);
+
+Ax[0]=-p1[0]+p2[0]+R2[2]*proj;
+Ax[1]=-p1[1]+p2[1]+R2[6]*proj;
+Ax[2]=-p1[2]+p2[2]+R2[10]*proj;
+dNormalize3(tAx);
+
+cos=dDOT14(tAx,R1+0);
+sin=dDOT14(tAx,R1+2);
+tAx[0]=R1[2]*cos-R1[0]*sin;
+tAx[1]=R1[6]*cos-R1[4]*sin;
+tAx[2]=R1[10]*cos-R1[8]*sin;
+
+dCROSS114(Ax,=,tAx,R2+2);
+dNormalize3(Ax);
+boxProj=dFabs(dDOT14(Ax,R2+1)*B2)+
+		dFabs(dDOT14(Ax,R2+2)*B3)+
+		dFabs(dDOT14(Ax,R2+0)*B1);
+
+  cos=dFabs(dDOT14(Ax,R1+1));
+  cos1=dDOT14(Ax,R1+0);
+  cos3=dDOT14(Ax,R1+2);
+  sin=sqrtf(cos1*cos1+cos3*cos3);
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],(sin*radius+cos*hlz+boxProj),Ax[0],Ax[1],Ax[2],7);
+
+
+#undef TEST
+
+// note: cross product axes need to be scaled when s is computed.
+// normal (n1,n2,n3) is relative to box 1.
+
+#define TEST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = dFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  l = dSqrt ((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+  if (l > 0) { \
+    s2 /= l; \
+    if (s2 > s) { \
+      s = s2; \
+      normalR = 0; \
+      normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+      invert_normal = ((expr1) < 0); \
+      *code = (cc); \
+    } \
+  }
+
+//crosses between cylinder axis and box axes
+  // separating axis = u2 x (v1,v2,v3)
+  TEST(pp[0]*R31-pp[2]*R11,(radius+B2*Q23+B3*Q22),R31,0,-R11,8);
+  TEST(pp[0]*R32-pp[2]*R12,(radius+B1*Q23+B3*Q21),R32,0,-R12,9);
+  TEST(pp[0]*R33-pp[2]*R13,(radius+B1*Q22+B2*Q21),R33,0,-R13,10);
+
+
+#undef TEST
+
+  // 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 {
+	  if(*code>7) dMULTIPLY0_331 (normal,R1,normalC);
+	  else {normal[0] =normalC[0];normal[1] = normalC[1];normal[2] = normalC[2];}
+  }
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+  *depth = -s;
+
+  // compute contact point(s)
+
+  if (*code > 7) {
+ //find point on the cylinder pa deepest along normal
+    dVector3 pa;
+    dReal sign, cos1,cos3,factor;
+
+
+    for (i=0; i<3; i++) pa[i] = p1[i];
+
+  	cos1 = dDOT14(normal,R1+0);
+	cos3 = dDOT14(normal,R1+2) ;
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+
+	cos1/=factor;
+	cos3/=factor;
+	
+    for (i=0; i<3; i++) pa[i] += cos1 * radius * R1[i*4];
+
+    sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) pa[i] += sign * hlz * R1[i*4+1];
+
+  
+    for (i=0; i<3; i++) pa[i] += cos3 * radius * R1[i*4+2];
+
+    // find vertex of the box  deepest along normal 
+    dVector3 pb;
+    for (i=0; i<3; i++) pb[i] = p2[i];
+    sign = (dDOT14(normal,R2+0) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) pb[i] += sign * B1 * R2[i*4];
+    sign = (dDOT14(normal,R2+1) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) pb[i] += sign * B2 * R2[i*4+1];
+    sign = (dDOT14(normal,R2+2) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) pb[i] += sign * B3 * R2[i*4+2];
+
+
+    dReal alpha,beta;
+    dVector3 ua,ub;
+    for (i=0; i<3; i++) ua[i] = R1[1 + i*4];
+    for (i=0; i<3; i++) ub[i] = R2[*code-8 + i*4];
+
+    lineClosestApproach (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;
+
+    for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]);
+    contact[0].depth = *depth;
+    return 1;
+  }
+
+
+  	if(*code==4){
+		for (i=0; i<3; i++) contact[0].pos[i] = pb[i];
+		contact[0].depth = *depth;
+		return 1;
+				}
+  
+
+  dVector3 vertex;
+  if (*code == 0) {
+   
+    dReal sign;
+    for (i=0; i<3; i++) vertex[i] = p2[i];
+    sign = (dDOT14(normal,R2+0) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) vertex[i] += sign * B1 * R2[i*4];
+    sign = (dDOT14(normal,R2+1) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) vertex[i] += sign * B2 * R2[i*4+1];
+    sign = (dDOT14(normal,R2+2) > 0) ? REAL(-1.0) : REAL(1.0);
+    for (i=0; i<3; i++) vertex[i] += sign * B3 * R2[i*4+2];
+  }
+  else {
+   
+    dReal sign,cos1,cos3,factor;
+    for (i=0; i<3; i++) vertex[i] = p1[i];
+    cos1 = dDOT14(normal,R1+0) ;
+	cos3 = dDOT14(normal,R1+2);
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+	factor= factor ? factor : 1.f;
+	cos1/=factor;
+	cos3/=factor;
+    for (i=0; i<3; i++) vertex[i] += cos1 * radius * R1[i*4];
+
+    sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) vertex[i] += sign * hlz * R1[i*4+1];
+   
+    for (i=0; i<3; i++) vertex[i] += cos3 * radius * R1[i*4+2];
+  }
+  for (i=0; i<3; i++) contact[0].pos[i] = vertex[i];
+  contact[0].depth = *depth;
+  return 1;
+}
+
+//****************************************************************************
+
+extern "C" int dCylCyl (const dVector3 p1, const dMatrix3 R1,
+			const dReal radius1,const dReal lz1, const dVector3 p2,
+			const dMatrix3 R2, const dReal radius2,const dReal lz2,
+			dVector3 normal, dReal *depth, int *code,
+			int maxc, dContactGeom *contact, int skip)
+{
+  dVector3 p,pp1,pp2,normalC;
+  const dReal *normalR = 0;
+  dReal hlz1,hlz2,s,s2;
+  int i,invert_normal;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p[0] = p2[0] - p1[0];
+  p[1] = p2[1] - p1[1];
+  p[2] = p2[2] - p1[2];
+  dMULTIPLY1_331 (pp1,R1,p);		// get pp1 = p relative to body 1
+  dMULTIPLY1_331 (pp2,R2,p);
+  // get side lengths / 2
+  hlz1 = lz1*REAL(0.5);
+  hlz2 = lz2*REAL(0.5); 
+
+ dReal proj,cos,sin,cos1,cos3;
+
+
+
+#define TEST(expr1,expr2,norm,cc) \
+  s2 = dFabs(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;
+
+  cos=dFabs(dDOT44(R1+1,R2+1));
+  sin=sqrtf(1.f-(cos>1.f ? 1.f : cos));
+
+  TEST (pp1[1],(hlz1 + radius2*sin + hlz2*cos ),R1+1,0);//pp
+
+  TEST (pp2[1],(radius1*sin + hlz1*cos + hlz2),R2+1,1);
+
+
+
+  // note: cross product axes need to be scaled when s is computed.
+ 
+#undef TEST
+#define TEST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = dFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  if (s2 > s) { \
+      s = s2; \
+	  normalR = 0; \
+      normalC[0] = (n1); normalC[1] = (n2); normalC[2] = (n3); \
+      invert_normal = ((expr1) < 0); \
+      *code = (cc); \
+    } 
+ 
+
+dVector3 tAx,Ax,pa,pb;
+
+//cross between cylinders' axes
+dCROSS144(Ax,=,R1+1,R2+1);
+dNormalize3(Ax);
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],radius1+radius2,Ax[0],Ax[1],Ax[2],6);
+
+
+{
+ 
+    dReal sign, factor;
+
+	//making ax which is perpendicular to cyl1 ax passing across cyl2 position//
+		//(project p on cyl1 flat surface )
+    for (i=0; i<3; i++) pb[i] = p2[i];
+ 	//cos1 = dDOT14(p,R1+0);
+	//cos3 = dDOT14(p,R1+2) ;
+	tAx[0]=pp1[0]*R1[0]+pp1[2]*R1[2];
+	tAx[1]=pp1[0]*R1[4]+pp1[2]*R1[6];
+	tAx[2]=pp1[0]*R1[8]+pp1[2]*R1[10];
+	dNormalize3(tAx);
+
+//find deepest point pb of cyl2 on opposite direction of tAx
+ 	cos1 = dDOT14(tAx,R2+0);
+	cos3 = dDOT14(tAx,R2+2) ;
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+	cos1/=factor;
+	cos3/=factor;
+    for (i=0; i<3; i++) pb[i] -= cos1 * radius2 * R2[i*4];
+
+    sign = (dDOT14(tAx,R2+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) pb[i] -= sign * hlz2 * R2[i*4+1];
+
+    for (i=0; i<3; i++) pb[i] -= cos3 * radius2 * R2[i*4+2];
+
+//making perpendicular to cyl1 ax passing across pb
+	proj=dDOT14(pb,R1+1)-dDOT14(p1,R1+1);
+
+	Ax[0]=pb[0]-p1[0]-R1[1]*proj;
+	Ax[1]=pb[1]-p1[1]-R1[5]*proj;
+	Ax[2]=pb[2]-p1[2]-R1[9]*proj;
+
+}
+
+dNormalize3(Ax);
+
+
+  cos=dFabs(dDOT14(Ax,R2+1));
+  cos1=dDOT14(Ax,R2+0);
+  cos3=dDOT14(Ax,R2+2);
+  sin=sqrtf(cos1*cos1+cos3*cos3);
+
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],radius1+cos*hlz2+sin*radius2,Ax[0],Ax[1],Ax[2],3);
+
+
+
+{
+   
+   dReal sign, factor;
+   	
+    for (i=0; i<3; i++) pa[i] = p1[i];
+
+ 	//making ax which is perpendicular to cyl2 ax passing across cyl1 position//
+	//(project p on cyl2 flat surface )
+ 	//cos1 = dDOT14(p,R2+0);
+	//cos3 = dDOT14(p,R2+2) ;
+	tAx[0]=pp2[0]*R2[0]+pp2[2]*R2[2];
+	tAx[1]=pp2[0]*R2[4]+pp2[2]*R2[6];
+	tAx[2]=pp2[0]*R2[8]+pp2[2]*R2[10];
+	dNormalize3(tAx);
+
+ 	cos1 = dDOT14(tAx,R1+0);
+	cos3 = dDOT14(tAx,R1+2) ;
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+	cos1/=factor;
+	cos3/=factor;
+
+//find deepest point pa of cyl2 on direction of tAx
+    for (i=0; i<3; i++) pa[i] += cos1 * radius1 * R1[i*4];
+
+    sign = (dDOT14(tAx,R1+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) pa[i] += sign * hlz1 * R1[i*4+1];
+
+  
+    for (i=0; i<3; i++) pa[i] += cos3 * radius1 * R1[i*4+2];
+
+	proj=dDOT14(pa,R2+1)-dDOT14(p2,R2+1);
+
+	Ax[0]=pa[0]-p2[0]-R2[1]*proj;
+	Ax[1]=pa[1]-p2[1]-R2[5]*proj;
+	Ax[2]=pa[2]-p2[2]-R2[9]*proj;
+
+}
+dNormalize3(Ax);
+
+
+
+  cos=dFabs(dDOT14(Ax,R1+1));
+  cos1=dDOT14(Ax,R1+0);
+  cos3=dDOT14(Ax,R1+2);
+  sin=sqrtf(cos1*cos1+cos3*cos3);
+
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],radius2+cos*hlz1+sin*radius1,Ax[0],Ax[1],Ax[2],4);
+
+
+////test circl
+
+//@ this needed to set right normal when cylinders edges intersect
+//@ the most precise axis for this test may be found as a line between nearest points of two
+//@ circles. But it needs comparatively a lot of computation.
+//@ I use a trick which lets not to solve quadric equation. 
+//@ In the case when cylinder eidges touches the test below rather accurate.
+//@ I still not sure about problems with sepparation but they have not been revealed during testing.
+dVector3 point;
+{
+ dVector3 ca,cb; 
+ dReal sign;
+ for (i=0; i<3; i++) ca[i] = p1[i];
+ for (i=0; i<3; i++) cb[i] = p2[i];
+//find two nearest flat rings
+ sign = (pp1[1] > 0) ? REAL(1.0) : REAL(-1.0);
+ for (i=0; i<3; i++) ca[i] += sign * hlz1 * R1[i*4+1];
+
+ sign = (pp2[1] > 0) ? REAL(1.0) : REAL(-1.0);
+ for (i=0; i<3; i++) cb[i] -= sign * hlz2 * R2[i*4+1];
+
+ dVector3 tAx,tAx1;
+	circleIntersection(R1+1,ca,radius1,R2+1,cb,radius2,point);
+
+	Ax[0]=point[0]-ca[0];
+	Ax[1]=point[1]-ca[1];
+	Ax[2]=point[2]-ca[2];
+
+  	cos1 = dDOT14(Ax,R1+0);
+	cos3 = dDOT14(Ax,R1+2) ;
+
+	tAx[0]=cos3*R1[0]-cos1*R1[2];
+	tAx[1]=cos3*R1[4]-cos1*R1[6];
+	tAx[2]=cos3*R1[8]-cos1*R1[10];
+
+	Ax[0]=point[0]-cb[0];
+	Ax[1]=point[1]-cb[1];
+	Ax[2]=point[2]-cb[2];
+
+
+ 	cos1 = dDOT14(Ax,R2+0);
+	cos3 = dDOT14(Ax,R2+2) ;
+
+	tAx1[0]=cos3*R2[0]-cos1*R2[2];
+	tAx1[1]=cos3*R2[4]-cos1*R2[6];
+	tAx1[2]=cos3*R2[8]-cos1*R2[10];
+	dCROSS(Ax,=,tAx,tAx1);
+	
+
+ 
+
+dNormalize3(Ax);
+dReal cyl1Pr,cyl2Pr;
+
+ cos=dFabs(dDOT14(Ax,R1+1));
+ cos1=dDOT14(Ax,R1+0);
+ cos3=dDOT14(Ax,R1+2);
+ sin=sqrtf(cos1*cos1+cos3*cos3);
+ cyl1Pr=cos*hlz1+sin*radius1;
+
+ cos=dFabs(dDOT14(Ax,R2+1));
+ cos1=dDOT14(Ax,R2+0);
+ cos3=dDOT14(Ax,R2+2);
+ sin=sqrtf(cos1*cos1+cos3*cos3);
+ cyl2Pr=cos*hlz2+sin*radius2;
+TEST(p[0]*Ax[0]+p[1]*Ax[1]+p[2]*Ax[2],cyl1Pr+cyl2Pr,Ax[0],Ax[1],Ax[2],5);
+
+
+}
+
+
+#undef TEST
+
+
+
+  // if we get to this point, the cylinders interpenetrate. compute the normal
+  // in global coordinates.
+  if (normalR) {
+    normal[0] = normalR[0];
+    normal[1] = normalR[4];
+    normal[2] = normalR[8];
+  }
+  else {
+		normal[0] =normalC[0];normal[1] = normalC[1];normal[2] = normalC[2];
+		}
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+
+  *depth = -s;
+
+  // compute contact point(s)
+
+	if(*code==3){
+		for (i=0; i<3; i++) contact[0].pos[i] = pb[i];
+		contact[0].depth = *depth;
+		return 1;
+				}
+
+	if(*code==4){
+		for (i=0; i<3; i++) contact[0].pos[i] = pa[i];
+		contact[0].depth = *depth;
+		return 1;
+				}
+
+	if(*code==5){
+		for (i=0; i<3; i++) contact[0].pos[i] = point[i];
+		contact[0].depth = *depth;
+		return 1;
+				}
+
+if (*code == 6) {
+	    dVector3 pa;
+    dReal sign, cos1,cos3,factor;
+
+
+    for (i=0; i<3; i++) pa[i] = p1[i];
+
+  	cos1 = dDOT14(normal,R1+0);
+	cos3 = dDOT14(normal,R1+2) ;
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+
+	cos1/=factor;
+	cos3/=factor;
+	
+    for (i=0; i<3; i++) pa[i] += cos1 * radius1 * R1[i*4];
+
+    sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) pa[i] += sign * hlz1 * R1[i*4+1];
+
+  
+    for (i=0; i<3; i++) pa[i] += cos3 * radius1 * R1[i*4+2];
+
+    // find a point pb on the intersecting edge of cylinder 2
+    dVector3 pb;
+    for (i=0; i<3; i++) pb[i] = p2[i];
+ 	cos1 = dDOT14(normal,R2+0);
+	cos3 = dDOT14(normal,R2+2) ;
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+
+	cos1/=factor;
+	cos3/=factor;
+	
+    for (i=0; i<3; i++) pb[i] -= cos1 * radius2 * R2[i*4];
+
+    sign = (dDOT14(normal,R2+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) pb[i] -= sign * hlz2 * R2[i*4+1];
+
+  
+    for (i=0; i<3; i++) pb[i] -= cos3 * radius2 * R2[i*4+2];
+
+	
+	dReal alpha,beta;
+	dVector3 ua,ub;
+	for (i=0; i<3; i++) ua[i] = R1[1 + i*4];
+	for (i=0; i<3; i++) ub[i] = R2[1 + i*4];
+	lineClosestApproach (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;
+
+    for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]);
+    contact[0].depth = *depth;
+    return 1;
+  }
+
+  // okay, we have a face-something intersection (because the separating
+  // axis is perpendicular to a face).
+
+  // @@@ temporary: make deepest point on the "other" cylinder the contact point.
+  // @@@ this kind of works, but we need multiple contact points for stability,
+  // @@@ especially for face-face contact.
+
+  dVector3 vertex;
+  if (*code == 0) {
+    // flat face from cylinder 1 touches a edge/face from cylinder 2.
+    dReal sign,cos1,cos3,factor;
+    for (i=0; i<3; i++) vertex[i] = p2[i];
+    cos1 = dDOT14(normal,R2+0) ;
+	cos3 = dDOT14(normal,R2+2);
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+
+	cos1/=factor;
+	cos3/=factor;
+    for (i=0; i<3; i++) vertex[i] -= cos1 * radius2 * R2[i*4];
+
+    sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) vertex[i] -= sign * hlz2 * R2[i*4+1];
+   
+    for (i=0; i<3; i++) vertex[i] -= cos3 * radius2 * R2[i*4+2];
+  }
+  else {
+     // flat face from cylinder 2 touches a edge/face from cylinder 1.
+    dReal sign,cos1,cos3,factor;
+    for (i=0; i<3; i++) vertex[i] = p1[i];
+    cos1 = dDOT14(normal,R1+0) ;
+	cos3 = dDOT14(normal,R1+2);
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+
+	cos1/=factor;
+	cos3/=factor;
+    for (i=0; i<3; i++) vertex[i] += cos1 * radius1 * R1[i*4];
+
+    sign = (dDOT14(normal,R1+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) vertex[i] += sign * hlz1 * R1[i*4+1];
+   
+    for (i=0; i<3; i++) vertex[i] += cos3 * radius1 * R1[i*4+2];
+  }
+  for (i=0; i<3; i++) contact[0].pos[i] = vertex[i];
+  contact[0].depth = *depth;
+  return 1;
+}
+
+//****************************************************************************
+
+
+int dCollideCylS (dxGeom *o1, dxGeom *o2, int flags,
+		dContactGeom *contact, int skip)
+{
+ 
+
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (dGeomGetClass(o2) == dSphereClass);
+  dIASSERT (dGeomGetClass(o1) == dCylinderClassUser);
+  const dReal* p1=dGeomGetPosition(o1);
+  const dReal* p2=dGeomGetPosition(o2);
+  const dReal* R=dGeomGetRotation(o1);
+  dVector3 p,normalC,normal;
+  const dReal *normalR = 0;
+  dReal cylRadius;
+  dReal hl;
+  dGeomCylinderGetParams(o1,&cylRadius,&hl);
+  dReal sphereRadius;
+  sphereRadius=dGeomSphereGetRadius(o2);
+  
+  int i,invert_normal;
+
+  // get vector from centers of cyl to shere
+  p[0] = p2[0] - p1[0];
+  p[1] = p2[1] - p1[1];
+  p[2] = p2[2] - p1[2];
+ 
+dReal s,s2;
+unsigned char code;
+#define TEST(expr1,expr2,norm,cc) \
+  s2 = dFabs(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 cyl ax 
+
+  TEST (dDOT14(p,R+1),sphereRadius+hl,R+1,2);
+  // note: cross product axes need to be scaled when s is computed.
+  // normal (n1,n2,n3) is relative to 
+#undef TEST
+#define TEST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = dFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  if (s2 > s) { \
+      s = s2; \
+	  normalR = 0; \
+      normalC[0] = (n1); normalC[1] = (n2); normalC[2] = (n3); \
+      invert_normal = ((expr1) < 0); \
+      code = (cc); \
+    } 
+ 
+//making ax which is perpendicular to cyl1 ax to sphere center//
+ 
+dReal proj,cos,sin,cos1,cos3;
+dVector3 Ax;
+	proj=dDOT14(p2,R+1)-dDOT14(p1,R+1);
+
+	Ax[0]=p2[0]-p1[0]-R[1]*proj;
+	Ax[1]=p2[1]-p1[1]-R[5]*proj;
+	Ax[2]=p2[2]-p1[2]-R[9]*proj;
+dNormalize3(Ax);
+TEST(dDOT(p,Ax),sphereRadius+cylRadius,Ax[0],Ax[1],Ax[2],9);
+
+
+Ax[0]=p[0];
+Ax[1]=p[1];
+Ax[2]=p[2];
+dNormalize3(Ax);
+
+	dVector3 pa;
+    dReal sign, factor;
+    for (i=0; i<3; i++) pa[i] = p1[i];
+
+  	cos1 = dDOT14(Ax,R+0);
+	cos3 = dDOT14(Ax,R+2) ;
+	factor=sqrtf(cos1*cos1+cos3*cos3);
+	cos1/=factor;
+	cos3/=factor;
+    for (i=0; i<3; i++) pa[i] += cos1 * cylRadius * R[i*4];
+    sign = (dDOT14(normal,R+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) pa[i] += sign * hl * R[i*4+1];
+    for (i=0; i<3; i++) pa[i] += cos3 * cylRadius  * R[i*4+2];
+
+Ax[0]=p2[0]-pa[0];
+Ax[1]=p2[1]-pa[1];
+Ax[2]=p2[2]-pa[2];
+dNormalize3(Ax);
+
+ cos=dFabs(dDOT14(Ax,R+1));
+ cos1=dDOT14(Ax,R+0);
+ cos3=dDOT14(Ax,R+2);
+ sin=sqrtf(cos1*cos1+cos3*cos3);
+TEST(dDOT(p,Ax),sphereRadius+cylRadius*sin+hl*cos,Ax[0],Ax[1],Ax[2],14);
+
+
+#undef TEST
+
+  if (normalR) {
+    normal[0] = normalR[0];
+    normal[1] = normalR[4];
+    normal[2] = normalR[8];
+  }
+  else {
+
+	normal[0] = normalC[0];
+	normal[1] = normalC[1];
+	normal[2] = normalC[2];
+		}
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+   // compute contact point(s)
+contact->depth=-s;
+contact->normal[0]=-normal[0];
+contact->normal[1]=-normal[1];
+contact->normal[2]=-normal[2];
+contact->g1=const_cast<dxGeom*> (o1);
+contact->g2=const_cast<dxGeom*> (o2);
+contact->pos[0]=p2[0]-normal[0]*sphereRadius;
+contact->pos[1]=p2[1]-normal[1]*sphereRadius;
+contact->pos[2]=p2[2]-normal[2]*sphereRadius;
+return 1;
+}
+
+
+
+int dCollideCylB (dxGeom *o1, dxGeom *o2, int flags,
+		dContactGeom *contact, int skip)
+{
+  dVector3 normal;
+  dReal depth;
+  int code;
+  dReal cylRadius,cylLength;
+  dVector3 boxSides;
+  dGeomCylinderGetParams(o1,&cylRadius,&cylLength);
+  dGeomBoxGetLengths(o2,boxSides);
+  int num = dCylBox(dGeomGetPosition(o1),dGeomGetRotation(o1),cylRadius,cylLength, 
+					dGeomGetPosition(o2),dGeomGetRotation(o2),boxSides,
+					normal,&depth,&code,flags & NUMC_MASK,contact,skip);
+  for (int i=0; i<num; i++) {
+    CONTACT(contact,i*skip)->normal[0] = -normal[0];
+    CONTACT(contact,i*skip)->normal[1] = -normal[1];
+    CONTACT(contact,i*skip)->normal[2] = -normal[2];
+    CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1);
+    CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2);
+  }
+  return num;
+}
+
+int dCollideCylCyl (dxGeom *o1, dxGeom *o2, int flags,
+		dContactGeom *contact, int skip)
+{
+  dVector3 normal;
+  dReal depth;
+  int code;
+dReal cylRadius1,cylRadius2;
+dReal cylLength1,cylLength2;
+dGeomCylinderGetParams(o1,&cylRadius1,&cylLength1);
+dGeomCylinderGetParams(o2,&cylRadius2,&cylLength2);
+int num = dCylCyl (dGeomGetPosition(o1),dGeomGetRotation(o1),cylRadius1,cylLength1,
+				   dGeomGetPosition(o2),dGeomGetRotation(o2),cylRadius2,cylLength2,
+				     normal,&depth,&code,flags & NUMC_MASK,contact,skip);
+
+  for (int i=0; i<num; i++) {
+    CONTACT(contact,i*skip)->normal[0] = -normal[0];
+    CONTACT(contact,i*skip)->normal[1] = -normal[1];
+    CONTACT(contact,i*skip)->normal[2] = -normal[2];
+    CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1);
+    CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2);
+  }
+  return num;
+}
+
+struct dxPlane {
+  dReal p[4];
+};
+
+
+int dCollideCylPlane 
+	(
+	dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip){
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (dGeomGetClass(o1) == dCylinderClassUser);
+  dIASSERT (dGeomGetClass(o2) == dPlaneClass);
+  contact->g1 = const_cast<dxGeom*> (o1);
+  contact->g2 = const_cast<dxGeom*> (o2);
+  
+ unsigned int ret = 0;
+
+ dReal radius;
+ dReal hlz;
+ dGeomCylinderGetParams(o1,&radius,&hlz);
+ hlz /= 2;
+ 
+ const dReal *R	=	dGeomGetRotation(o1);// rotation of cylinder
+ const dReal* p	=	dGeomGetPosition(o1);
+ dVector4 n;		// normal vector
+ dReal pp;
+ dGeomPlaneGetParams (o2, n);
+ pp=n[3];
+ dReal cos1,sin1;
+  cos1=dFabs(dDOT14(n,R+1));
+
+cos1=cos1<REAL(1.) ? cos1 : REAL(1.); //cos1 may slightly exeed 1.f
+sin1=sqrtf(REAL(1.)-cos1*cos1);
+//////////////////////////////
+
+dReal sidePr=cos1*hlz+sin1*radius;
+
+dReal dist=-pp+dDOT(n,p);
+dReal outDepth=sidePr-dist;
+
+if(outDepth<0.f) return 0;
+
+dVector3 pos;
+
+
+/////////////////////////////////////////// from geom.cpp dCollideBP
+  dReal Q1 = dDOT14(n,R+0);
+  dReal Q2 = dDOT14(n,R+1);
+  dReal Q3 = dDOT14(n,R+2);
+  dReal factor =sqrtf(Q1*Q1+Q3*Q3);
+  factor= factor ? factor :1.f;
+  dReal A1 = radius *		Q1/factor;
+  dReal A2 = hlz*Q2;
+  dReal A3 = radius *		Q3/factor;
+
+  pos[0]=p[0];
+  pos[1]=p[1];
+  pos[2]=p[2];
+
+  pos[0]-= A1*R[0];
+  pos[1]-= A1*R[4];
+  pos[2]-= A1*R[8];
+
+  pos[0]-= A3*R[2];
+  pos[1]-= A3*R[6];
+  pos[2]-= A3*R[10];
+
+  pos[0]-= A2>0 ? hlz*R[1]:-hlz*R[1];
+  pos[1]-= A2>0 ? hlz*R[5]:-hlz*R[5];
+  pos[2]-= A2>0 ? hlz*R[9]:-hlz*R[9];
+  
+ 
+
+  contact->pos[0] = pos[0];
+  contact->pos[1] = pos[1];
+  contact->pos[2] = pos[2];
+   contact->depth = outDepth;
+  ret=1;
+ 
+if(dFabs(Q2)>M_SQRT1_2){
+
+  CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*A1*R[0];
+  CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*A1*R[4];
+  CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*A1*R[8];
+  CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q1*2.f*A1);
+
+  if(CONTACT(contact,ret*skip)->depth>0.f)
+  ret++;
+  
+  
+  CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*A3*R[2];
+  CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*A3*R[6];
+  CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*A3*R[10];
+  CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q3*2.f*A3);
+
+  if(CONTACT(contact,ret*skip)->depth>0.f) ret++;
+} else {
+
+  CONTACT(contact,ret*skip)->pos[0]=pos[0]+2.f*(A2>0 ? hlz*R[1]:-hlz*R[1]);
+  CONTACT(contact,ret*skip)->pos[1]=pos[1]+2.f*(A2>0 ? hlz*R[5]:-hlz*R[5]);
+  CONTACT(contact,ret*skip)->pos[2]=pos[2]+2.f*(A2>0 ? hlz*R[9]:-hlz*R[9]);
+  CONTACT(contact,ret*skip)->depth=outDepth-dFabs(Q2*2.f*A2);
+
+  if(CONTACT(contact,ret*skip)->depth>0.f) ret++;
+}
+
+
+
+ for (unsigned int i=0; i<ret; i++) {
+    CONTACT(contact,i*skip)->g1 = const_cast<dxGeom*> (o1);
+    CONTACT(contact,i*skip)->g2 = const_cast<dxGeom*> (o2);
+	CONTACT(contact,i*skip)->normal[0] =n[0];
+	CONTACT(contact,i*skip)->normal[1] =n[1];
+	CONTACT(contact,i*skip)->normal[2] =n[2];
+  }
+  return ret;  
+}
+
+int dCollideCylRay(dxGeom *o1, dxGeom *o2, int flags,
+		   dContactGeom *contact, int skip) {
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (dGeomGetClass(o1) == dCylinderClassUser);
+  dIASSERT (dGeomGetClass(o2) == dRayClass);
+  contact->g1 = const_cast<dxGeom*> (o1);
+  contact->g2 = const_cast<dxGeom*> (o2);
+  dReal radius;
+  dReal lz;
+  dGeomCylinderGetParams(o1,&radius,&lz);
+  dReal lz2=lz*REAL(0.5);
+  const dReal *R = dGeomGetRotation(o1); // rotation of the cylinder
+  const dReal *p = dGeomGetPosition(o1); // position of the cylinder
+  dVector3 start,dir;
+  dGeomRayGet(o2,start,dir); // position and orientation of the ray
+  dReal length = dGeomRayGetLength(o2);
+
+  // compute some useful info
+  dVector3 cs,q,r;
+  dReal C,k;
+  cs[0] = start[0] - p[0];
+  cs[1] = start[1] - p[1];
+  cs[2] = start[2] - p[2];
+  k = dDOT41(R+1,cs);	// position of ray start along cyl axis (Y)
+  q[0] = k*R[0*4+1] - cs[0];
+  q[1] = k*R[1*4+1] - cs[1];
+  q[2] = k*R[2*4+1] - cs[2];
+  C = dDOT(q,q) - radius*radius;
+  // if C < 0 then ray start position within infinite extension of cylinder
+  // if ray start position is inside the cylinder
+  int inside_cyl=0;
+  if (C<0 && !(k<-lz2 || k>lz2)) inside_cyl=1;
+  // compute ray collision with infinite cylinder, except for the case where
+  // the ray is outside the cylinder but within the infinite cylinder
+  // (it that case the ray can only hit endcaps)
+  if (!inside_cyl && C < 0) {
+    // set k to cap position to check
+    if (k < 0) k = -lz2; else k = lz2;
+  }
+  else {
+    dReal uv = dDOT41(R+1,dir);
+    r[0] = uv*R[0*4+1] - dir[0];
+    r[1] = uv*R[1*4+1] - dir[1];
+    r[2] = uv*R[2*4+1] - dir[2];
+    dReal A = dDOT(r,r);
+    dReal B = 2*dDOT(q,r);
+    k = B*B-4*A*C;
+    if (k < 0) {
+      // the ray does not intersect the infinite cylinder, but if the ray is
+      // inside and parallel to the cylinder axis it may intersect the end
+      // caps. set k to cap position to check.
+      if (!inside_cyl) return 0;
+      if (uv < 0) k = -lz2; else k = lz2;
+    }
+    else {
+      k = dSqrt(k);
+      A = dRecip (2*A);
+      dReal alpha = (-B-k)*A;
+      if (alpha < 0) {
+	alpha = (-B+k)*A;
+	if (alpha<0) return 0;
+      }
+      if (alpha>length) return 0;
+      // the ray intersects the infinite cylinder. check to see if the
+      // intersection point is between the caps
+      contact->pos[0] = start[0] + alpha*dir[0];
+      contact->pos[1] = start[1] + alpha*dir[1];
+      contact->pos[2] = start[2] + alpha*dir[2];
+      q[0] = contact->pos[0] - p[0];
+      q[1] = contact->pos[1] - p[1];
+      q[2] = contact->pos[2] - p[2];
+      k = dDOT14(q,R+1);
+      dReal nsign = inside_cyl ? -1 : 1;
+      if (k >= -lz2 && k <= lz2) {
+	contact->normal[0] = nsign * (contact->pos[0] -
+				      (p[0] + k*R[0*4+1]));
+	contact->normal[1] = nsign * (contact->pos[1] -
+				      (p[1] + k*R[1*4+1]));
+	contact->normal[2] = nsign * (contact->pos[2] -
+				      (p[2] + k*R[2*4+1]));
+	dNormalize3 (contact->normal);
+	contact->depth = alpha;
+	return 1;
+      }
+      // the infinite cylinder intersection point is not between the caps.
+      // set k to cap position to check.
+      if (k < 0) k = -lz2; else k = lz2;
+    }
+  }
+  // check for ray intersection with the caps. k must indicate the cap
+  // position to check
+  // perform a ray plan interesection
+  // R+1 is the plan normal
+  q[0] = start[0] - (p[0] + k*R[0*4+1]);
+  q[1] = start[1] - (p[1] + k*R[1*4+1]);
+  q[2] = start[2] - (p[2] + k*R[2*4+1]);
+  dReal alpha = -dDOT14(q,R+1);
+  dReal k2 = dDOT14(dir,R+1);
+  if (k2==0) return 0; // ray parallel to the plane
+  alpha/=k2;
+  if (alpha<0 || alpha>length) return 0; // too short
+  contact->pos[0]=start[0]+alpha*dir[0];
+  contact->pos[1]=start[1]+alpha*dir[1];
+  contact->pos[2]=start[2]+alpha*dir[2];
+  dReal nsign = (k<0)?-1:1;
+  contact->normal[0]=nsign*R[0*4+1];
+  contact->normal[1]=nsign*R[1*4+1];
+  contact->normal[2]=nsign*R[2*4+1];
+  contact->depth=alpha;
+  return 1;
+}
+
+static  dColliderFn * dCylinderColliderFn (int num)
+{
+  if (num == dBoxClass) return (dColliderFn *) &dCollideCylB;
+  else if (num == dSphereClass) return (dColliderFn *) &dCollideCylS;
+  else if (num == dCylinderClassUser) return (dColliderFn *) &dCollideCylCyl;
+  else if (num == dPlaneClass) return (dColliderFn *) &dCollideCylPlane;
+  else if (num == dRayClass) return (dColliderFn *) &dCollideCylRay;
+  return 0;
+}
+
+
+static  void dCylinderAABB (dxGeom *geom, dReal aabb[6])
+{
+  dReal radius,lz;
+  dGeomCylinderGetParams(geom,&radius,&lz);
+const dReal* R= dGeomGetRotation(geom);
+const dReal* pos= dGeomGetPosition(geom);
+  dReal xrange =  dFabs (R[0] *radius) +
+    REAL(0.5) *dFabs (R[1] * lz) + dFabs (R[2] * radius);
+
+  dReal yrange = dFabs (R[4] *radius) +
+    REAL(0.5) * dFabs (R[5] * lz) + dFabs (R[6] * radius);
+
+  dReal zrange =  dFabs (R[8] * radius) +
+    REAL(0.5) *dFabs (R[9] * lz) + dFabs (R[10] * radius);
+
+  aabb[0] = pos[0] - xrange;
+  aabb[1] = pos[0] + xrange;
+  aabb[2] = pos[1] - yrange;
+  aabb[3] = pos[1] + yrange;
+  aabb[4] = pos[2] - zrange;
+  aabb[5] = pos[2] + zrange;
+}
+
+dxGeom *dCreateCylinder (dSpaceID space, dReal r, dReal lz)
+{
+ dAASSERT (r > 0 && lz > 0);
+ if (dCylinderClassUser == -1)
+  {
+    dGeomClass c;
+    c.bytes = sizeof (dxCylinder);
+    c.collider = &dCylinderColliderFn;
+    c.aabb = &dCylinderAABB;
+    c.aabb_test = 0;
+    c.dtor = 0;
+    dCylinderClassUser=dCreateGeomClass (&c);
+
+  }
+
+  dGeomID g = dCreateGeom (dCylinderClassUser);
+  if (space) dSpaceAdd (space,g);
+  dxCylinder *c = (dxCylinder*) dGeomGetClassData(g);
+
+  c->radius = r;
+  c->lz = lz;
+  return g;
+}
+
+
+
+void dGeomCylinderSetParams (dGeomID g, dReal radius, dReal length)
+{
+  dUASSERT (g && dGeomGetClass(g) == dCylinderClassUser,"argument not a cylinder");
+  dAASSERT (radius > 0 && length > 0);
+  dxCylinder *c = (dxCylinder*) dGeomGetClassData(g);
+  c->radius = radius;
+  c->lz = length;
+}
+
+
+
+void dGeomCylinderGetParams (dGeomID g, dReal *radius, dReal *length)
+{
+  dUASSERT (g && dGeomGetClass(g) == dCylinderClassUser ,"argument not a cylinder");
+  dxCylinder *c = (dxCylinder*) dGeomGetClassData(g);
+  *radius = c->radius;
+  *length = c->lz;
+}
+
+/*
+void dMassSetCylinder (dMass *m, dReal density,
+		  dReal radius, dReal length)
+{
+  dAASSERT (m);
+  dMassSetZero (m);
+  dReal M = length*M_PI*radius*radius*density;
+  m->mass = M;
+  m->_I(0,0) = M/REAL(4.0) * (ly*ly + lz*lz);
+  m->_I(1,1) = M/REAL(12.0) * (lx*lx + lz*lz);
+  m->_I(2,2) = M/REAL(4.0) * (lx*lx + ly*ly);
+
+# ifndef dNODEBUG
+  checkMass (m);
+# endif
+}
+*/
Index: /code/branches/ode/ode-0.9/contrib/dCylinder/dCylinder.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dCylinder/dCylinder.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dCylinder/dCylinder.h	(revision 216)
@@ -0,0 +1,14 @@
+
+#ifndef dCylinder_h
+#define dCylinder_h
+
+struct dxCylinder;
+extern int dCylinderClassUser;
+
+
+dxGeom *dCreateCylinder (dSpaceID space, dReal r, dReal lz);
+void dGeomCylinderSetParams (dGeomID g, dReal radius, dReal length);
+
+void dGeomCylinderGetParams (dGeomID g, dReal *radius, dReal *length);
+#endif //dCylinder_h
+
Index: /code/branches/ode/ode-0.9/contrib/dCylinder/readme.txt
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dCylinder/readme.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dCylinder/readme.txt	(revision 216)
@@ -0,0 +1,62 @@
+readme.txt
+
+WARNING: THIS IS NOT VERY RELIABLE CODE.  IT HAS BUGS.  YOUR
+         SUCCESS MAY VARY.  CONTRIBUTIONS OF FIXES/REWRITES ARE
+         WELCOME.
+
+///////////////////////////////////////////////////////////////////////
+
+Cylinder geometry class.
+
+New in this version:
+
+Cylinder class implemented as User Geometry Class so it now can be
+used with old and new ODE collision detection.
+
+Cylinder - Ray has been contributed by Olivier Michel.
+
+THE IDENTIFIER dCylinderClass HAS BEEN REPLACED BY dCylinderClassUser
+
+to avoid conflict with dCylinderClass in the enum definite in collision.h
+
+///////////////////////////////////////////////////////////////////////
+The dCylinder class includes the following collisions:
+
+Cylinder - Box
+Cylinder - Cylinder
+Cylinder - Sphere
+Cylinder - Plane
+Cylinder - Ray (contributed by Olivier Michel)
+
+Cylinder aligned along axis - Y when created. (Not like Capped
+Cylinder which aligned along axis - Z).
+
+Interface is just the same as  Capped Cylinder has.
+
+Use functions which have one "C" instead of double "C".
+
+to create:
+dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length);
+
+to set params:
+void dGeomCylinderSetParams (dGeomID cylinder,
+                              dReal radius, dReal length);
+
+
+to get params:
+void dGeomCylinderGetParams (dGeomID cylinder,
+                              dReal *radius, dReal *length);
+
+Return in radius and length the parameters of the given cylinder.
+
+Identification number of the class:
+ dCylinderClassUser
+
+ I do not include a function that sets inertia tensor for cylinder.
+ One may use existing ODE functions dMassSetCappedCylinder or dMassSetBox.
+ To set exact tensor for cylinder use dMassSetParameters.
+ Remember cylinder aligned along axis - Y.
+ 
+ ///////////////////////////////////////////////////////////////////////////
+ Konstantin Slipchenko
+ February 5, 2002
Index: /code/branches/ode/ode-0.9/contrib/dRay/Include/dRay.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/Include/dRay.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/Include/dRay.h	(revision 216)
@@ -0,0 +1,15 @@
+#include "ode\ode.h"
+
+/* Class ID */
+extern int dRayClass;
+
+/* Creates a ray */
+dxGeom* dGeomCreateRay(dSpaceID space, dReal Length);
+
+/* Set/Get length */
+void dGeomRaySetLength(dxGeom* g, dReal Length);
+dReal dGeomRayGetLength(dxGeom* g);
+
+/* Utility function to override the ray's pos + rot */
+void dGeomRaySet(dxGeom* g, dVector3 Origin, dVector3 Direction);
+void dGeomRayGet(dxGeom* g, dVector3 Origin, dVector3 Direction);
Index: /code/branches/ode/ode-0.9/contrib/dRay/README.txt
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/README.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/README.txt	(revision 216)
@@ -0,0 +1,16 @@
+From: "Erwin de Vries" <erwin@vo.com>
+To: <ode@q12.org>
+Subject: [ODE] dRay class
+Date: Thu, 25 Jul 2002 13:05:28 +0200
+
+Yesterday and today i've written a dRay class. It interacts with dPlane,
+dSphere, dBox and dCCylinder. It does not generate full contact information.
+It only generates the pos member. I dont think its useful to anyone to go
+through hoops and find a reasonable normal and penetration depth, as i dont
+think anyone will want to use it for dynamics. Just for CD.
+
+It should compile in single and double precision mode, and should be
+platform independant. I hope.
+
+The next Tri-Collider release using Opcode 1.1 will also implement a ray
+collision function along with some other not too interesting improvements.
Index: /code/branches/ode/ode-0.9/contrib/dRay/Test/test_ray.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/Test/test_ray.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/Test/test_ray.cpp	(revision 216)
@@ -0,0 +1,1372 @@
+/*************************************************************************
+
+
+ *                                                                       *
+
+
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+
+
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+
+
+ *                                                                       *
+
+
+ * This library is free software; you can redistribute it and/or         *
+
+
+ * modify it under the terms of EITHER:                                  *
+
+
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+
+
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+
+
+ *       your option) any later version. The text of the GNU Lesser      *
+
+
+ *       General Public License is included with this library in the     *
+
+
+ *       file LICENSE.TXT.                                               *
+
+
+ *   (2) The BSD-style license that is included with this library in     *
+
+
+ *       the file LICENSE-BSD.TXT.                                       *
+
+
+ *                                                                       *
+
+
+ * This library is distributed in the hope that it will be useful,       *
+
+
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+
+
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+
+
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+
+
+ *                                                                       *
+
+
+ *************************************************************************/
+
+
+
+
+
+#include <ode/ode.h>
+
+
+#include <dRay.h>
+
+
+#include <drawstuff/drawstuff.h>
+
+
+
+
+
+#ifdef _MSC_VER
+
+
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+
+
+#endif
+
+
+
+
+
+// select correct drawing functions
+
+
+
+
+
+#ifdef dDOUBLE
+
+
+#define dsDrawBox dsDrawBoxD
+
+
+#define dsDrawSphere dsDrawSphereD
+
+
+#define dsDrawCylinder dsDrawCylinderD
+
+
+#define dsDrawCappedCylinder dsDrawCappedCylinderD
+
+
+#endif
+
+
+
+
+
+
+
+
+// some constants
+
+
+
+
+
+#define NUM 20			// max number of objects
+
+
+#define DENSITY (5.0)		// density of all objects
+
+
+#define GPB 3			// maximum number of geometries per body
+
+
+
+
+
+
+
+
+// dynamics and collision objects
+
+
+
+
+
+struct MyObject {
+
+
+  dBodyID body;			// the body
+
+
+  dGeomID geom[GPB];		// geometries representing this body
+
+
+};
+
+
+
+
+
+static int num=0;		// number of objects in simulation
+
+
+static int nextobj=0;		// next object to recycle if num==NUM
+
+
+static dWorldID world;
+
+
+static dSpaceID space;
+
+
+static MyObject obj[NUM];
+
+
+static dJointGroupID contactgroup;
+
+
+static int selected = -1;	// selected object
+
+
+
+
+
+static dGeomID* Rays;
+
+
+static int RayCount;
+
+
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+
+
+// potentially colliding.
+
+
+
+
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+
+
+{
+
+
+  int i;
+
+
+  // if (o1->body && o2->body) return;
+
+
+
+
+
+  // exit without doing anything if the two bodies are connected by a joint
+
+
+  dBodyID b1 = dGeomGetBody(o1);
+
+
+  dBodyID b2 = dGeomGetBody(o2);
+
+
+  if (b1 && b2 && dAreConnected (b1,b2)) return;
+
+
+
+
+
+  dContact contact[32];			// up to 3 contacts per box
+
+
+  for (i=0; i<32; i++) {
+
+
+    contact[i].surface.mode = dContactBounce; //dContactMu2;
+
+
+    contact[i].surface.mu = dInfinity;
+
+
+    contact[i].surface.mu2 = 0;
+
+
+    contact[i].surface.bounce = 0.5;
+
+
+    contact[i].surface.bounce_vel = 0.1;
+
+
+  }
+
+
+  if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) {
+
+
+     dMatrix3 RI;
+
+
+     dRSetIdentity (RI);
+
+
+     const dReal ss[3] = {0.02,0.02,0.02};
+
+
+    for (i=0; i<numc; i++) {
+
+
+		if (dGeomGetClass(o1) == dRayClass || dGeomGetClass(o2) == dRayClass){
+
+
+			dMatrix3 Rotation;
+
+
+			dRSetIdentity(Rotation);
+
+
+			dsDrawSphere(contact[i].geom.pos, Rotation, REAL(0.01));
+
+
+			continue;
+
+
+		}
+
+
+
+
+
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+
+
+      dJointAttach (c,b1,b2);
+
+
+       //dsDrawBox (contact[i].geom.pos,RI,ss);
+
+
+
+
+
+	  
+
+
+    }
+
+
+  }
+
+
+}
+
+
+
+
+
+// start simulation - set viewpoint
+
+
+
+
+
+static void start()
+
+
+{
+
+
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+
+
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+
+
+  dsSetViewpoint (xyz,hpr);
+
+
+  printf ("To drop another object, press:\n");
+
+
+  printf ("   b for box.\n");
+
+
+  printf ("   s for sphere.\n");
+
+
+  printf ("   c for cylinder.\n");
+
+
+  printf ("   x for a composite object.\n");
+
+
+  printf ("To select an object, press space.\n");
+
+
+  printf ("To disable the selected object, press d.\n");
+
+
+  printf ("To enable the selected object, press e.\n");
+
+
+}
+
+
+
+
+
+
+
+
+char locase (char c)
+
+
+{
+
+
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+
+
+  else return c;
+
+
+}
+
+
+
+
+
+
+
+
+// called when a key pressed
+
+
+
+
+
+static void command (int cmd)
+
+
+{
+
+
+  int i,j,k;
+
+
+  dReal sides[3];
+
+
+  dMass m;
+
+
+
+
+
+  cmd = locase (cmd);
+
+
+  if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x') {
+
+
+    if (num < NUM) {
+
+
+      i = num;
+
+
+      num++;
+
+
+    }
+
+
+    else {
+
+
+      i = nextobj;
+
+
+      nextobj++;
+
+
+      if (nextobj >= num) nextobj = 0;
+
+
+
+
+
+      // destroy the body and geoms for slot i
+
+
+      dBodyDestroy (obj[i].body);
+
+
+      for (k=0; k < GPB; k++) {
+
+
+	if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+
+
+      }
+
+
+      memset (&obj[i],0,sizeof(obj[i]));
+
+
+    }
+
+
+
+
+
+    obj[i].body = dBodyCreate (world);
+
+
+    for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+
+
+
+
+    dBodySetPosition (obj[i].body,
+
+
+		      dRandReal()*2-1,dRandReal()*2-1,dRandReal()+1);
+
+
+    dMatrix3 R;
+
+
+    dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+
+
+			dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+
+
+    dBodySetRotation (obj[i].body,R);
+
+
+    dBodySetData (obj[i].body,(void*) i);
+
+
+
+
+
+    if (cmd == 'b') {
+
+
+      dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+
+
+      obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+
+
+    }
+
+
+    else if (cmd == 'c') {
+
+
+      sides[0] *= 0.5;
+
+
+      dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
+
+
+      obj[i].geom[0] = dCreateCCylinder (space,sides[0],sides[1]);
+
+
+    }
+
+
+    else if (cmd == 's') {
+
+
+      sides[0] *= 0.5;
+
+
+      dMassSetSphere (&m,DENSITY,sides[0]);
+
+
+      obj[i].geom[0] = dCreateSphere (space,sides[0]);
+
+
+    }
+
+
+    else if (cmd == 'x') {
+
+
+      dGeomID g2[GPB];		// encapsulated geometries
+
+
+      dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+
+
+
+
+      // start accumulating masses for the encapsulated geometries
+
+
+      dMass m2;
+
+
+      dMassSetZero (&m);
+
+
+
+
+
+      // set random delta positions
+
+
+      for (j=0; j<GPB; j++) {
+
+
+	for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+
+
+      }
+
+
+
+
+
+      for (k=0; k<3; k++) {
+
+
+	obj[i].geom[k] = dCreateGeomTransform (space);
+
+
+	dGeomTransformSetCleanup (obj[i].geom[k],1);
+
+
+	if (k==0) {
+
+
+	  dReal radius = dRandReal()*0.25+0.05;
+
+
+	  g2[k] = dCreateSphere (0,radius);
+
+
+	  dMassSetSphere (&m2,DENSITY,radius);
+
+
+	}
+
+
+	else if (k==1) {
+
+
+	  g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+
+
+	  dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+
+
+	}
+
+
+	else {
+
+
+	  dReal radius = dRandReal()*0.1+0.05;
+
+
+	  dReal length = dRandReal()*1.0+0.1;
+
+
+	  g2[k] = dCreateCCylinder (0,radius,length);
+
+
+	  dMassSetCappedCylinder (&m2,DENSITY,3,radius,length);
+
+
+	}
+
+
+	dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+
+
+
+
+	// set the transformation (adjust the mass too)
+
+
+	dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+
+
+	dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+
+
+	dMatrix3 Rtx;
+
+
+	dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+
+
+			    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+
+
+	dGeomSetRotation (g2[k],Rtx);
+
+
+	dMassRotate (&m2,Rtx);
+
+
+
+
+
+	// add to the total mass
+
+
+	dMassAdd (&m,&m2);
+
+
+      }
+
+
+
+
+
+      // move all encapsulated objects so that the center of mass is (0,0,0)
+
+
+      for (k=0; k<2; k++) {
+
+
+	dGeomSetPosition (g2[k],
+
+
+			  dpos[k][0]-m.c[0],
+
+
+			  dpos[k][1]-m.c[1],
+
+
+			  dpos[k][2]-m.c[2]);
+
+
+      }
+
+
+      dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+
+
+    }
+
+
+
+
+
+    for (k=0; k < GPB; k++) {
+
+
+      if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+
+
+    }
+
+
+
+
+
+    dBodySetMass (obj[i].body,&m);
+
+
+  }
+
+
+
+
+
+  if (cmd == ' ') {
+
+
+    selected++;
+
+
+    if (selected >= num) selected = 0;
+
+
+    if (selected < 0) selected = 0;
+
+
+  }
+
+
+  else if (cmd == 'd' && selected >= 0 && selected < num) {
+
+
+    dBodyDisable (obj[selected].body);
+
+
+  }
+
+
+  else if (cmd == 'e' && selected >= 0 && selected < num) {
+
+
+    dBodyEnable (obj[selected].body);
+
+
+  }
+
+
+}
+
+
+
+
+
+
+
+
+// draw a geom
+
+
+
+
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R)
+
+
+{
+
+
+  if (!g) return;
+
+
+  if (!pos) pos = dGeomGetPosition (g);
+
+
+  if (!R) R = dGeomGetRotation (g);
+
+
+
+
+
+  int type = dGeomGetClass (g);
+
+
+  if (type == dBoxClass) {
+
+
+    dVector3 sides;
+
+
+    dGeomBoxGetLengths (g,sides);
+
+
+    dsDrawBox (pos,R,sides);
+
+
+  }
+
+
+  else if (type == dSphereClass) {
+
+
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+
+
+  }
+
+
+  else if (type == dCCylinderClass) {
+
+
+    dReal radius,length;
+
+
+    dGeomCCylinderGetParams (g,&radius,&length);
+
+
+    dsDrawCappedCylinder (pos,R,length,radius);
+
+
+  }
+
+
+  else if (type == dGeomTransformClass) {
+
+
+    dGeomID g2 = dGeomTransformGetGeom (g);
+
+
+    const dReal *pos2 = dGeomGetPosition (g2);
+
+
+    const dReal *R2 = dGeomGetRotation (g2);
+
+
+    dVector3 actual_pos;
+
+
+    dMatrix3 actual_R;
+
+
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+
+
+    actual_pos[0] += pos[0];
+
+
+    actual_pos[1] += pos[1];
+
+
+    actual_pos[2] += pos[2];
+
+
+    dMULTIPLY0_333 (actual_R,R,R2);
+
+
+    drawGeom (g2,actual_pos,actual_R);
+
+
+  }
+
+
+}
+
+
+
+
+
+
+
+
+// simulation loop
+
+
+
+
+
+static void simLoop (int pause)
+
+
+{
+
+
+  dsSetColor (0,0,2);
+
+
+  dSpaceCollide (space,0,&nearCallback);
+
+
+  if (!pause) dWorldStep (world,0.05);
+
+
+
+
+
+  // remove all contact joints
+
+
+  dJointGroupEmpty (contactgroup);
+
+
+
+
+
+  dsSetColor (1,1,0);
+
+
+  dsSetTexture (DS_WOOD);
+
+
+  for (int i=0; i<num; i++) {
+
+
+    int color_changed = 0;
+
+
+    if (i==selected) {
+
+
+      dsSetColor (0,0.7,1);
+
+
+      color_changed = 1;
+
+
+    }
+
+
+    else if (! dBodyIsEnabled (obj[i].body)) {
+
+
+      dsSetColor (1,0,0);
+
+
+      color_changed = 1;
+
+
+    }
+
+
+    for (int j=0; j < GPB; j++) drawGeom (obj[i].geom[j],0,0);
+
+
+    if (color_changed) dsSetColor (1,1,0);
+
+
+  }
+
+
+
+
+
+  {for (int i = 0; i < RayCount; i++){
+
+
+	  dVector3 Origin, Direction;
+
+
+	  dGeomRayGet(Rays[i], Origin, Direction);
+
+
+  
+
+
+	  dReal Length = dGeomRayGetLength(Rays[i]);
+
+
+
+
+
+	  dVector3 End;
+
+
+	  End[0] = Origin[0] + (Direction[0] * Length);
+
+
+	  End[1] = Origin[1] + (Direction[1] * Length);
+
+
+	  End[2] = Origin[2] + (Direction[2] * Length);
+
+
+	  End[3] = Origin[3] + (Direction[3] * Length);
+
+
+  
+
+
+	  dsDrawLine(Origin, End);
+
+
+  }}
+
+
+}
+
+
+
+
+
+
+
+
+int main (int argc, char **argv)
+
+
+{
+
+
+  // setup pointers to drawstuff callback functions
+
+
+  dsFunctions fn;
+
+
+  fn.version = DS_VERSION;
+
+
+  fn.start = &start;
+
+
+  fn.step = &simLoop;
+
+
+  fn.command = &command;
+
+
+  fn.stop = 0;
+
+
+  fn.path_to_textures = "../../drawstuff/textures";
+
+
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+
+
+  // create world
+
+
+
+
+
+  world = dWorldCreate();
+
+
+  space = dHashSpaceCreate();
+
+
+  contactgroup = dJointGroupCreate (0);
+
+
+  dWorldSetGravity (world,0,0,-0.5);
+
+
+  dWorldSetCFM (world,1e-5);
+
+
+  dCreatePlane (space,0,0,1,0);
+
+
+  memset (obj,0,sizeof(obj));
+
+
+
+
+
+  dVector3 Origin, Direction;
+
+
+  
+
+
+  RayCount = 5;
+
+
+  Rays = new dGeomID[RayCount];
+
+
+
+
+
+  /* Ray 0 */
+
+
+  Origin[0] = 1;
+
+
+  Origin[1] = 1;
+
+
+  Origin[2] = 1.5;
+
+
+  Origin[3] = 0;
+
+
+
+
+
+  Direction[0] = 0.0f;
+
+
+  Direction[1] = 0.0f;
+
+
+  Direction[2] = -1;
+
+
+  Direction[3] = 0;
+
+
+
+
+
+  dNormalize3(Direction);
+
+
+
+
+
+  Rays[0] = dGeomCreateRay(space, 5.0f);
+
+
+  dGeomRaySet(Rays[0], Origin, Direction);
+
+
+
+
+
+  /* Ray 1 */
+
+
+  Origin[0] = 0;
+
+
+  Origin[1] = 10;
+
+
+  Origin[2] = 0.25;
+
+
+  Origin[3] = 0;
+
+
+
+
+
+  Direction[0] = 0.0f;
+
+
+  Direction[1] = -1.0f;
+
+
+  Direction[2] = 0.0f;
+
+
+  Direction[3] = 0;
+
+
+
+
+
+  dNormalize3(Direction);
+
+
+
+
+
+  Rays[1] = dGeomCreateRay(space, 20.0f);
+
+
+  dGeomRaySet(Rays[1], Origin, Direction);
+
+
+
+
+
+  /* Ray 2 */
+
+
+  Origin[0] = -10;
+
+
+  Origin[1] = 0;
+
+
+  Origin[2] = 0.20;
+
+
+  Origin[3] = 0;
+
+
+
+
+
+  Direction[0] = 1.0f;
+
+
+  Direction[1] = 0.0f;
+
+
+  Direction[2] = 0.0f;
+
+
+  Direction[3] = 0;
+
+
+
+
+
+  dNormalize3(Direction);
+
+
+
+
+
+  Rays[2] = dGeomCreateRay(space, 20.0f);
+
+
+  dGeomRaySet(Rays[2], Origin, Direction);
+
+
+
+
+
+  /* Ray 3 */
+
+
+  Origin[0] = -9;
+
+
+  Origin[1] = 11;
+
+
+  Origin[2] = 0.15;
+
+
+  Origin[3] = 0;
+
+
+
+
+
+  Direction[0] = 1.0f;
+
+
+  Direction[1] = -1.0f;
+
+
+  Direction[2] = 0.0f;
+
+
+  Direction[3] = 0;
+
+
+
+
+
+  dNormalize3(Direction);
+
+
+
+
+
+  Rays[3] = dGeomCreateRay(space, 20.0f);
+
+
+  dGeomRaySet(Rays[3], Origin, Direction);
+
+
+
+
+
+  /* Ray 4 */
+
+
+  Origin[0] = -0.1;
+
+
+  Origin[1] = 0.3;
+
+
+  Origin[2] = 0.30;
+
+
+  Origin[3] = 0;
+
+
+
+
+
+  Direction[0] = 0.3f;
+
+
+  Direction[1] = 0.5f;
+
+
+  Direction[2] = 1.0f;
+
+
+  Direction[3] = 0;
+
+
+
+
+
+  Rays[4] = dGeomCreateRay(space, 5.0f);
+
+
+  dGeomRaySet(Rays[4], Origin, Direction);
+
+
+
+
+
+  // run simulation
+
+
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+
+
+
+
+  dJointGroupDestroy (contactgroup);
+
+
+  dSpaceDestroy (space);
+
+
+  dWorldDestroy (world);
+
+
+
+
+
+  return 0;
+
+
+}
+
+
Index: /code/branches/ode/ode-0.9/contrib/dRay/dRay.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/dRay.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/dRay.cpp	(revision 216)
@@ -0,0 +1,119 @@
+#include "Include\dRay.h"
+#include "dxRay.h"
+
+int dRayClass = -1;
+
+void dAABBRay(dxGeom* Ray, dReal AABB[6]){
+	dVector3 Start, End;
+	dGeomRayGet(Ray, Start, End);
+	dReal Length = dGeomRayGetLength(Ray);
+
+	End[0] = Start[0] + End[0] * Length;
+	End[1] = Start[1] + End[1] * Length;
+	End[2] = Start[2] + End[2] * Length;
+	End[3] = Start[3] + End[3] * Length;
+
+	if (Start[0] < End[0]){
+		AABB[0] = Start[0];
+		AABB[1] = End[0];
+	}
+	else{
+		AABB[0] = End[0];
+		AABB[1] = Start[0];
+	}
+
+	if (Start[1] < End[1]){
+		AABB[2] = Start[1];
+		AABB[3] = End[1];
+	}
+	else{
+		AABB[2] = End[1];
+		AABB[3] = Start[1];
+	}
+
+	if (Start[2] < End[2]){
+		AABB[4] = Start[2];
+		AABB[5] = End[2];
+	}
+	else{
+		AABB[4] = End[2];
+		AABB[5] = Start[2];
+	}
+	// Should we tweak the box to have a minimum size for axis aligned lines? How small should it be?
+}
+
+dColliderFn* dRayColliderFn(int num){
+	if (num == dPlaneClass) return (dColliderFn*)&dCollidePR;
+	if (num == dSphereClass) return (dColliderFn*)&dCollideSR;
+	if (num == dBoxClass) return (dColliderFn*)&dCollideBR;
+	if (num == dCCylinderClass) return (dColliderFn*)&dCollideCCR;
+	return 0;
+}
+
+dxGeom* dGeomCreateRay(dSpaceID space, dReal Length){
+	if (dRayClass == -1){
+		dGeomClass c;
+		c.bytes = sizeof(dxRay);
+		c.collider = &dRayColliderFn;
+		c.aabb = &dAABBRay;
+		c.aabb_test = 0;
+		c.dtor = 0;
+
+		dRayClass = dCreateGeomClass(&c);
+	}
+
+	dxGeom* g = dCreateGeom(dRayClass);
+	if (space) dSpaceAdd(space, g);
+
+	dGeomRaySetLength(g, Length);
+	return g;
+}
+
+void dGeomRaySetLength(dxGeom* g, dReal Length){
+	((dxRay*)dGeomGetClassData(g))->Length = Length;
+}
+
+dReal dGeomRayGetLength(dxGeom* g){
+	return ((dxRay*)dGeomGetClassData(g))->Length;
+}
+
+void dGeomRaySet(dxGeom* g, dVector3 Origin, dVector3 Direction){
+	dGeomSetPosition(g, Origin[0], Origin[1], Origin[2]);
+
+	dVector3 Up, Right;
+	dPlaneSpace(Direction, Up, Right);
+
+	Origin[3] = Up[3] = Right[3] = REAL(0.0);
+
+	dMatrix3 Rotation;
+	Rotation[0 * 4 + 0] = Right[0];
+	Rotation[1 * 4 + 0] = Right[1];
+	Rotation[2 * 4 + 0] = Right[2];
+	Rotation[3 * 4 + 0] = Right[3];
+
+	Rotation[0 * 4 + 1] = Up[0];
+	Rotation[1 * 4 + 1] = Up[1];
+	Rotation[2 * 4 + 1] = Up[2];
+	Rotation[3 * 4 + 1] = Up[3];
+
+	Rotation[0 * 4 + 2] = Direction[0];
+	Rotation[1 * 4 + 2] = Direction[1];
+	Rotation[2 * 4 + 2] = Direction[2];
+	Rotation[3 * 4 + 2] = Direction[3];
+
+	dGeomSetRotation(g, Rotation);
+}
+
+void dGeomRayGet(dxGeom* g, dVector3 Origin, dVector3 Direction){
+	const dReal* Position = dGeomGetPosition(g);
+	Origin[0] = Position[0];
+	Origin[1] = Position[1];
+	Origin[2] = Position[2];
+	Origin[3] = Position[3];
+
+	const dReal* Rotation = dGeomGetRotation(g);
+	Direction[0] = Rotation[0 * 4 + 2];
+	Direction[1] = Rotation[1 * 4 + 2];
+	Direction[2] = Rotation[2 * 4 + 2];
+	Direction[3] = Rotation[3 * 4 + 2];
+}
Index: /code/branches/ode/ode-0.9/contrib/dRay/dRay_Box.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/dRay_Box.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/dRay_Box.cpp	(revision 216)
@@ -0,0 +1,134 @@
+// Ripped from Magic Software
+
+#include "Include\dRay.h"
+#include "dxRay.h"
+
+bool Clip(dReal Denom, dReal Numer, dReal& T0, dReal& T1){
+    // Return value is 'true' if line segment intersects the current test
+    // plane.  Otherwise 'false' is returned in which case the line segment
+    // is entirely clipped.
+	
+    if (Denom > REAL(0.0)){
+		if (Numer > Denom * T1){
+            return false;
+		}
+
+        if (Numer > Denom * T0){
+            T0 = Numer / Denom;
+		}
+        return true;
+    }
+    else if (Denom < REAL(0.0)){
+        if (Numer > Denom * T0){
+            return false;
+		}
+
+        if (Numer > Denom * T1){
+            T1 = Numer / Denom;
+		}
+        return true;
+    }
+    else return Numer <= REAL(0.0);
+}
+
+bool FindIntersection(const dVector3 Origin, const dVector3 Direction, const dVector3 Extents, dReal& T0, dReal& T1){
+    dReal SaveT0 = T0;
+	dReal SaveT1 = T1;
+
+    bool NotEntirelyClipped =
+        Clip(+Direction[0], -Origin[0] - Extents[0], T0, T1) &&
+        Clip(-Direction[0], +Origin[0] - Extents[0], T0, T1) &&
+        Clip(+Direction[1], -Origin[1] - Extents[1], T0, T1) &&
+        Clip(-Direction[1], +Origin[1] - Extents[1], T0, T1) &&
+        Clip(+Direction[2], -Origin[2] - Extents[2], T0, T1) &&
+        Clip(-Direction[2], +Origin[2] - Extents[2], T0, T1);
+
+    return NotEntirelyClipped && (T0 != SaveT0 || T1 != SaveT1);
+}
+
+int dCollideBR(dxGeom* RayGeom, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride){
+	const dVector3& Position = *(const dVector3*)dGeomGetPosition(BoxGeom);
+	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(BoxGeom);
+	dVector3 Extents;
+	dGeomBoxGetLengths(BoxGeom, Extents);
+	Extents[0] /= 2;
+	Extents[1] /= 2;
+	Extents[2] /= 2;
+	Extents[3] /= 2;
+
+	dVector3 Origin, Direction;
+	dGeomRayGet(RayGeom, Origin, Direction);
+	dReal Length = dGeomRayGetLength(RayGeom);
+
+	dVector3 Diff;
+	Diff[0] = Origin[0] - Position[0];
+	Diff[1] = Origin[1] - Position[1];
+	Diff[2] = Origin[2] - Position[2];
+	Diff[3] = Origin[3] - Position[3];
+
+	Direction[0] *= Length;
+	Direction[1] *= Length;
+	Direction[2] *= Length;
+	Direction[3] *= Length;
+
+	dVector3 Rot[3];
+	Decompose(Rotation, Rot);
+
+	dVector3 TransOrigin;
+	TransOrigin[0] = dDOT(Diff, Rot[0]);
+	TransOrigin[1] = dDOT(Diff, Rot[1]);
+	TransOrigin[2] = dDOT(Diff, Rot[2]);
+	TransOrigin[3] = REAL(0.0);
+
+	dVector3 TransDirection;
+	TransDirection[0] = dDOT(Direction, Rot[0]);
+	TransDirection[1] = dDOT(Direction, Rot[1]);
+	TransDirection[2] = dDOT(Direction, Rot[2]);
+	TransDirection[3] = REAL(0.0);
+
+	dReal T[2];
+	T[0] = 0.0f;
+	T[1] = dInfinity;
+
+	bool Intersect = FindIntersection(TransOrigin, TransDirection, Extents, T[0], T[1]);
+
+	if (Intersect){
+		if (T[0] > REAL(0.0)){
+			dContactGeom* Contact0 = CONTACT(Flags, Contacts, 0, Stride);
+			Contact0->pos[0] = Origin[0] + T[0] * Direction[0];
+			Contact0->pos[1] = Origin[1] + T[0] * Direction[1];
+			Contact0->pos[2] = Origin[2] + T[0] * Direction[2];
+			Contact0->pos[3] = Origin[3] + T[0] * Direction[3];
+			//Contact0->normal = 0;
+			Contact0->depth = 0.0f;
+			Contact0->g1 = RayGeom;
+			Contact0->g2 = BoxGeom;
+
+			dContactGeom* Contact1 = CONTACT(Flags, Contacts, 1, Stride);
+			Contact1->pos[0] = Origin[0] + T[1] * Direction[0];
+			Contact1->pos[1] = Origin[1] + T[1] * Direction[1];
+			Contact1->pos[2] = Origin[2] + T[1] * Direction[2];
+			Contact1->pos[3] = Origin[3] + T[1] * Direction[3];
+			//Contact1->normal = 0;
+			Contact1->depth = 0.0f;
+			Contact1->g1 = RayGeom;
+			Contact1->g2 = BoxGeom;
+
+			return 2;
+		}
+		else{
+			dContactGeom* Contact = CONTACT(Flags, Contacts, 0, Stride);
+			Contact->pos[0] = Origin[0] + T[1] * Direction[0];
+			Contact->pos[1] = Origin[1] + T[1] * Direction[1];
+			Contact->pos[2] = Origin[2] + T[1] * Direction[2];
+			Contact->pos[3] = Origin[3] + T[1] * Direction[3];
+			//Contact->normal = 0;
+			Contact->depth = 0.0f;
+			Contact->g1 = RayGeom;
+			Contact->g2 = BoxGeom;
+
+			return 1;
+		}
+	}
+	else return 0;
+}
Index: /code/branches/ode/ode-0.9/contrib/dRay/dRay_CCylinder.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/dRay_CCylinder.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/dRay_CCylinder.cpp	(revision 216)
@@ -0,0 +1,199 @@
+// Ripped from Magic Software
+
+#include "Include\dRay.h"
+#include "dxRay.h"
+
+int Find(const dVector3 Origin, dVector3 Direction, dReal Length, const dVector3 CCPos, const dMatrix3 CCRot, dReal CCRadius, dReal CCLength, dReal T[2]){
+	dVector3 U, V, W;
+	Decompose(CCRot, U, V, W);
+
+	dVector3 CCOrigin;
+	CCOrigin[0] = CCPos[0] - (W[0] * CCLength / 2);
+	CCOrigin[1] = CCPos[1] - (W[1] * CCLength / 2);
+	CCOrigin[2] = CCPos[2] - (W[2] * CCLength / 2);
+	CCOrigin[3] = CCPos[3] - (W[3] * CCLength / 2);
+	
+	dVector3 D;
+	D[0] = dDOT(U, Direction);
+	D[1] = dDOT(V, Direction);
+	D[2] = dDOT(W, Direction);
+
+	dReal DMag = Length;
+	dReal InvDMag = REAL(1.0) / DMag;
+
+	dVector3 Diff;
+	Diff[0] = Origin[0] - CCOrigin[0];
+	Diff[1] = Origin[1] - CCOrigin[1];
+	Diff[2] = Origin[2] - CCOrigin[2];
+	Diff[3] = Origin[3] - CCOrigin[3];
+
+	dVector3 P;
+	P[0] = dDOT(U, Diff);
+	P[1] = dDOT(V, Diff);
+	P[2] = dDOT(W, Diff);
+
+	dReal CCRadiusSq = CCRadius * CCRadius;
+
+	dReal Epsilon = 1e-12f;
+
+	if (dFabs(D[2]) >= REAL(1.0) - Epsilon){	// line is parallel to capsule axis
+		dReal Discr =  CCRadiusSq - P[0] * P[0] - P[1] * P[1];
+
+		if (Discr >= REAL(0.0)){
+            dReal Root = dSqrt(Discr);
+            T[0] = (-P[2] + Root) * InvDMag;
+            T[1] = (CCLength - P[2] + Root) * InvDMag;
+            return 2;
+        }
+        else return 0;
+	}
+
+	// test intersection with infinite cylinder
+    dReal A = D[0] * D[0] + D[1] * D[1];
+    dReal B = P[0] * D[0] + P[1] * D[1];
+    dReal C = P[0] * P[0] + P[1] * P[1] - CCRadiusSq;
+    dReal Discr = B * B - A * C;
+    if (Discr < REAL(0.0)){	// line does not intersect infinite cylinder
+        return 0;
+    }
+
+	int Count = 0;
+
+    if (Discr > REAL(0.0)){	// line intersects infinite cylinder in two places
+        dReal Root = dSqrt(Discr);
+        dReal Inv = REAL(1.0) / A;
+
+		dReal TTemp = (-B - Root) * Inv;
+
+        dReal Tmp = P[2] + TTemp * D[2];
+        if (REAL(0.0) <= Tmp && Tmp <= CCLength){
+			T[Count++] = TTemp * InvDMag;
+		}
+		
+		
+        TTemp = (-B + Root) * Inv;
+        Tmp = P[2] + TTemp * D[2];
+        if (REAL(0.0) <= Tmp && Tmp <= CCLength){
+			T[Count++] = TTemp * InvDMag;
+		}
+
+        if (Count == 2){	// line intersects capsule wall in two places
+            return 2;
+        }
+    }
+	else{	// line is tangent to infinite cylinder
+        dReal TTemp = -B / A;
+        dReal Tmp = P[2] + TTemp * D[2];
+        if (REAL(0.0) <= Tmp && Tmp <= CCLength){
+            T[0] = TTemp * InvDMag;
+            return 1;
+        }
+    }
+
+	// test intersection with bottom hemisphere
+    // fA = 1
+    B += P[2] * D[2];
+    C += P[2] * P[2];
+    Discr = B * B - C;
+    if (Discr > REAL(0.0)){
+        dReal Root = dSqrt(Discr);
+        dReal TTemp = -B - Root;
+        dReal Tmp = P[2] + TTemp * D[2];
+        if (Tmp <= REAL(0.0)){
+            T[Count++] = TTemp * InvDMag;
+            if (Count == 2){
+                return 2;
+			}
+        }
+
+        TTemp = -B + Root;
+        Tmp = P[2] + TTemp * D[2];
+        if (Tmp <= REAL(0.0)){
+            T[Count++] = TTemp * InvDMag;
+            if (Count == 2){
+                return 2;
+			}
+        }
+    }
+    else if (Discr == REAL(0.0)){
+        dReal TTemp = -B;
+        dReal Tmp = P[2] + TTemp * D[2];
+        if (Tmp <= REAL(0.0)){
+            T[Count++] = TTemp * InvDMag;
+            if (Count == 2){
+                return 2;
+			}
+        }
+    }
+
+	// test intersection with top hemisphere
+    // fA = 1
+    B -= D[2] * CCLength;
+    C += CCLength * (CCLength - REAL(2.0) * P[2]);
+
+    Discr = B * B - C;
+    if (Discr > REAL(0.0)){
+        dReal Root = dSqrt(Discr);
+        dReal TTemp = -B - Root;
+        dReal Tmp = P[2] + TTemp * D[2];
+        if (Tmp >= CCLength){
+
+            T[Count++] = TTemp * InvDMag;
+            if (Count == 2){
+                return 2;
+			}
+        }
+
+        TTemp = -B + Root;
+        Tmp = P[2] + TTemp * D[2];
+        if (Tmp >= CCLength){
+            T[Count++] = TTemp * InvDMag;
+            if (Count == 2){
+                return 2;
+			}
+        }
+    }
+    else if (Discr == REAL(0.0)){
+        dReal TTemp = -B;
+        dReal Tmp = P[2] + TTemp * D[2];
+        if (Tmp >= CCLength){
+            T[Count++] = TTemp * InvDMag;
+            if (Count == 2){
+                return 2;
+			}
+        }
+    }
+	return Count;
+}
+
+int dCollideCCR(dxGeom* RayGeom, dxGeom* CCGeom, int Flags, dContactGeom* Contacts, int Stride){
+	const dVector3& CCPos = *(const dVector3*)dGeomGetPosition(CCGeom);
+	const dMatrix3& CCRot = *(const dMatrix3*)dGeomGetRotation(CCGeom);
+
+	dReal CCRadius, CCLength;
+	dGeomCCylinderGetParams(CCGeom, &CCRadius, &CCLength);
+
+	dVector3 Origin, Direction;
+	dGeomRayGet(RayGeom, Origin, Direction);
+	dReal Length = dGeomRayGetLength(RayGeom);
+
+	dReal T[2];
+    int Count = Find(Origin, Direction, Length, CCPos, CCRot, CCRadius, CCLength, T);
+	int ContactCount = 0;
+	for (int i = 0; i < Count; i++){
+		if (T[i] >= 0.0){
+			dContactGeom* Contact = CONTACT(Flags, Contacts, ContactCount, Stride);
+			Contact->pos[0] = Origin[0] + T[i] * Direction[0] * Length;
+			Contact->pos[1] = Origin[1] + T[i] * Direction[1] * Length;
+			Contact->pos[2] = Origin[2] + T[i] * Direction[2] * Length;
+			Contact->pos[3] = Origin[3] + T[i] * Direction[3] * Length;
+			//Contact->normal = 0;
+			Contact->depth = 0.0f;
+			Contact->g1 = RayGeom;
+			Contact->g2 = CCGeom;
+
+			ContactCount++;
+		}
+	}
+    return ContactCount;
+}
Index: /code/branches/ode/ode-0.9/contrib/dRay/dRay_Plane.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/dRay_Plane.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/dRay_Plane.cpp	(revision 216)
@@ -0,0 +1,35 @@
+// Ripped from Paul Bourke
+
+#include "Include\dRay.h"
+#include "dxRay.h"
+
+int dCollidePR(dxGeom* RayGeom, dxGeom* PlaneGeom, int Flags, dContactGeom* Contact, int Stride){
+	dVector3 Plane;
+	dGeomPlaneGetParams(PlaneGeom, Plane);
+
+	dVector3 Origin, Direction;
+	dGeomRayGet(RayGeom, Origin, Direction);
+
+	dReal Length = dGeomRayGetLength(RayGeom);
+
+	dReal Denom = Plane[0] * Direction[0] + Plane[1] * Direction[1] + Plane[2] * Direction[2];
+	if (dFabs(Denom) < 0.00001f){
+		return 0;	// Ray never hits
+	}
+	
+	float T = -(Plane[3] + Plane[0] * Origin[0] + Plane[1] * Origin[1] + Plane[2] * Origin[2]) / Denom;
+	
+	if (T < 0 || T > Length){
+		return 0;	// Ray hits but not within boundaries
+	}
+
+	Contact->pos[0] = Origin[0] + T * Direction[0];
+	Contact->pos[1] = Origin[1] + T * Direction[1];
+	Contact->pos[2] = Origin[2] + T * Direction[2];
+	Contact->pos[3] = REAL(0.0);
+	//Contact->normal = 0;
+	Contact->depth = 0.0f;
+	Contact->g1 = RayGeom;
+	Contact->g2 = PlaneGeom;
+	return 1;
+}
Index: /code/branches/ode/ode-0.9/contrib/dRay/dRay_Sphere.cpp
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/dRay_Sphere.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/dRay_Sphere.cpp	(revision 216)
@@ -0,0 +1,95 @@
+// Ripped from Magic Software
+
+#include "Include\dRay.h"
+#include "dxRay.h"
+
+int dCollideSR(dxGeom* RayGeom, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride){
+	const dVector3& Position = *(const dVector3*)dGeomGetPosition(SphereGeom);
+	dReal Radius = dGeomSphereGetRadius(SphereGeom);
+
+	dVector3 Origin, Direction;
+	dGeomRayGet(RayGeom, Origin, Direction);
+	dReal Length = dGeomRayGetLength(RayGeom);
+
+	dVector3 Diff;
+	Diff[0] = Origin[0] - Position[0];
+	Diff[1] = Origin[1] - Position[1];
+	Diff[2] = Origin[2] - Position[2];
+	Diff[3] = Origin[3] - Position[3];
+
+	Direction[0] *= Length;
+	Direction[1] *= Length;
+	Direction[2] *= Length;
+	Direction[3] *= Length;
+
+	dReal A = Length * Length;
+	dReal B = dDOT(Diff, Direction);
+	dReal C = dDOT(Diff, Diff) - (Radius * Radius);
+
+	dReal Discr = B * B - A * C;
+	if (Discr < REAL(0.0)){
+		return 0;
+	}
+	else if (Discr > REAL(0.0)){
+		dReal T[2];
+		dReal Root = dSqrt(Discr);
+		dReal InvA = REAL(1.0) / A;
+		T[0] = (-B - Root) * InvA;
+		T[1] = (-B + Root) * InvA;
+
+		if (T[0] >= REAL(0.0)){
+			dContactGeom* Contact0 = CONTACT(Flags, Contacts, 0, Stride);
+			Contact0->pos[0] = Origin[0] + T[0] * Direction[0];
+			Contact0->pos[1] = Origin[1] + T[0] * Direction[1];
+			Contact0->pos[2] = Origin[2] + T[0] * Direction[2];
+			Contact0->pos[3] = Origin[3] + T[0] * Direction[3];
+			//Contact0->normal = 0;
+			Contact0->depth = 0.0f;
+			Contact0->g1 = RayGeom;
+			Contact0->g2 = SphereGeom;
+
+			dContactGeom* Contact1 = CONTACT(Flags, Contacts, 1, Stride);
+			Contact1->pos[0] = Origin[0] + T[1] * Direction[0];
+			Contact1->pos[1] = Origin[1] + T[1] * Direction[1];
+			Contact1->pos[2] = Origin[2] + T[1] * Direction[2];
+			Contact1->pos[3] = Origin[3] + T[1] * Direction[3];
+			//Contact1->normal = 0;
+			Contact1->depth = 0.0f;
+			Contact1->g1 = RayGeom;
+			Contact1->g2 = SphereGeom;
+
+			return 2;
+		}
+		else if (T[1] >= REAL(0.0)){
+			dContactGeom* Contact = CONTACT(Flags, Contacts, 1, Stride);
+			Contact->pos[0] = Origin[0] + T[1] * Direction[0];
+			Contact->pos[1] = Origin[1] + T[1] * Direction[1];
+			Contact->pos[2] = Origin[2] + T[1] * Direction[2];
+			Contact->pos[3] = Origin[3] + T[1] * Direction[3];
+			//Contact->normal = 0;
+			Contact->depth = 0.0f;
+			Contact->g1 = RayGeom;
+			Contact->g2 = SphereGeom;
+
+            return 1;
+		}
+		else return 0;
+	}
+	else{
+		dReal T;
+		T = -B / A;
+		if (T >= REAL(0.0)){
+			dContactGeom* Contact = CONTACT(Flags, Contacts, 0, Stride);
+			Contact->pos[0] = Origin[0] + T * Direction[0];
+			Contact->pos[1] = Origin[1] + T * Direction[1];
+			Contact->pos[2] = Origin[2] + T * Direction[2];
+			Contact->pos[3] = Origin[3] + T * Direction[3];
+			//Contact->normal = 0;
+			Contact->depth = 0.0f;
+			Contact->g1 = RayGeom;
+			Contact->g2 = SphereGeom;
+            return 1;
+		}
+		else return 0;
+	}
+}
Index: /code/branches/ode/ode-0.9/contrib/dRay/dxRay.h
===================================================================
--- /code/branches/ode/ode-0.9/contrib/dRay/dxRay.h	(revision 216)
+++ /code/branches/ode/ode-0.9/contrib/dRay/dxRay.h	(revision 216)
@@ -0,0 +1,32 @@
+struct dxRay{
+	dReal Length;
+};
+
+inline void Decompose(const dMatrix3 Matrix, dVector3 Right, dVector3 Up, dVector3 Direction){
+	Right[0] = Matrix[0 * 4 + 0];
+	Right[1] = Matrix[1 * 4 + 0];
+	Right[2] = Matrix[2 * 4 + 0];
+	Right[3] = Matrix[3 * 4 + 0];
+	Up[0] = Matrix[0 * 4 + 1];
+	Up[1] = Matrix[1 * 4 + 1];
+	Up[2] = Matrix[2 * 4 + 1];
+	Up[3] = Matrix[3 * 4 + 1];
+	Direction[0] = Matrix[0 * 4 + 2];
+	Direction[1] = Matrix[1 * 4 + 2];
+	Direction[2] = Matrix[2 * 4 + 2];
+	Direction[3] = Matrix[3 * 4 + 2];
+}
+
+inline void Decompose(const dMatrix3 Matrix, dVector3 Vectors[3]){
+	Decompose(Matrix, Vectors[0], Vectors[1], Vectors[2]);
+}
+
+inline dContactGeom* CONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){
+	dIASSERT(Index >= 0 && Index < (Flags & 0x0ffff));
+	return ((dContactGeom*)(((char*)Contacts) + (Index * Stride)));
+}
+
+int dCollidePR(dxGeom* RayGeom, dxGeom* PlaneGeom, int Flags, dContactGeom* Contacts, int Stride);
+int dCollideSR(dxGeom* RayGeom, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride);
+int dCollideBR(dxGeom* RayGeom, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride);
+int dCollideCCR(dxGeom* RayGeom, dxGeom* CCylinderGeom, int Flags, dContactGeom* Contacts, int Stride);
Index: /code/branches/ode/ode-0.9/depcomp
===================================================================
--- /code/branches/ode/ode-0.9/depcomp	(revision 216)
+++ /code/branches/ode/ode-0.9/depcomp	(revision 216)
@@ -0,0 +1,584 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2006-10-15.18
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software
+# Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
+  tmpdepfile="$stripped.u"
+  if test "$libtool" = yes; then
+    "$@" -Wc,-M
+  else
+    "$@" -M
+  fi
+  stat=$?
+
+  if test -f "$tmpdepfile"; then :
+  else
+    stripped=`echo "$stripped" | sed 's,^.*/,,'`
+    tmpdepfile="$stripped.u"
+  fi
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+
+  if test -f "$tmpdepfile"; then
+    outname="$stripped.o"
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add `dependent.h:' lines.
+    sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+  else
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # With Tru64 cc, shared objects can also be used to make a
+      # static library.  This mechanism is used in libtool 1.4 series to
+      # handle both shared and static libraries in a single compilation.
+      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+      #
+      # With libtool 1.5 this exception was removed, and libtool now
+      # generates 2 separate objects for the 2 libraries.  These two
+      # compilations output dependencies in $dir.libs/$base.o.d and
+      # in $dir$base.o.d.  We have to check for both files, because
+      # one of the two compilations can be disabled.  We should prefer
+      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+      # automatically cleaned when .libs/ is deleted, while ignoring
+      # the former would cause a distcleancheck panic.
+      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
+      tmpdepfile2=$dir$base.o.d          # libtool 1.5
+      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
+      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1=$dir$base.o.d
+      tmpdepfile2=$dir$base.d
+      tmpdepfile3=$dir$base.d
+      tmpdepfile4=$dir$base.d
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+      exit $stat
+   fi
+
+   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+   do
+     test -f "$tmpdepfile" && break
+   done
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no
+  for arg in "$@"; do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix="`echo $object | sed 's/^.*\././'`"
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test $1 != '--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  "$@" || exit $?
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+	set fnord "$@"
+	shift
+	shift
+	;;
+    *)
+	set fnord "$@" "$arg"
+	shift
+	shift
+	;;
+    esac
+  done
+  "$@" -E |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
+  echo "	" >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /code/branches/ode/ode-0.9/docs/annotated.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/annotated.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/annotated.html	(revision 216)
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Data Structures</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li class="current"><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li class="current"><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="functions.html"><span>Data&nbsp;Fields</span></a></li>
+  </ul>
+</div>
+<h1>Open Dynamics Engine Data Structures</h1>Here are the data structures with brief descriptions:<table>
+  <tr><td class="indexkey"><a class="el" href="structd_contact_geom.html">dContactGeom</a></td><td class="indexvalue">Describe the contact point between two geoms </td></tr>
+  <tr><td class="indexkey"><a class="el" href="structds_functions.html">dsFunctions</a></td><td class="indexvalue">Set of functions to be used as callbacks by the simulation loop </td></tr>
+</table>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/collision_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/collision_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/collision_8h-source.html	(revision 216)
@@ -0,0 +1,417 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: collision.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>collision.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_COLLISION_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_COLLISION_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 <span class="preprocessor">#include &lt;ode/collision_space.h&gt;</span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;ode/contact.h&gt;</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00032"></a>00032 <span class="preprocessor">#endif</span>
+<a name="l00033"></a>00033 <span class="preprocessor"></span>
+<a name="l00049"></a>00049 <span class="comment">/* ************************************************************************ */</span>
+<a name="l00050"></a>00050 <span class="comment">/* general functions */</span>
+<a name="l00051"></a>00051 
+<a name="l00065"></a>00065 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (dGeomID geom);
+<a name="l00066"></a>00066 
+<a name="l00067"></a>00067 
+<a name="l00075"></a>00075 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gf68eb443d5c66ab1aaa8a7d38d1dbc4f" title="Set the user-defined data pointer stored in the geom.">dGeomSetData</a> (dGeomID geom, <span class="keywordtype">void</span>* data);
+<a name="l00076"></a>00076 
+<a name="l00077"></a>00077 
+<a name="l00084"></a>00084 ODE_API <span class="keywordtype">void</span> *<a class="code" href="group__collide.html#gc1a185e22b136814fd3afc8469d98996" title="Get the user-defined data pointer stored in the geom.">dGeomGetData</a> (dGeomID geom);
+<a name="l00085"></a>00085 
+<a name="l00086"></a>00086 
+<a name="l00105"></a>00105 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g97cad1194789477eac19fe364d986505" title="Set the body associated with a placeable geom.">dGeomSetBody</a> (dGeomID geom, dBodyID body);
+<a name="l00106"></a>00106 
+<a name="l00107"></a>00107 
+<a name="l00114"></a>00114 ODE_API dBodyID <a class="code" href="group__collide.html#gd6cedf77fde0dddf751c5d42fcc8eebf" title="Get the body associated with a placeable geom.">dGeomGetBody</a> (dGeomID geom);
+<a name="l00115"></a>00115 
+<a name="l00116"></a>00116 
+<a name="l00131"></a>00131 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g71043b70a735e8f5451c3e13cef345fe" title="Set the position vector of a placeable geom.">dGeomSetPosition</a> (dGeomID geom, dReal x, dReal y, dReal z);
+<a name="l00132"></a>00132 
+<a name="l00133"></a>00133 
+<a name="l00146"></a>00146 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g76c510f4b7d5a036d8a36f2d60d670e5" title="Set the rotation matrix of a placeable geom.">dGeomSetRotation</a> (dGeomID geom, <span class="keyword">const</span> dMatrix3 R);
+<a name="l00147"></a>00147 
+<a name="l00148"></a>00148 
+<a name="l00162"></a>00162 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g989149d93162264d699444a57b045150" title="Set the rotation of a placeable geom.">dGeomSetQuaternion</a> (dGeomID geom, <span class="keyword">const</span> dQuaternion Q);
+<a name="l00163"></a>00163 
+<a name="l00164"></a>00164 
+<a name="l00181"></a>00181 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__collide.html#g95b93f803880cac2619fe2635aa93ad8" title="Get the position vector of a placeable geom.">dGeomGetPosition</a> (dGeomID geom);
+<a name="l00182"></a>00182 
+<a name="l00183"></a>00183 
+<a name="l00191"></a>00191 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gd2cccf2b4c62bec58720d4f5fab8108d" title="Copy the position of a geom into a vector.">dGeomCopyPosition</a> (dGeomID geom, dVector3 pos);
+<a name="l00192"></a>00192 
+<a name="l00193"></a>00193 
+<a name="l00210"></a>00210 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__collide.html#g293b2264cefb12f9a6659cacc6a722f7" title="Get the rotation matrix of a placeable geom.">dGeomGetRotation</a> (dGeomID geom);
+<a name="l00211"></a>00211 
+<a name="l00212"></a>00212 
+<a name="l00226"></a>00226 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g800b702e148a8c279596f591b910cfbd" title="Get the rotation matrix of a placeable geom.">dGeomCopyRotation</a>(dGeomID geom, dMatrix3 R);
+<a name="l00227"></a>00227 
+<a name="l00228"></a>00228 
+<a name="l00242"></a>00242 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g11ad7f0098639b06f4bcd2d681122842" title="Get the rotation quaternion of a placeable geom.">dGeomGetQuaternion</a> (dGeomID geom, dQuaternion result);
+<a name="l00243"></a>00243 
+<a name="l00244"></a>00244 
+<a name="l00261"></a>00261 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g904e360ac6e9e85a05e67929990e5b72" title="Return the axis-aligned bounding box.">dGeomGetAABB</a> (dGeomID geom, dReal aabb[6]);
+<a name="l00262"></a>00262 
+<a name="l00263"></a>00263 
+<a name="l00270"></a>00270 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__collide.html#ge5a58bdc78fb4f163a0e9c3ecabf64c9" title="Determing if a geom is a space.">dGeomIsSpace</a> (dGeomID geom);
+<a name="l00271"></a>00271 
+<a name="l00272"></a>00272 
+<a name="l00280"></a>00280 ODE_API dSpaceID <a class="code" href="group__collide.html#gfdc35eade2cbd0b6886ce957325d7c03" title="Query for the space containing a particular geom.">dGeomGetSpace</a> (dGeomID);
+<a name="l00281"></a>00281 
+<a name="l00282"></a>00282 
+<a name="l00307"></a>00307 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__collide.html#g07b5ed5b915f756f419a4a7ce69dc67e" title="Given a geom, this returns its class.">dGeomGetClass</a> (dGeomID geom);
+<a name="l00308"></a>00308 
+<a name="l00309"></a>00309 
+<a name="l00322"></a>00322 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g80fd5741701eb48472521780d5e2f9b9" title="Set the &amp;quot;category&amp;quot; bitfield for the given geom.">dGeomSetCategoryBits</a> (dGeomID geom, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> bits);
+<a name="l00323"></a>00323 
+<a name="l00324"></a>00324 
+<a name="l00337"></a>00337 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#ga55b4de01a61be41668685857b78455d" title="Set the &amp;quot;collide&amp;quot; bitfield for the given geom.">dGeomSetCollideBits</a> (dGeomID geom, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> bits);
+<a name="l00338"></a>00338 
+<a name="l00339"></a>00339 
+<a name="l00348"></a>00348 ODE_API <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <a class="code" href="group__collide.html#gfb62d3493b6789382f65776ab931e78d" title="Get the &amp;quot;category&amp;quot; bitfield for the given geom.">dGeomGetCategoryBits</a> (dGeomID);
+<a name="l00349"></a>00349 
+<a name="l00350"></a>00350 
+<a name="l00359"></a>00359 ODE_API <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <a class="code" href="group__collide.html#g5591e5c496a5a6f8b66dc57e03d0cd8d" title="Get the &amp;quot;collide&amp;quot; bitfield for the given geom.">dGeomGetCollideBits</a> (dGeomID);
+<a name="l00360"></a>00360 
+<a name="l00361"></a>00361 
+<a name="l00374"></a>00374 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#ga7c64b8fcae37ee9541208a0351f3d05" title="Enable a geom.">dGeomEnable</a> (dGeomID geom);
+<a name="l00375"></a>00375 
+<a name="l00376"></a>00376 
+<a name="l00389"></a>00389 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g6cb32b4161435fe491859680b463fc12" title="Disable a geom.">dGeomDisable</a> (dGeomID geom);
+<a name="l00390"></a>00390 
+<a name="l00391"></a>00391 
+<a name="l00405"></a>00405 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__collide.html#g6533d33f870cf0fb6684ec05e5c0562e" title="Check to see if a geom is enabled.">dGeomIsEnabled</a> (dGeomID geom);
+<a name="l00406"></a>00406 
+<a name="l00407"></a>00407 <span class="comment">/* ************************************************************************ */</span>
+<a name="l00408"></a>00408 <span class="comment">/* geom offset from body */</span>
+<a name="l00409"></a>00409 
+<a name="l00425"></a>00425 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gdc292bc01d5bed32f145ee42760d73b4" title="Set the local offset position of a geom from its body.">dGeomSetOffsetPosition</a> (dGeomID geom, dReal x, dReal y, dReal z);
+<a name="l00426"></a>00426 
+<a name="l00427"></a>00427 
+<a name="l00441"></a>00441 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g805d896b4bc79ceb40e70aadb9629cab" title="Set the local offset rotation matrix of a geom from its body.">dGeomSetOffsetRotation</a> (dGeomID geom, <span class="keyword">const</span> dMatrix3 R);
+<a name="l00442"></a>00442 
+<a name="l00443"></a>00443 
+<a name="l00457"></a>00457 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g9eba87b7598eb6b3a9b6bde1abbeaa1a" title="Set the local offset rotation of a geom from its body.">dGeomSetOffsetQuaternion</a> (dGeomID geom, <span class="keyword">const</span> dQuaternion Q);
+<a name="l00458"></a>00458 
+<a name="l00459"></a>00459 
+<a name="l00476"></a>00476 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g934fe31c543d588991d28cd8571e52ed" title="Set the offset position of a geom from its body.">dGeomSetOffsetWorldPosition</a> (dGeomID geom, dReal x, dReal y, dReal z);
+<a name="l00477"></a>00477 
+<a name="l00478"></a>00478 
+<a name="l00493"></a>00493 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g2c1ef27e7e8ced6eb8488221a1a7c200" title="Set the offset rotation of a geom from its body.">dGeomSetOffsetWorldRotation</a> (dGeomID geom, <span class="keyword">const</span> dMatrix3 R);
+<a name="l00494"></a>00494 
+<a name="l00495"></a>00495 
+<a name="l00510"></a>00510 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#ga04f2117ab18a1d3e27270defdad83a8" title="Set the offset rotation of a geom from its body.">dGeomSetOffsetWorldQuaternion</a> (dGeomID geom, <span class="keyword">const</span> dQuaternion);
+<a name="l00511"></a>00511 
+<a name="l00512"></a>00512 
+<a name="l00526"></a>00526 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gc81929d988b21c4e5338017f2e92a6f2" title="Clear any offset from the geom.">dGeomClearOffset</a>(dGeomID geom);
+<a name="l00527"></a>00527 
+<a name="l00528"></a>00528 
+<a name="l00544"></a>00544 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__collide.html#g46260e0668373aa600b1cf8f83276e10" title="Check to see whether the geom has an offset.">dGeomIsOffset</a>(dGeomID geom);
+<a name="l00545"></a>00545 
+<a name="l00546"></a>00546 
+<a name="l00560"></a>00560 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__collide.html#gb200f73800d253ab3a87f9856d4e18d2" title="Get the offset position vector of a geom.">dGeomGetOffsetPosition</a> (dGeomID geom);
+<a name="l00561"></a>00561 
+<a name="l00562"></a>00562 
+<a name="l00573"></a>00573 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gd4a1e59ecc3c570e3c37c5b8fad71220" title="Copy the offset position vector of a geom.">dGeomCopyOffsetPosition</a> (dGeomID geom, dVector3 pos);
+<a name="l00574"></a>00574 
+<a name="l00575"></a>00575 
+<a name="l00590"></a>00590 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__collide.html#gba28cf4ca8f552c782fc30ce3073dc73" title="Get the offset rotation matrix of a geom.">dGeomGetOffsetRotation</a> (dGeomID geom);
+<a name="l00591"></a>00591 
+<a name="l00592"></a>00592 
+<a name="l00604"></a>00604 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gcf96cd4f9913dc258e6f29da9979388c" title="Copy the offset rotation matrix of a geom.">dGeomCopyOffsetRotation</a> (dGeomID geom, dMatrix3 R);
+<a name="l00605"></a>00605 
+<a name="l00606"></a>00606 
+<a name="l00617"></a>00617 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g8fc20f761daf36976e50d057cf2650ca" title="Get the offset rotation quaternion of a geom.">dGeomGetOffsetQuaternion</a> (dGeomID geom, dQuaternion result);
+<a name="l00618"></a>00618 
+<a name="l00619"></a>00619 
+<a name="l00620"></a>00620 <span class="comment">/* ************************************************************************ */</span>
+<a name="l00621"></a>00621 <span class="comment">/* collision detection */</span>
+<a name="l00622"></a>00622 
+<a name="l00623"></a>00623 <span class="comment">/*</span>
+<a name="l00624"></a>00624 <span class="comment"> * Just generate any contacts (disables any contact refining).</span>
+<a name="l00625"></a>00625 <span class="comment"> */</span>
+<a name="l00626"></a>00626 <span class="preprocessor">#define CONTACTS_UNIMPORTANT        0x80000000</span>
+<a name="l00627"></a>00627 <span class="preprocessor"></span>
+<a name="l00675"></a>00675 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__collide.html#g08508345384abb95e25d674b39157bf8" title="Given two geoms o1 and o2 that potentially intersect, generate contact information...">dCollide</a> (dGeomID o1, dGeomID o2, <span class="keywordtype">int</span> flags, <a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> *contact,
+<a name="l00676"></a>00676          <span class="keywordtype">int</span> skip);
+<a name="l00677"></a>00677 
+<a name="l00705"></a>00705 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gfd185829b6940e2b3238517e1acd2fbb" title="Determines which pairs of geoms in a space may potentially intersect, and calls the...">dSpaceCollide</a> (dSpaceID space, <span class="keywordtype">void</span> *data, <a class="code" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0" title="User callback for geom-geom collision testing.">dNearCallback</a> *callback);
+<a name="l00706"></a>00706 
+<a name="l00707"></a>00707 
+<a name="l00742"></a>00742 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g72a6bb0b550d3e181f8b7a9be7179db5" title="Determines which geoms from one space may potentially intersect with geoms from another...">dSpaceCollide2</a> (dGeomID space1, dGeomID space2, <span class="keywordtype">void</span> *data, <a class="code" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0" title="User callback for geom-geom collision testing.">dNearCallback</a> *callback);
+<a name="l00743"></a>00743 
+<a name="l00744"></a>00744 
+<a name="l00745"></a>00745 <span class="comment">/* ************************************************************************ */</span>
+<a name="l00746"></a>00746 <span class="comment">/* standard classes */</span>
+<a name="l00747"></a>00747 
+<a name="l00748"></a>00748 <span class="comment">/* the maximum number of user classes that are supported */</span>
+<a name="l00749"></a>00749 <span class="keyword">enum</span> {
+<a name="l00750"></a>00750   dMaxUserClasses = 4
+<a name="l00751"></a>00751 };
+<a name="l00752"></a>00752 
+<a name="l00753"></a>00753 <span class="comment">/* class numbers - each geometry object needs a unique number */</span>
+<a name="l00754"></a>00754 <span class="keyword">enum</span> {
+<a name="l00755"></a>00755   dSphereClass = 0,
+<a name="l00756"></a>00756   dBoxClass,
+<a name="l00757"></a>00757   dCapsuleClass,
+<a name="l00758"></a>00758   dCylinderClass,
+<a name="l00759"></a>00759   dPlaneClass,
+<a name="l00760"></a>00760   dRayClass,
+<a name="l00761"></a>00761   dConvexClass,
+<a name="l00762"></a>00762   dGeomTransformClass,
+<a name="l00763"></a>00763   dTriMeshClass,
+<a name="l00764"></a>00764   dHeightfieldClass,
+<a name="l00765"></a>00765 
+<a name="l00766"></a>00766   dFirstSpaceClass,
+<a name="l00767"></a>00767   dSimpleSpaceClass = dFirstSpaceClass,
+<a name="l00768"></a>00768   dHashSpaceClass,
+<a name="l00769"></a>00769   dQuadTreeSpaceClass,
+<a name="l00770"></a>00770   dLastSpaceClass = dQuadTreeSpaceClass,
+<a name="l00771"></a>00771 
+<a name="l00772"></a>00772   dFirstUserClass,
+<a name="l00773"></a>00773   dLastUserClass = dFirstUserClass + dMaxUserClasses - 1,
+<a name="l00774"></a>00774   dGeomNumClasses
+<a name="l00775"></a>00775 };
+<a name="l00776"></a>00776 
+<a name="l00777"></a>00777 
+<a name="l00797"></a>00797 ODE_API dGeomID <a class="code" href="group__collide__sphere.html#g53c79c860638ca3600744a193da68474" title="Create a sphere geom of the given radius, and return its ID.">dCreateSphere</a> (dSpaceID space, dReal radius);
+<a name="l00798"></a>00798 
+<a name="l00799"></a>00799 
+<a name="l00809"></a>00809 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide__sphere.html#g2341ae9b3b733571eff7a1857109f394" title="Set the radius of a sphere geom.">dGeomSphereSetRadius</a> (dGeomID sphere, dReal radius);
+<a name="l00810"></a>00810 
+<a name="l00811"></a>00811 
+<a name="l00820"></a>00820 ODE_API dReal <a class="code" href="group__collide__sphere.html#g0e7f664deb9f557a6a24f93705b29fa9" title="Retrieves the radius of a sphere geom.">dGeomSphereGetRadius</a> (dGeomID sphere);
+<a name="l00821"></a>00821 
+<a name="l00822"></a>00822 
+<a name="l00837"></a>00837 ODE_API dReal <a class="code" href="group__collide__sphere.html#gee86d3744471e447ffc85f85ee6578b1" title="Calculate the depth of the a given point within a sphere.">dGeomSpherePointDepth</a> (dGeomID sphere, dReal x, dReal y, dReal z);
+<a name="l00838"></a>00838 
+<a name="l00839"></a>00839 
+<a name="l00840"></a>00840 <span class="comment">//--&gt; Convex Functions</span>
+<a name="l00841"></a>00841 ODE_API dGeomID dCreateConvex (dSpaceID space,
+<a name="l00842"></a>00842                 dReal *_planes,
+<a name="l00843"></a>00843                 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _planecount,
+<a name="l00844"></a>00844                 dReal *_points,
+<a name="l00845"></a>00845                 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _pointcount,<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> *_polygons);
+<a name="l00846"></a>00846 
+<a name="l00847"></a>00847 ODE_API <span class="keywordtype">void</span> dGeomSetConvex (dGeomID g,
+<a name="l00848"></a>00848               dReal *_planes,
+<a name="l00849"></a>00849               <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _count,
+<a name="l00850"></a>00850               dReal *_points,
+<a name="l00851"></a>00851               <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _pointcount,<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> *_polygons);
+<a name="l00852"></a>00852 <span class="comment">//&lt;-- Convex Functions</span>
+<a name="l00853"></a>00853 
+<a name="l00875"></a>00875 ODE_API dGeomID <a class="code" href="group__collide__box.html#g3e3b0b249a8ccd40a9969e3a26548397" title="Create a box geom with the provided side lengths.">dCreateBox</a> (dSpaceID space, dReal lx, dReal ly, dReal lz);
+<a name="l00876"></a>00876 
+<a name="l00877"></a>00877 
+<a name="l00889"></a>00889 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide__box.html#g4c7060780be9eaf74228565910168273" title="Set the side lengths of the given box.">dGeomBoxSetLengths</a> (dGeomID box, dReal lx, dReal ly, dReal lz);
+<a name="l00890"></a>00890 
+<a name="l00891"></a>00891 
+<a name="l00901"></a>00901 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide__box.html#ge24d9264235d2487b2e2d52b2c62c879" title="Get the side lengths of a box.">dGeomBoxGetLengths</a> (dGeomID box, dVector3 result);
+<a name="l00902"></a>00902 
+<a name="l00903"></a>00903 
+<a name="l00916"></a>00916 ODE_API dReal dGeomBoxPointDepth (dGeomID box, dReal x, dReal y, dReal z);
+<a name="l00917"></a>00917 
+<a name="l00918"></a>00918 
+<a name="l00919"></a>00919 ODE_API dGeomID dCreatePlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d);
+<a name="l00920"></a>00920 ODE_API <span class="keywordtype">void</span> dGeomPlaneSetParams (dGeomID plane, dReal a, dReal b, dReal c, dReal d);
+<a name="l00921"></a>00921 ODE_API <span class="keywordtype">void</span> dGeomPlaneGetParams (dGeomID plane, dVector4 result);
+<a name="l00922"></a>00922 ODE_API dReal dGeomPlanePointDepth (dGeomID plane, dReal x, dReal y, dReal z);
+<a name="l00923"></a>00923 
+<a name="l00924"></a>00924 ODE_API dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length);
+<a name="l00925"></a>00925 ODE_API <span class="keywordtype">void</span> dGeomCapsuleSetParams (dGeomID ccylinder, dReal radius, dReal length);
+<a name="l00926"></a>00926 ODE_API <span class="keywordtype">void</span> dGeomCapsuleGetParams (dGeomID ccylinder, dReal *radius, dReal *length);
+<a name="l00927"></a>00927 ODE_API dReal dGeomCapsulePointDepth (dGeomID ccylinder, dReal x, dReal y, dReal z);
+<a name="l00928"></a>00928 
+<a name="l00929"></a>00929 <span class="comment">// For now we want to have a backwards compatible C-API, note: C++ API is not.</span>
+<a name="l00930"></a>00930 <span class="preprocessor">#define dCreateCCylinder dCreateCapsule</span>
+<a name="l00931"></a>00931 <span class="preprocessor"></span><span class="preprocessor">#define dGeomCCylinderSetParams dGeomCapsuleSetParams</span>
+<a name="l00932"></a>00932 <span class="preprocessor"></span><span class="preprocessor">#define dGeomCCylinderGetParams dGeomCapsuleGetParams</span>
+<a name="l00933"></a>00933 <span class="preprocessor"></span><span class="preprocessor">#define dGeomCCylinderPointDepth dGeomCapsulePointDepth</span>
+<a name="l00934"></a>00934 <span class="preprocessor"></span><span class="preprocessor">#define dCCylinderClass dCapsuleClass</span>
+<a name="l00935"></a>00935 <span class="preprocessor"></span>
+<a name="l00936"></a>00936 ODE_API dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length);
+<a name="l00937"></a>00937 ODE_API <span class="keywordtype">void</span> dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length);
+<a name="l00938"></a>00938 ODE_API <span class="keywordtype">void</span> dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length);
+<a name="l00939"></a>00939 
+<a name="l00940"></a>00940 ODE_API dGeomID dCreateRay (dSpaceID space, dReal length);
+<a name="l00941"></a>00941 ODE_API <span class="keywordtype">void</span> dGeomRaySetLength (dGeomID ray, dReal length);
+<a name="l00942"></a>00942 ODE_API dReal dGeomRayGetLength (dGeomID ray);
+<a name="l00943"></a>00943 ODE_API <span class="keywordtype">void</span> dGeomRaySet (dGeomID ray, dReal px, dReal py, dReal pz,
+<a name="l00944"></a>00944         dReal dx, dReal dy, dReal dz);
+<a name="l00945"></a>00945 ODE_API <span class="keywordtype">void</span> dGeomRayGet (dGeomID ray, dVector3 start, dVector3 dir);
+<a name="l00946"></a>00946 
+<a name="l00947"></a>00947 <span class="comment">/*</span>
+<a name="l00948"></a>00948 <span class="comment"> * Set/get ray flags that influence ray collision detection.</span>
+<a name="l00949"></a>00949 <span class="comment"> * These flags are currently only noticed by the trimesh collider, because</span>
+<a name="l00950"></a>00950 <span class="comment"> * they can make a major differences there.</span>
+<a name="l00951"></a>00951 <span class="comment"> */</span>
+<a name="l00952"></a>00952 ODE_API <span class="keywordtype">void</span> dGeomRaySetParams (dGeomID g, <span class="keywordtype">int</span> FirstContact, <span class="keywordtype">int</span> BackfaceCull);
+<a name="l00953"></a>00953 ODE_API <span class="keywordtype">void</span> dGeomRayGetParams (dGeomID g, <span class="keywordtype">int</span> *FirstContact, <span class="keywordtype">int</span> *BackfaceCull);
+<a name="l00954"></a>00954 ODE_API <span class="keywordtype">void</span> dGeomRaySetClosestHit (dGeomID g, <span class="keywordtype">int</span> closestHit);
+<a name="l00955"></a>00955 ODE_API <span class="keywordtype">int</span> dGeomRayGetClosestHit (dGeomID g);
+<a name="l00956"></a>00956 
+<a name="l00957"></a>00957 <span class="preprocessor">#include "collision_trimesh.h"</span>
+<a name="l00958"></a>00958 
+<a name="l00959"></a>00959 ODE_API dGeomID dCreateGeomTransform (dSpaceID space);
+<a name="l00960"></a>00960 ODE_API <span class="keywordtype">void</span> dGeomTransformSetGeom (dGeomID g, dGeomID obj);
+<a name="l00961"></a>00961 ODE_API dGeomID dGeomTransformGetGeom (dGeomID g);
+<a name="l00962"></a>00962 ODE_API <span class="keywordtype">void</span> dGeomTransformSetCleanup (dGeomID g, <span class="keywordtype">int</span> mode);
+<a name="l00963"></a>00963 ODE_API <span class="keywordtype">int</span> dGeomTransformGetCleanup (dGeomID g);
+<a name="l00964"></a>00964 ODE_API <span class="keywordtype">void</span> dGeomTransformSetInfo (dGeomID g, <span class="keywordtype">int</span> mode);
+<a name="l00965"></a>00965 ODE_API <span class="keywordtype">int</span> dGeomTransformGetInfo (dGeomID g);
+<a name="l00966"></a>00966 
+<a name="l00967"></a>00967 
+<a name="l00968"></a>00968 <span class="comment">/* ************************************************************************ */</span>
+<a name="l00969"></a>00969 <span class="comment">/* heightfield functions */</span>
+<a name="l00970"></a>00970 
+<a name="l00971"></a>00971 
+<a name="l00972"></a>00972 <span class="comment">// Data storage for heightfield data.</span>
+<a name="l00973"></a>00973 <span class="keyword">struct </span>dxHeightfieldData;
+<a name="l00974"></a>00974 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxHeightfieldData* dHeightfieldDataID;
+<a name="l00975"></a>00975 
+<a name="l00976"></a>00976 
+<a name="l00994"></a><a class="code" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9">00994</a> <span class="keyword">typedef</span> dReal <a class="code" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9" title="Callback prototype.">dHeightfieldGetHeight</a>( <span class="keywordtype">void</span>* p_user_data, <span class="keywordtype">int</span> x, <span class="keywordtype">int</span> z );
+<a name="l00995"></a>00995 
+<a name="l00996"></a>00996 
+<a name="l00997"></a>00997 
+<a name="l01017"></a>01017 ODE_API dGeomID <a class="code" href="group__collide.html#gd50d5cd5fea5bfc12584e60d4a936cfb" title="Creates a heightfield geom.">dCreateHeightfield</a>( dSpaceID space,
+<a name="l01018"></a>01018                dHeightfieldDataID data, <span class="keywordtype">int</span> bPlaceable );
+<a name="l01019"></a>01019 
+<a name="l01020"></a>01020 
+<a name="l01033"></a>01033 ODE_API dHeightfieldDataID <a class="code" href="group__collide.html#g7de82d5cf9aa10bb3144d51f4360eea1" title="Creates a new empty dHeightfieldDataID.">dGeomHeightfieldDataCreate</a>();
+<a name="l01034"></a>01034 
+<a name="l01035"></a>01035 
+<a name="l01044"></a>01044 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gf98fc1f3d1784df5a5dff114b483d408" title="Destroys a dHeightfieldDataID.">dGeomHeightfieldDataDestroy</a>( dHeightfieldDataID d );
+<a name="l01045"></a>01045 
+<a name="l01046"></a>01046 
+<a name="l01047"></a>01047 
+<a name="l01088"></a>01088 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g34566000a5a2673cc013294f0ed85926" title="Configures a dHeightfieldDataID to use a callback to retrieve height data.">dGeomHeightfieldDataBuildCallback</a>( dHeightfieldDataID d,
+<a name="l01089"></a>01089             <span class="keywordtype">void</span>* pUserData, <a class="code" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9" title="Callback prototype.">dHeightfieldGetHeight</a>* pCallback,
+<a name="l01090"></a>01090             dReal width, dReal depth, <span class="keywordtype">int</span> widthSamples, <span class="keywordtype">int</span> depthSamples,
+<a name="l01091"></a>01091             dReal scale, dReal offset, dReal thickness, <span class="keywordtype">int</span> bWrap );
+<a name="l01092"></a>01092 
+<a name="l01136"></a>01136 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g2c15b7c1a36c7526b66911beab1b7934" title="Configures a dHeightfieldDataID to use height data in byte format.">dGeomHeightfieldDataBuildByte</a>( dHeightfieldDataID d,
+<a name="l01137"></a>01137             <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span>* pHeightData, <span class="keywordtype">int</span> bCopyHeightData,
+<a name="l01138"></a>01138             dReal width, dReal depth, <span class="keywordtype">int</span> widthSamples, <span class="keywordtype">int</span> depthSamples,
+<a name="l01139"></a>01139             dReal scale, dReal offset, dReal thickness,  <span class="keywordtype">int</span> bWrap );
+<a name="l01140"></a>01140 
+<a name="l01184"></a>01184 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g2f7582d64cc8219141bc10efeca86d17" title="Configures a dHeightfieldDataID to use height data in short format.">dGeomHeightfieldDataBuildShort</a>( dHeightfieldDataID d,
+<a name="l01185"></a>01185             <span class="keyword">const</span> <span class="keywordtype">short</span>* pHeightData, <span class="keywordtype">int</span> bCopyHeightData,
+<a name="l01186"></a>01186             dReal width, dReal depth, <span class="keywordtype">int</span> widthSamples, <span class="keywordtype">int</span> depthSamples,
+<a name="l01187"></a>01187             dReal scale, dReal offset, dReal thickness, <span class="keywordtype">int</span> bWrap );
+<a name="l01188"></a>01188 
+<a name="l01234"></a>01234 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g8da529419317e7bd4e01dabbe94daa09" title="Configures a dHeightfieldDataID to use height data in single precision floating point...">dGeomHeightfieldDataBuildSingle</a>( dHeightfieldDataID d,
+<a name="l01235"></a>01235             <span class="keyword">const</span> <span class="keywordtype">float</span>* pHeightData, <span class="keywordtype">int</span> bCopyHeightData,
+<a name="l01236"></a>01236             dReal width, dReal depth, <span class="keywordtype">int</span> widthSamples, <span class="keywordtype">int</span> depthSamples,
+<a name="l01237"></a>01237             dReal scale, dReal offset, dReal thickness, <span class="keywordtype">int</span> bWrap );
+<a name="l01238"></a>01238 
+<a name="l01284"></a>01284 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g98ec0c952b3b4e0fb3cd8cf66e267c86" title="Configures a dHeightfieldDataID to use height data in double precision floating point...">dGeomHeightfieldDataBuildDouble</a>( dHeightfieldDataID d,
+<a name="l01285"></a>01285             <span class="keyword">const</span> <span class="keywordtype">double</span>* pHeightData, <span class="keywordtype">int</span> bCopyHeightData,
+<a name="l01286"></a>01286             dReal width, dReal depth, <span class="keywordtype">int</span> widthSamples, <span class="keywordtype">int</span> depthSamples,
+<a name="l01287"></a>01287             dReal scale, dReal offset, dReal thickness, <span class="keywordtype">int</span> bWrap );
+<a name="l01288"></a>01288 
+<a name="l01306"></a>01306 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#gcdef420e65e3751388b315f5de2804b2" title="Manually set the minimum and maximum height bounds.">dGeomHeightfieldDataSetBounds</a>( dHeightfieldDataID d,
+<a name="l01307"></a>01307             dReal minHeight, dReal maxHeight );
+<a name="l01308"></a>01308 
+<a name="l01309"></a>01309 
+<a name="l01320"></a>01320 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g6c1ae1f3ca652d6410e7804cdf8f8491" title="Assigns a dHeightfieldDataID to a heightfield geom.">dGeomHeightfieldSetHeightfieldData</a>( dGeomID g, dHeightfieldDataID d );
+<a name="l01321"></a>01321 
+<a name="l01322"></a>01322 
+<a name="l01332"></a>01332 ODE_API dHeightfieldDataID <a class="code" href="group__collide.html#g747176d26ce4f9b10ebfa6c865ef1cca" title="Gets the dHeightfieldDataID bound to a heightfield geom.">dGeomHeightfieldGetHeightfieldData</a>( dGeomID g );
+<a name="l01333"></a>01333 
+<a name="l01334"></a>01334 
+<a name="l01335"></a>01335 
+<a name="l01336"></a>01336 <span class="comment">/* ************************************************************************ */</span>
+<a name="l01337"></a>01337 <span class="comment">/* utility functions */</span>
+<a name="l01338"></a>01338 
+<a name="l01339"></a>01339 ODE_API <span class="keywordtype">void</span> dClosestLineSegmentPoints (<span class="keyword">const</span> dVector3 a1, <span class="keyword">const</span> dVector3 a2,
+<a name="l01340"></a>01340             <span class="keyword">const</span> dVector3 b1, <span class="keyword">const</span> dVector3 b2,
+<a name="l01341"></a>01341             dVector3 cp1, dVector3 cp2);
+<a name="l01342"></a>01342 
+<a name="l01343"></a>01343 ODE_API <span class="keywordtype">int</span> dBoxTouchesBox (<span class="keyword">const</span> dVector3 _p1, <span class="keyword">const</span> dMatrix3 R1,
+<a name="l01344"></a>01344           <span class="keyword">const</span> dVector3 side1, <span class="keyword">const</span> dVector3 _p2,
+<a name="l01345"></a>01345           <span class="keyword">const</span> dMatrix3 R2, <span class="keyword">const</span> dVector3 side2);
+<a name="l01346"></a>01346 
+<a name="l01347"></a>01347 <span class="comment">// The meaning of flags parameter is the same as in dCollide()</span>
+<a name="l01348"></a>01348 ODE_API <span class="keywordtype">int</span> dBoxBox (<span class="keyword">const</span> dVector3 p1, <span class="keyword">const</span> dMatrix3 R1,
+<a name="l01349"></a>01349         <span class="keyword">const</span> dVector3 side1, <span class="keyword">const</span> dVector3 p2,
+<a name="l01350"></a>01350         <span class="keyword">const</span> dMatrix3 R2, <span class="keyword">const</span> dVector3 side2,
+<a name="l01351"></a>01351         dVector3 normal, dReal *depth, <span class="keywordtype">int</span> *return_code,
+<a name="l01352"></a>01352         <span class="keywordtype">int</span> flags, <a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> *contact, <span class="keywordtype">int</span> skip);
+<a name="l01353"></a>01353 
+<a name="l01354"></a>01354 ODE_API <span class="keywordtype">void</span> dInfiniteAABB (dGeomID geom, dReal aabb[6]);
+<a name="l01355"></a>01355 ODE_API <span class="keywordtype">void</span> dInitODE(<span class="keywordtype">void</span>);
+<a name="l01356"></a>01356 ODE_API <span class="keywordtype">void</span> dCloseODE(<span class="keywordtype">void</span>);
+<a name="l01357"></a>01357 
+<a name="l01358"></a>01358 <span class="comment">/* ************************************************************************ */</span>
+<a name="l01359"></a>01359 <span class="comment">/* custom classes */</span>
+<a name="l01360"></a>01360 
+<a name="l01361"></a>01361 <span class="keyword">typedef</span> <span class="keywordtype">void</span> dGetAABBFn (dGeomID, dReal aabb[6]);
+<a name="l01362"></a>01362 <span class="keyword">typedef</span> <span class="keywordtype">int</span> dColliderFn (dGeomID o1, dGeomID o2,
+<a name="l01363"></a>01363           <span class="keywordtype">int</span> flags, <a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> *contact, <span class="keywordtype">int</span> skip);
+<a name="l01364"></a>01364 <span class="keyword">typedef</span> dColliderFn * dGetColliderFnFn (<span class="keywordtype">int</span> num);
+<a name="l01365"></a>01365 <span class="keyword">typedef</span> <span class="keywordtype">void</span> dGeomDtorFn (dGeomID o);
+<a name="l01366"></a>01366 <span class="keyword">typedef</span> <span class="keywordtype">int</span> dAABBTestFn (dGeomID o1, dGeomID o2, dReal aabb[6]);
+<a name="l01367"></a>01367 
+<a name="l01368"></a>01368 <span class="keyword">typedef</span> <span class="keyword">struct </span>dGeomClass {
+<a name="l01369"></a>01369   <span class="keywordtype">int</span> bytes;
+<a name="l01370"></a>01370   dGetColliderFnFn *collider;
+<a name="l01371"></a>01371   dGetAABBFn *aabb;
+<a name="l01372"></a>01372   dAABBTestFn *aabb_test;
+<a name="l01373"></a>01373   dGeomDtorFn *dtor;
+<a name="l01374"></a>01374 } dGeomClass;
+<a name="l01375"></a>01375 
+<a name="l01376"></a>01376 ODE_API <span class="keywordtype">int</span> dCreateGeomClass (<span class="keyword">const</span> dGeomClass *classptr);
+<a name="l01377"></a>01377 ODE_API <span class="keywordtype">void</span> * dGeomGetClassData (dGeomID);
+<a name="l01378"></a>01378 ODE_API dGeomID dCreateGeom (<span class="keywordtype">int</span> classnum);
+<a name="l01379"></a>01379 
+<a name="l01380"></a>01380 <span class="comment">/* ************************************************************************ */</span>
+<a name="l01381"></a>01381 
+<a name="l01382"></a>01382 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l01383"></a>01383 <span class="preprocessor"></span>}
+<a name="l01384"></a>01384 <span class="preprocessor">#endif</span>
+<a name="l01385"></a>01385 <span class="preprocessor"></span>
+<a name="l01386"></a>01386 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/collision__space_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/collision__space_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/collision__space_8h-source.html	(revision 216)
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: collision_space.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>collision_space.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_COLLISION_SPACE_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_COLLISION_SPACE_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00030"></a>00030 <span class="preprocessor">#endif</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span>
+<a name="l00032"></a>00032 <span class="keyword">struct </span><a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a>;
+<a name="l00033"></a>00033 
+<a name="l00049"></a><a class="code" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">00049</a> <span class="keyword">typedef</span> <span class="keywordtype">void</span> <a class="code" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0" title="User callback for geom-geom collision testing.">dNearCallback</a> (<span class="keywordtype">void</span> *data, dGeomID o1, dGeomID o2);
+<a name="l00050"></a>00050 
+<a name="l00051"></a>00051 
+<a name="l00052"></a>00052 ODE_API dSpaceID dSimpleSpaceCreate (dSpaceID space);
+<a name="l00053"></a>00053 ODE_API dSpaceID dHashSpaceCreate (dSpaceID space);
+<a name="l00054"></a>00054 ODE_API dSpaceID dQuadTreeSpaceCreate (dSpaceID space, dVector3 Center, dVector3 Extents, <span class="keywordtype">int</span> Depth);
+<a name="l00055"></a>00055 
+<a name="l00056"></a>00056 ODE_API <span class="keywordtype">void</span> dSpaceDestroy (dSpaceID);
+<a name="l00057"></a>00057 
+<a name="l00058"></a>00058 ODE_API <span class="keywordtype">void</span> dHashSpaceSetLevels (dSpaceID space, <span class="keywordtype">int</span> minlevel, <span class="keywordtype">int</span> maxlevel);
+<a name="l00059"></a>00059 ODE_API <span class="keywordtype">void</span> dHashSpaceGetLevels (dSpaceID space, <span class="keywordtype">int</span> *minlevel, <span class="keywordtype">int</span> *maxlevel);
+<a name="l00060"></a>00060 
+<a name="l00061"></a>00061 ODE_API <span class="keywordtype">void</span> dSpaceSetCleanup (dSpaceID space, <span class="keywordtype">int</span> mode);
+<a name="l00062"></a>00062 ODE_API <span class="keywordtype">int</span> dSpaceGetCleanup (dSpaceID space);
+<a name="l00063"></a>00063 
+<a name="l00064"></a>00064 ODE_API <span class="keywordtype">void</span> dSpaceAdd (dSpaceID, dGeomID);
+<a name="l00065"></a>00065 ODE_API <span class="keywordtype">void</span> dSpaceRemove (dSpaceID, dGeomID);
+<a name="l00066"></a>00066 ODE_API <span class="keywordtype">int</span> dSpaceQuery (dSpaceID, dGeomID);
+<a name="l00067"></a>00067 ODE_API <span class="keywordtype">void</span> dSpaceClean (dSpaceID);
+<a name="l00068"></a>00068 ODE_API <span class="keywordtype">int</span> dSpaceGetNumGeoms (dSpaceID);
+<a name="l00069"></a>00069 ODE_API dGeomID dSpaceGetGeom (dSpaceID, <span class="keywordtype">int</span> i);
+<a name="l00070"></a>00070 
+<a name="l00071"></a>00071 
+<a name="l00072"></a>00072 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00073"></a>00073 <span class="preprocessor"></span>}
+<a name="l00074"></a>00074 <span class="preprocessor">#endif</span>
+<a name="l00075"></a>00075 <span class="preprocessor"></span>
+<a name="l00076"></a>00076 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/collision__trimesh_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/collision__trimesh_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/collision__trimesh_8h-source.html	(revision 216)
@@ -0,0 +1,220 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: collision_trimesh.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>collision_trimesh.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/*</span>
+<a name="l00024"></a>00024 <span class="comment"> * TriMesh code by Erwin de Vries.</span>
+<a name="l00025"></a>00025 <span class="comment"> *</span>
+<a name="l00026"></a>00026 <span class="comment"> * Trimesh data.</span>
+<a name="l00027"></a>00027 <span class="comment"> * This is where the actual vertexdata (pointers), and BV tree is stored.</span>
+<a name="l00028"></a>00028 <span class="comment"> * Vertices should be single precision!</span>
+<a name="l00029"></a>00029 <span class="comment"> * This should be more sophisticated, so that the user can easyly implement</span>
+<a name="l00030"></a>00030 <span class="comment"> * another collision library, but this is a lot of work, and also costs some</span>
+<a name="l00031"></a>00031 <span class="comment"> * performance because some data has to be copied.</span>
+<a name="l00032"></a>00032 <span class="comment"> */</span>
+<a name="l00033"></a>00033 
+<a name="l00034"></a>00034 <span class="preprocessor">#ifndef _ODE_COLLISION_TRIMESH_H_</span>
+<a name="l00035"></a>00035 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_COLLISION_TRIMESH_H_</span>
+<a name="l00036"></a>00036 <span class="preprocessor"></span>
+<a name="l00037"></a>00037 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00038"></a>00038 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00039"></a>00039 <span class="preprocessor">#endif</span>
+<a name="l00040"></a>00040 <span class="preprocessor"></span>
+<a name="l00041"></a>00041 <span class="comment">/*</span>
+<a name="l00042"></a>00042 <span class="comment"> * Data storage for triangle meshes.</span>
+<a name="l00043"></a>00043 <span class="comment"> */</span>
+<a name="l00044"></a>00044 <span class="keyword">struct </span>dxTriMeshData;
+<a name="l00045"></a>00045 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxTriMeshData* dTriMeshDataID;
+<a name="l00046"></a>00046 
+<a name="l00047"></a>00047 <span class="comment">/*</span>
+<a name="l00048"></a>00048 <span class="comment"> * These dont make much sense now, but they will later when we add more</span>
+<a name="l00049"></a>00049 <span class="comment"> * features.</span>
+<a name="l00050"></a>00050 <span class="comment"> */</span>
+<a name="l00051"></a>00051 ODE_API dTriMeshDataID dGeomTriMeshDataCreate(<span class="keywordtype">void</span>);
+<a name="l00052"></a>00052 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataDestroy(dTriMeshDataID g);
+<a name="l00053"></a>00053 
+<a name="l00054"></a>00054 
+<a name="l00055"></a>00055 
+<a name="l00056"></a>00056 <span class="keyword">enum</span> { TRIMESH_FACE_NORMALS };
+<a name="l00057"></a>00057 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataSet(dTriMeshDataID g, <span class="keywordtype">int</span> data_id, <span class="keywordtype">void</span>* in_data);
+<a name="l00058"></a>00058 ODE_API <span class="keywordtype">void</span>* dGeomTriMeshDataGet(dTriMeshDataID g, <span class="keywordtype">int</span> data_id);
+<a name="l00059"></a>00059 
+<a name="l00060"></a>00060 
+<a name="l00061"></a>00061 
+<a name="l00067"></a>00067 ODE_API <span class="keywordtype">void</span> dGeomTriMeshSetLastTransform( dGeomID g, dMatrix4 last_trans );
+<a name="l00068"></a>00068 ODE_API dReal* dGeomTriMeshGetLastTransform( dGeomID g );
+<a name="l00069"></a>00069 
+<a name="l00070"></a>00070 <span class="comment">/*</span>
+<a name="l00071"></a>00071 <span class="comment"> * Build TriMesh data with single precision used in vertex data .</span>
+<a name="l00072"></a>00072 <span class="comment"> */</span>
+<a name="l00073"></a>00073 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataBuildSingle(dTriMeshDataID g,
+<a name="l00074"></a>00074                                  <span class="keyword">const</span> <span class="keywordtype">void</span>* Vertices, <span class="keywordtype">int</span> VertexStride, <span class="keywordtype">int</span> VertexCount, 
+<a name="l00075"></a>00075                                  <span class="keyword">const</span> <span class="keywordtype">void</span>* Indices, <span class="keywordtype">int</span> IndexCount, <span class="keywordtype">int</span> TriStride);
+<a name="l00076"></a>00076 <span class="comment">/* same again with a normals array (used as trimesh-trimesh optimization) */</span>
+<a name="l00077"></a>00077 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataBuildSingle1(dTriMeshDataID g,
+<a name="l00078"></a>00078                                   <span class="keyword">const</span> <span class="keywordtype">void</span>* Vertices, <span class="keywordtype">int</span> VertexStride, <span class="keywordtype">int</span> VertexCount, 
+<a name="l00079"></a>00079                                   <span class="keyword">const</span> <span class="keywordtype">void</span>* Indices, <span class="keywordtype">int</span> IndexCount, <span class="keywordtype">int</span> TriStride,
+<a name="l00080"></a>00080                                   <span class="keyword">const</span> <span class="keywordtype">void</span>* Normals);
+<a name="l00081"></a>00081 <span class="comment">/*</span>
+<a name="l00082"></a>00082 <span class="comment">* Build TriMesh data with double pricision used in vertex data .</span>
+<a name="l00083"></a>00083 <span class="comment">*/</span>
+<a name="l00084"></a>00084 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataBuildDouble(dTriMeshDataID g, 
+<a name="l00085"></a>00085                                  <span class="keyword">const</span> <span class="keywordtype">void</span>* Vertices,  <span class="keywordtype">int</span> VertexStride, <span class="keywordtype">int</span> VertexCount, 
+<a name="l00086"></a>00086                                  <span class="keyword">const</span> <span class="keywordtype">void</span>* Indices, <span class="keywordtype">int</span> IndexCount, <span class="keywordtype">int</span> TriStride);
+<a name="l00087"></a>00087 <span class="comment">/* same again with a normals array (used as trimesh-trimesh optimization) */</span>
+<a name="l00088"></a>00088 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataBuildDouble1(dTriMeshDataID g, 
+<a name="l00089"></a>00089                                   <span class="keyword">const</span> <span class="keywordtype">void</span>* Vertices,  <span class="keywordtype">int</span> VertexStride, <span class="keywordtype">int</span> VertexCount, 
+<a name="l00090"></a>00090                                   <span class="keyword">const</span> <span class="keywordtype">void</span>* Indices, <span class="keywordtype">int</span> IndexCount, <span class="keywordtype">int</span> TriStride,
+<a name="l00091"></a>00091                                   <span class="keyword">const</span> <span class="keywordtype">void</span>* Normals);
+<a name="l00092"></a>00092 
+<a name="l00093"></a>00093 <span class="comment">/*</span>
+<a name="l00094"></a>00094 <span class="comment"> * Simple build. Single/double precision based on dSINGLE/dDOUBLE!</span>
+<a name="l00095"></a>00095 <span class="comment"> */</span>
+<a name="l00096"></a>00096 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
+<a name="l00097"></a>00097                                  <span class="keyword">const</span> dReal* Vertices, <span class="keywordtype">int</span> VertexCount,
+<a name="l00098"></a>00098                                  <span class="keyword">const</span> <span class="keywordtype">int</span>* Indices, <span class="keywordtype">int</span> IndexCount);
+<a name="l00099"></a>00099 <span class="comment">/* same again with a normals array (used as trimesh-trimesh optimization) */</span>
+<a name="l00100"></a>00100 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataBuildSimple1(dTriMeshDataID g,
+<a name="l00101"></a>00101                                   <span class="keyword">const</span> dReal* Vertices, <span class="keywordtype">int</span> VertexCount,
+<a name="l00102"></a>00102                                   <span class="keyword">const</span> <span class="keywordtype">int</span>* Indices, <span class="keywordtype">int</span> IndexCount,
+<a name="l00103"></a>00103                                   <span class="keyword">const</span> <span class="keywordtype">int</span>* Normals);
+<a name="l00104"></a>00104 
+<a name="l00105"></a>00105 <span class="comment">/* Preprocess the trimesh data to remove mark unnecessary edges and vertices */</span>
+<a name="l00106"></a>00106 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataPreprocess(dTriMeshDataID g);
+<a name="l00107"></a>00107 <span class="comment">/* Get and set the internal preprocessed trimesh data buffer, for loading and saving */</span>
+<a name="l00108"></a>00108 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataGetBuffer(dTriMeshDataID g, <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span>** buf, <span class="keywordtype">int</span>* bufLen);
+<a name="l00109"></a>00109 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataSetBuffer(dTriMeshDataID g, <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span>* buf);
+<a name="l00110"></a>00110 
+<a name="l00111"></a>00111 
+<a name="l00112"></a>00112 <span class="comment">/*</span>
+<a name="l00113"></a>00113 <span class="comment"> * Per triangle callback. Allows the user to say if he wants a collision with</span>
+<a name="l00114"></a>00114 <span class="comment"> * a particular triangle.</span>
+<a name="l00115"></a>00115 <span class="comment"> */</span>
+<a name="l00116"></a>00116 <span class="keyword">typedef</span> <span class="keywordtype">int</span> dTriCallback(dGeomID TriMesh, dGeomID RefObject, <span class="keywordtype">int</span> TriangleIndex);
+<a name="l00117"></a>00117 ODE_API <span class="keywordtype">void</span> dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback);
+<a name="l00118"></a>00118 ODE_API dTriCallback* dGeomTriMeshGetCallback(dGeomID g);
+<a name="l00119"></a>00119 
+<a name="l00120"></a>00120 <span class="comment">/*</span>
+<a name="l00121"></a>00121 <span class="comment"> * Per object callback. Allows the user to get the list of triangles in 1</span>
+<a name="l00122"></a>00122 <span class="comment"> * shot. Maybe we should remove this one.</span>
+<a name="l00123"></a>00123 <span class="comment"> */</span>
+<a name="l00124"></a>00124 <span class="keyword">typedef</span> <span class="keywordtype">void</span> dTriArrayCallback(dGeomID TriMesh, dGeomID RefObject, <span class="keyword">const</span> <span class="keywordtype">int</span>* TriIndices, <span class="keywordtype">int</span> TriCount);
+<a name="l00125"></a>00125 ODE_API <span class="keywordtype">void</span> dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback);
+<a name="l00126"></a>00126 ODE_API dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g);
+<a name="l00127"></a>00127 
+<a name="l00128"></a>00128 <span class="comment">/*</span>
+<a name="l00129"></a>00129 <span class="comment"> * Ray callback.</span>
+<a name="l00130"></a>00130 <span class="comment"> * Allows the user to say if a ray collides with a triangle on barycentric</span>
+<a name="l00131"></a>00131 <span class="comment"> * coords. The user can for example sample a texture with alpha transparency</span>
+<a name="l00132"></a>00132 <span class="comment"> * to determine if a collision should occur.</span>
+<a name="l00133"></a>00133 <span class="comment"> */</span>
+<a name="l00134"></a>00134 <span class="keyword">typedef</span> <span class="keywordtype">int</span> dTriRayCallback(dGeomID TriMesh, dGeomID Ray, <span class="keywordtype">int</span> TriangleIndex, dReal u, dReal v);
+<a name="l00135"></a>00135 ODE_API <span class="keywordtype">void</span> dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback);
+<a name="l00136"></a>00136 ODE_API dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g);
+<a name="l00137"></a>00137 
+<a name="l00138"></a>00138 <span class="comment">/*</span>
+<a name="l00139"></a>00139 <span class="comment"> * Trimesh class</span>
+<a name="l00140"></a>00140 <span class="comment"> * Construction. Callbacks are optional.</span>
+<a name="l00141"></a>00141 <span class="comment"> */</span>
+<a name="l00142"></a>00142 ODE_API dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback);
+<a name="l00143"></a>00143 
+<a name="l00144"></a>00144 ODE_API <span class="keywordtype">void</span> dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data);
+<a name="l00145"></a>00145 ODE_API dTriMeshDataID dGeomTriMeshGetData(dGeomID g);
+<a name="l00146"></a>00146 
+<a name="l00147"></a>00147 
+<a name="l00148"></a>00148 <span class="comment">// enable/disable/check temporal coherence</span>
+<a name="l00149"></a>00149 ODE_API <span class="keywordtype">void</span> dGeomTriMeshEnableTC(dGeomID g, <span class="keywordtype">int</span> geomClass, <span class="keywordtype">int</span> enable);
+<a name="l00150"></a>00150 ODE_API <span class="keywordtype">int</span> dGeomTriMeshIsTCEnabled(dGeomID g, <span class="keywordtype">int</span> geomClass);
+<a name="l00151"></a>00151 
+<a name="l00152"></a>00152 <span class="comment">/*</span>
+<a name="l00153"></a>00153 <span class="comment"> * Clears the internal temporal coherence caches. When a geom has its</span>
+<a name="l00154"></a>00154 <span class="comment"> * collision checked with a trimesh once, data is stored inside the trimesh.</span>
+<a name="l00155"></a>00155 <span class="comment"> * With large worlds with lots of seperate objects this list could get huge.</span>
+<a name="l00156"></a>00156 <span class="comment"> * We should be able to do this automagically.</span>
+<a name="l00157"></a>00157 <span class="comment"> */</span>
+<a name="l00158"></a>00158 ODE_API <span class="keywordtype">void</span> dGeomTriMeshClearTCCache(dGeomID g);
+<a name="l00159"></a>00159 
+<a name="l00160"></a>00160 
+<a name="l00161"></a>00161 <span class="comment">/*</span>
+<a name="l00162"></a>00162 <span class="comment"> * returns the TriMeshDataID</span>
+<a name="l00163"></a>00163 <span class="comment"> */</span>
+<a name="l00164"></a>00164 ODE_API dTriMeshDataID dGeomTriMeshGetTriMeshDataID(dGeomID g);
+<a name="l00165"></a>00165 
+<a name="l00166"></a>00166 <span class="comment">/*</span>
+<a name="l00167"></a>00167 <span class="comment"> * Gets a triangle.</span>
+<a name="l00168"></a>00168 <span class="comment"> */</span>
+<a name="l00169"></a>00169 ODE_API <span class="keywordtype">void</span> dGeomTriMeshGetTriangle(dGeomID g, <span class="keywordtype">int</span> Index, dVector3* v0, dVector3* v1, dVector3* v2);
+<a name="l00170"></a>00170 
+<a name="l00171"></a>00171 <span class="comment">/*</span>
+<a name="l00172"></a>00172 <span class="comment"> * Gets the point on the requested triangle and the given barycentric</span>
+<a name="l00173"></a>00173 <span class="comment"> * coordinates.</span>
+<a name="l00174"></a>00174 <span class="comment"> */</span>
+<a name="l00175"></a>00175 ODE_API <span class="keywordtype">void</span> dGeomTriMeshGetPoint(dGeomID g, <span class="keywordtype">int</span> Index, dReal u, dReal v, dVector3 Out);
+<a name="l00176"></a>00176 
+<a name="l00177"></a>00177 <span class="comment">/*</span>
+<a name="l00178"></a>00178 <span class="comment"></span>
+<a name="l00179"></a>00179 <span class="comment">This is how the strided data works:</span>
+<a name="l00180"></a>00180 <span class="comment"></span>
+<a name="l00181"></a>00181 <span class="comment">struct StridedVertex{</span>
+<a name="l00182"></a>00182 <span class="comment">   dVector3 Vertex;</span>
+<a name="l00183"></a>00183 <span class="comment">   // Userdata</span>
+<a name="l00184"></a>00184 <span class="comment">};</span>
+<a name="l00185"></a>00185 <span class="comment">int VertexStride = sizeof(StridedVertex);</span>
+<a name="l00186"></a>00186 <span class="comment"></span>
+<a name="l00187"></a>00187 <span class="comment">struct StridedTri{</span>
+<a name="l00188"></a>00188 <span class="comment">   int Indices[3];</span>
+<a name="l00189"></a>00189 <span class="comment">   // Userdata</span>
+<a name="l00190"></a>00190 <span class="comment">};</span>
+<a name="l00191"></a>00191 <span class="comment">int TriStride = sizeof(StridedTri);</span>
+<a name="l00192"></a>00192 <span class="comment"></span>
+<a name="l00193"></a>00193 <span class="comment">*/</span>
+<a name="l00194"></a>00194 
+<a name="l00195"></a>00195 
+<a name="l00196"></a>00196 ODE_API <span class="keywordtype">int</span> dGeomTriMeshGetTriangleCount (dGeomID g);
+<a name="l00197"></a>00197 
+<a name="l00198"></a>00198 ODE_API <span class="keywordtype">void</span> dGeomTriMeshDataUpdate(dTriMeshDataID g);
+<a name="l00199"></a>00199 
+<a name="l00200"></a>00200 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00201"></a>00201 <span class="preprocessor"></span>}
+<a name="l00202"></a>00202 <span class="preprocessor">#endif</span>
+<a name="l00203"></a>00203 <span class="preprocessor"></span>
+<a name="l00204"></a>00204 <span class="preprocessor">#endif   </span><span class="comment">/* _ODE_COLLISION_TRIMESH_H_ */</span>
+<a name="l00205"></a>00205 
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/common_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/common_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/common_8h-source.html	(revision 216)
@@ -0,0 +1,408 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: common.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>common.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_COMMON_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_COMMON_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span><span class="preprocessor">#include &lt;ode/config.h&gt;</span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/error.h&gt;</span>
+<a name="l00027"></a>00027 <span class="preprocessor">#include &lt;math.h&gt;</span>
+<a name="l00028"></a>00028 
+<a name="l00029"></a>00029 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00030"></a>00030 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00031"></a>00031 <span class="preprocessor">#endif</span>
+<a name="l00032"></a>00032 <span class="preprocessor"></span>
+<a name="l00033"></a>00033 
+<a name="l00034"></a>00034 <span class="comment">/* configuration stuff */</span>
+<a name="l00035"></a>00035 
+<a name="l00036"></a>00036 <span class="comment">/* the efficient alignment. most platforms align data structures to some</span>
+<a name="l00037"></a>00037 <span class="comment"> * number of bytes, but this is not always the most efficient alignment.</span>
+<a name="l00038"></a>00038 <span class="comment"> * for example, many x86 compilers align to 4 bytes, but on a pentium it</span>
+<a name="l00039"></a>00039 <span class="comment"> * is important to align doubles to 8 byte boundaries (for speed), and</span>
+<a name="l00040"></a>00040 <span class="comment"> * the 4 floats in a SIMD register to 16 byte boundaries. many other</span>
+<a name="l00041"></a>00041 <span class="comment"> * platforms have similar behavior. setting a larger alignment can waste</span>
+<a name="l00042"></a>00042 <span class="comment"> * a (very) small amount of memory. NOTE: this number must be a power of</span>
+<a name="l00043"></a>00043 <span class="comment"> * two. this is set to 16 by default.</span>
+<a name="l00044"></a>00044 <span class="comment"> */</span>
+<a name="l00045"></a>00045 <span class="preprocessor">#define EFFICIENT_ALIGNMENT 16</span>
+<a name="l00046"></a>00046 <span class="preprocessor"></span>
+<a name="l00047"></a>00047 
+<a name="l00048"></a>00048 <span class="comment">/* constants */</span>
+<a name="l00049"></a>00049 
+<a name="l00050"></a>00050 <span class="comment">/* pi and 1/sqrt(2) are defined here if necessary because they don't get</span>
+<a name="l00051"></a>00051 <span class="comment"> * defined in &lt;math.h&gt; on some platforms (like MS-Windows)</span>
+<a name="l00052"></a>00052 <span class="comment"> */</span>
+<a name="l00053"></a>00053 
+<a name="l00054"></a>00054 <span class="preprocessor">#ifndef M_PI</span>
+<a name="l00055"></a>00055 <span class="preprocessor"></span><span class="preprocessor">#define M_PI REAL(3.1415926535897932384626433832795029)</span>
+<a name="l00056"></a>00056 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00057"></a>00057 <span class="preprocessor"></span><span class="preprocessor">#ifndef M_SQRT1_2</span>
+<a name="l00058"></a>00058 <span class="preprocessor"></span><span class="preprocessor">#define M_SQRT1_2 REAL(0.7071067811865475244008443621048490)</span>
+<a name="l00059"></a>00059 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00060"></a>00060 <span class="preprocessor"></span>
+<a name="l00061"></a>00061 
+<a name="l00062"></a>00062 <span class="comment">/* debugging:</span>
+<a name="l00063"></a>00063 <span class="comment"> *   IASSERT  is an internal assertion, i.e. a consistency check. if it fails</span>
+<a name="l00064"></a>00064 <span class="comment"> *            we want to know where.</span>
+<a name="l00065"></a>00065 <span class="comment"> *   UASSERT  is a user assertion, i.e. if it fails a nice error message</span>
+<a name="l00066"></a>00066 <span class="comment"> *            should be printed for the user.</span>
+<a name="l00067"></a>00067 <span class="comment"> *   AASSERT  is an arguments assertion, i.e. if it fails "bad argument(s)"</span>
+<a name="l00068"></a>00068 <span class="comment"> *            is printed.</span>
+<a name="l00069"></a>00069 <span class="comment"> *   DEBUGMSG just prints out a message</span>
+<a name="l00070"></a>00070 <span class="comment"> */</span>
+<a name="l00071"></a>00071 
+<a name="l00072"></a>00072 <span class="preprocessor">#ifndef dNODEBUG</span>
+<a name="l00073"></a>00073 <span class="preprocessor"></span><span class="preprocessor">#ifdef __GNUC__</span>
+<a name="l00074"></a>00074 <span class="preprocessor"></span><span class="preprocessor">#define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \</span>
+<a name="l00075"></a>00075 <span class="preprocessor">  "assertion \"" #a "\" failed in %s() [%s]",__FUNCTION__,__FILE__);</span>
+<a name="l00076"></a>00076 <span class="preprocessor"></span><span class="preprocessor">#define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \</span>
+<a name="l00077"></a>00077 <span class="preprocessor">  msg " in %s()", __FUNCTION__);</span>
+<a name="l00078"></a>00078 <span class="preprocessor"></span><span class="preprocessor">#define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT,          \</span>
+<a name="l00079"></a>00079 <span class="preprocessor">msg " in %s() File %s Line %d", __FUNCTION__, __FILE__,__LINE__);</span>
+<a name="l00080"></a>00080 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00081"></a>00081 <span class="preprocessor"></span><span class="preprocessor">#define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \</span>
+<a name="l00082"></a>00082 <span class="preprocessor">  "assertion \"" #a "\" failed in %s:%d",__FILE__,__LINE__);</span>
+<a name="l00083"></a>00083 <span class="preprocessor"></span><span class="preprocessor">#define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \</span>
+<a name="l00084"></a>00084 <span class="preprocessor">  msg " (%s:%d)", __FILE__,__LINE__);</span>
+<a name="l00085"></a>00085 <span class="preprocessor"></span><span class="preprocessor">#define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT, \</span>
+<a name="l00086"></a>00086 <span class="preprocessor">  msg " (%s:%d)", __FILE__,__LINE__);</span>
+<a name="l00087"></a>00087 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00088"></a>00088 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00089"></a>00089 <span class="preprocessor"></span><span class="preprocessor">#define dIASSERT(a) ;</span>
+<a name="l00090"></a>00090 <span class="preprocessor"></span><span class="preprocessor">#define dUASSERT(a,msg) ;</span>
+<a name="l00091"></a>00091 <span class="preprocessor"></span><span class="preprocessor">#define dDEBUGMSG(msg) ;</span>
+<a name="l00092"></a>00092 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00093"></a>00093 <span class="preprocessor"></span><span class="preprocessor">#define dAASSERT(a) dUASSERT(a,"Bad argument(s)")</span>
+<a name="l00094"></a>00094 <span class="preprocessor"></span>
+<a name="l00095"></a>00095 <span class="comment">// Macro used to suppress unused variable warning</span>
+<a name="l00096"></a>00096 <span class="preprocessor">#define dVARIABLEUSED(a) ((void)a)</span>
+<a name="l00097"></a>00097 <span class="preprocessor"></span>
+<a name="l00098"></a>00098 <span class="comment">/* floating point data type, vector, matrix and quaternion types */</span>
+<a name="l00099"></a>00099 
+<a name="l00100"></a>00100 <span class="preprocessor">#if defined(dSINGLE)</span>
+<a name="l00101"></a>00101 <span class="preprocessor"></span><span class="keyword">typedef</span> <span class="keywordtype">float</span> dReal;
+<a name="l00102"></a>00102 <span class="preprocessor">#ifdef dDOUBLE</span>
+<a name="l00103"></a>00103 <span class="preprocessor"></span><span class="preprocessor">#error You can only #define dSINGLE or dDOUBLE, not both.</span>
+<a name="l00104"></a>00104 <span class="preprocessor"></span><span class="preprocessor">#endif // dDOUBLE</span>
+<a name="l00105"></a>00105 <span class="preprocessor"></span><span class="preprocessor">#elif defined(dDOUBLE)</span>
+<a name="l00106"></a>00106 <span class="preprocessor"></span><span class="keyword">typedef</span> <span class="keywordtype">double</span> dReal;
+<a name="l00107"></a>00107 <span class="preprocessor">#else</span>
+<a name="l00108"></a>00108 <span class="preprocessor"></span><span class="preprocessor">#error You must #define dSINGLE or dDOUBLE</span>
+<a name="l00109"></a>00109 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00110"></a>00110 <span class="preprocessor"></span>
+<a name="l00111"></a>00111 <span class="comment">// Detect if we've got both trimesh engines enabled.</span>
+<a name="l00112"></a>00112 <span class="preprocessor">#if dTRIMESH_ENABLED</span>
+<a name="l00113"></a>00113 <span class="preprocessor"></span><span class="preprocessor">#if dTRIMESH_OPCODE &amp;&amp; dTRIMESH_GIMPACT</span>
+<a name="l00114"></a>00114 <span class="preprocessor"></span><span class="preprocessor">#error You can only #define dTRIMESH_OPCODE or dTRIMESH_GIMPACT, not both.</span>
+<a name="l00115"></a>00115 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00116"></a>00116 <span class="preprocessor"></span><span class="preprocessor">#endif // dTRIMESH_ENABLED</span>
+<a name="l00117"></a>00117 <span class="preprocessor"></span>
+<a name="l00118"></a>00118 <span class="comment">/* round an integer up to a multiple of 4, except that 0 and 1 are unmodified</span>
+<a name="l00119"></a>00119 <span class="comment"> * (used to compute matrix leading dimensions)</span>
+<a name="l00120"></a>00120 <span class="comment"> */</span>
+<a name="l00121"></a>00121 <span class="preprocessor">#define dPAD(a) (((a) &gt; 1) ? ((((a)-1)|3)+1) : (a))</span>
+<a name="l00122"></a>00122 <span class="preprocessor"></span>
+<a name="l00123"></a>00123 <span class="comment">/* these types are mainly just used in headers */</span>
+<a name="l00124"></a>00124 <span class="keyword">typedef</span> dReal dVector3[4];
+<a name="l00125"></a>00125 <span class="keyword">typedef</span> dReal dVector4[4];
+<a name="l00126"></a>00126 <span class="keyword">typedef</span> dReal dMatrix3[4*3];
+<a name="l00127"></a>00127 <span class="keyword">typedef</span> dReal dMatrix4[4*4];
+<a name="l00128"></a>00128 <span class="keyword">typedef</span> dReal dMatrix6[8*6];
+<a name="l00129"></a>00129 <span class="keyword">typedef</span> dReal dQuaternion[4];
+<a name="l00130"></a>00130 
+<a name="l00131"></a>00131 
+<a name="l00132"></a>00132 <span class="comment">/* precision dependent scalar math functions */</span>
+<a name="l00133"></a>00133 
+<a name="l00134"></a>00134 <span class="preprocessor">#if defined(dSINGLE)</span>
+<a name="l00135"></a>00135 <span class="preprocessor"></span>
+<a name="l00136"></a>00136 <span class="preprocessor">#define REAL(x) (x ## f)               </span><span class="comment">/* form a constant */</span>
+<a name="l00137"></a>00137 <span class="preprocessor">#define dRecip(x) ((1.0f/(x)))            </span><span class="comment">/* reciprocal */</span>
+<a name="l00138"></a>00138 <span class="preprocessor">#define dSqrt(x) (sqrtf(x))         </span><span class="comment">/* square root */</span>
+<a name="l00139"></a>00139 <span class="preprocessor">#define dRecipSqrt(x) ((1.0f/sqrtf(x)))      </span><span class="comment">/* reciprocal square root */</span>
+<a name="l00140"></a>00140 <span class="preprocessor">#define dSin(x) (sinf(x))           </span><span class="comment">/* sine */</span>
+<a name="l00141"></a>00141 <span class="preprocessor">#define dCos(x) (cosf(x))           </span><span class="comment">/* cosine */</span>
+<a name="l00142"></a>00142 <span class="preprocessor">#define dFabs(x) (fabsf(x))         </span><span class="comment">/* absolute value */</span>
+<a name="l00143"></a>00143 <span class="preprocessor">#define dAtan2(y,x) (atan2f(y,x))      </span><span class="comment">/* arc tangent with 2 args */</span>
+<a name="l00144"></a>00144 <span class="preprocessor">#define dFMod(a,b) (fmodf(a,b))     </span><span class="comment">/* modulo */</span>
+<a name="l00145"></a>00145 <span class="preprocessor">#define dFloor(x) floorf(x)         </span><span class="comment">/* floor */</span>
+<a name="l00146"></a>00146 
+<a name="l00147"></a>00147 <span class="preprocessor">#ifdef HAVE___ISNANF</span>
+<a name="l00148"></a>00148 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (__isnanf(x))</span>
+<a name="l00149"></a>00149 <span class="preprocessor"></span><span class="preprocessor">#elif defined(HAVE__ISNANF)</span>
+<a name="l00150"></a>00150 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (_isnanf(x))</span>
+<a name="l00151"></a>00151 <span class="preprocessor"></span><span class="preprocessor">#elif defined(HAVE_ISNANF)</span>
+<a name="l00152"></a>00152 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (isnanf(x))</span>
+<a name="l00153"></a>00153 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00154"></a>00154 <span class="preprocessor"></span>  <span class="comment">/*</span>
+<a name="l00155"></a>00155 <span class="comment">     fall back to _isnan which is the VC way,</span>
+<a name="l00156"></a>00156 <span class="comment">     this may seem redundant since we already checked</span>
+<a name="l00157"></a>00157 <span class="comment">     for _isnan before, but if isnan is detected by</span>
+<a name="l00158"></a>00158 <span class="comment">     configure but is not found during compilation</span>
+<a name="l00159"></a>00159 <span class="comment">     we should always make sure we check for __isnanf,</span>
+<a name="l00160"></a>00160 <span class="comment">     _isnanf and isnanf in that order before falling</span>
+<a name="l00161"></a>00161 <span class="comment">     back to a default</span>
+<a name="l00162"></a>00162 <span class="comment">  */</span>
+<a name="l00163"></a>00163 <span class="preprocessor">#define dIsNan(x) (_isnan(x))</span>
+<a name="l00164"></a>00164 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00165"></a>00165 <span class="preprocessor"></span>
+<a name="l00166"></a>00166 <span class="preprocessor">#define dCopySign(a,b) ((dReal)copysignf(a,b))</span>
+<a name="l00167"></a>00167 <span class="preprocessor"></span>
+<a name="l00168"></a>00168 <span class="preprocessor">#elif defined(dDOUBLE)</span>
+<a name="l00169"></a>00169 <span class="preprocessor"></span>
+<a name="l00170"></a>00170 <span class="preprocessor">#define REAL(x) (x)</span>
+<a name="l00171"></a>00171 <span class="preprocessor"></span><span class="preprocessor">#define dRecip(x) (1.0/(x))</span>
+<a name="l00172"></a>00172 <span class="preprocessor"></span><span class="preprocessor">#define dSqrt(x) sqrt(x)</span>
+<a name="l00173"></a>00173 <span class="preprocessor"></span><span class="preprocessor">#define dRecipSqrt(x) (1.0/sqrt(x))</span>
+<a name="l00174"></a>00174 <span class="preprocessor"></span><span class="preprocessor">#define dSin(x) sin(x)</span>
+<a name="l00175"></a>00175 <span class="preprocessor"></span><span class="preprocessor">#define dCos(x) cos(x)</span>
+<a name="l00176"></a>00176 <span class="preprocessor"></span><span class="preprocessor">#define dFabs(x) fabs(x)</span>
+<a name="l00177"></a>00177 <span class="preprocessor"></span><span class="preprocessor">#define dAtan2(y,x) atan2((y),(x))</span>
+<a name="l00178"></a>00178 <span class="preprocessor"></span><span class="preprocessor">#define dFMod(a,b) (fmod((a),(b)))</span>
+<a name="l00179"></a>00179 <span class="preprocessor"></span><span class="preprocessor">#define dFloor(x) floor(x)</span>
+<a name="l00180"></a>00180 <span class="preprocessor"></span>
+<a name="l00181"></a>00181 <span class="preprocessor">#ifdef HAVE___ISNAN</span>
+<a name="l00182"></a>00182 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (__isnan(x))</span>
+<a name="l00183"></a>00183 <span class="preprocessor"></span><span class="preprocessor">#elif defined(HAVE__ISNAN)</span>
+<a name="l00184"></a>00184 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (_isnan(x))</span>
+<a name="l00185"></a>00185 <span class="preprocessor"></span><span class="preprocessor">#elif defined(HAVE_ISNAN)</span>
+<a name="l00186"></a>00186 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (isnan(x))</span>
+<a name="l00187"></a>00187 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00188"></a>00188 <span class="preprocessor"></span><span class="preprocessor">#define dIsNan(x) (_isnan(x))</span>
+<a name="l00189"></a>00189 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00190"></a>00190 <span class="preprocessor"></span>
+<a name="l00191"></a>00191 <span class="preprocessor">#define dCopySign(a,b) (copysign((a),(b)))</span>
+<a name="l00192"></a>00192 <span class="preprocessor"></span>
+<a name="l00193"></a>00193 <span class="preprocessor">#else</span>
+<a name="l00194"></a>00194 <span class="preprocessor"></span><span class="preprocessor">#error You must #define dSINGLE or dDOUBLE</span>
+<a name="l00195"></a>00195 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00196"></a>00196 <span class="preprocessor"></span>
+<a name="l00197"></a>00197 
+<a name="l00198"></a>00198 <span class="comment">/* utility */</span>
+<a name="l00199"></a>00199 
+<a name="l00200"></a>00200 
+<a name="l00201"></a>00201 <span class="comment">/* round something up to be a multiple of the EFFICIENT_ALIGNMENT */</span>
+<a name="l00202"></a>00202 
+<a name="l00203"></a>00203 <span class="preprocessor">#define dEFFICIENT_SIZE(x) ((((x)-1)|(EFFICIENT_ALIGNMENT-1))+1)</span>
+<a name="l00204"></a>00204 <span class="preprocessor"></span>
+<a name="l00205"></a>00205 
+<a name="l00206"></a>00206 <span class="comment">/* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste</span>
+<a name="l00207"></a>00207 <span class="comment"> * up to 15 bytes per allocation, depending on what alloca() returns.</span>
+<a name="l00208"></a>00208 <span class="comment"> */</span>
+<a name="l00209"></a>00209 
+<a name="l00210"></a>00210 <span class="preprocessor">#define dALLOCA16(n) \</span>
+<a name="l00211"></a>00211 <span class="preprocessor">  ((char*)dEFFICIENT_SIZE(((size_t)(alloca((n)+(EFFICIENT_ALIGNMENT-1))))))</span>
+<a name="l00212"></a>00212 <span class="preprocessor"></span>
+<a name="l00213"></a>00213 
+<a name="l00214"></a>00214 <span class="comment">// Use the error-checking memory allocation system.  Because this system uses heap</span>
+<a name="l00215"></a>00215 <span class="comment">//  (malloc) instead of stack (alloca), it is slower.  However, it allows you to</span>
+<a name="l00216"></a>00216 <span class="comment">//  simulate larger scenes, as well as handle out-of-memory errors in a somewhat</span>
+<a name="l00217"></a>00217 <span class="comment">//  graceful manner</span>
+<a name="l00218"></a>00218 
+<a name="l00219"></a>00219 <span class="comment">// #define dUSE_MALLOC_FOR_ALLOCA</span>
+<a name="l00220"></a>00220 
+<a name="l00221"></a>00221 <span class="preprocessor">#ifdef dUSE_MALLOC_FOR_ALLOCA</span>
+<a name="l00222"></a>00222 <span class="preprocessor"></span><span class="keyword">enum</span> {
+<a name="l00223"></a>00223   d_MEMORY_OK = 0,      <span class="comment">/* no memory errors */</span>
+<a name="l00224"></a>00224   d_MEMORY_OUT_OF_MEMORY   <span class="comment">/* malloc failed due to out of memory error */</span>
+<a name="l00225"></a>00225 };
+<a name="l00226"></a>00226 
+<a name="l00227"></a>00227 <span class="preprocessor">#endif</span>
+<a name="l00228"></a>00228 <span class="preprocessor"></span>
+<a name="l00229"></a>00229 
+<a name="l00230"></a>00230 
+<a name="l00231"></a>00231 <span class="comment">/* internal object types (all prefixed with `dx') */</span>
+<a name="l00232"></a>00232 
+<a name="l00233"></a>00233 <span class="keyword">struct </span>dxWorld;      <span class="comment">/* dynamics world */</span>
+<a name="l00234"></a>00234 <span class="keyword">struct </span>dxSpace;      <span class="comment">/* collision space */</span>
+<a name="l00235"></a>00235 <span class="keyword">struct </span>dxBody;    <span class="comment">/* rigid body (dynamics object) */</span>
+<a name="l00236"></a>00236 <span class="keyword">struct </span>dxGeom;    <span class="comment">/* geometry (collision object) */</span>
+<a name="l00237"></a>00237 <span class="keyword">struct </span>dxJoint;
+<a name="l00238"></a>00238 <span class="keyword">struct </span>dxJointNode;
+<a name="l00239"></a>00239 <span class="keyword">struct </span>dxJointGroup;
+<a name="l00240"></a>00240 
+<a name="l00241"></a>00241 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxWorld *dWorldID;
+<a name="l00242"></a>00242 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxSpace *dSpaceID;
+<a name="l00243"></a>00243 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxBody *dBodyID;
+<a name="l00244"></a>00244 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxGeom *dGeomID;
+<a name="l00245"></a>00245 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxJoint *dJointID;
+<a name="l00246"></a>00246 <span class="keyword">typedef</span> <span class="keyword">struct </span>dxJointGroup *dJointGroupID;
+<a name="l00247"></a>00247 
+<a name="l00248"></a>00248 
+<a name="l00249"></a>00249 <span class="comment">/* error numbers */</span>
+<a name="l00250"></a>00250 
+<a name="l00251"></a>00251 <span class="keyword">enum</span> {
+<a name="l00252"></a>00252   d_ERR_UNKNOWN = 0,    <span class="comment">/* unknown error */</span>
+<a name="l00253"></a>00253   d_ERR_IASSERT,     <span class="comment">/* internal assertion failed */</span>
+<a name="l00254"></a>00254   d_ERR_UASSERT,     <span class="comment">/* user assertion failed */</span>
+<a name="l00255"></a>00255   d_ERR_LCP       <span class="comment">/* user assertion failed */</span>
+<a name="l00256"></a>00256 };
+<a name="l00257"></a>00257 
+<a name="l00258"></a>00258 
+<a name="l00259"></a>00259 <span class="comment">/* joint type numbers */</span>
+<a name="l00260"></a>00260 
+<a name="l00261"></a>00261 <span class="keyword">enum</span> {
+<a name="l00262"></a>00262   dJointTypeNone = 0,      <span class="comment">/* or "unknown" */</span>
+<a name="l00263"></a>00263   dJointTypeBall,
+<a name="l00264"></a>00264   dJointTypeHinge,
+<a name="l00265"></a>00265   dJointTypeSlider,
+<a name="l00266"></a>00266   dJointTypeContact,
+<a name="l00267"></a>00267   dJointTypeUniversal,
+<a name="l00268"></a>00268   dJointTypeHinge2,
+<a name="l00269"></a>00269   dJointTypeFixed,
+<a name="l00270"></a>00270   dJointTypeNull,
+<a name="l00271"></a>00271   dJointTypeAMotor,
+<a name="l00272"></a>00272   dJointTypeLMotor,
+<a name="l00273"></a>00273   dJointTypePlane2D,
+<a name="l00274"></a>00274   dJointTypePR
+<a name="l00275"></a>00275 };
+<a name="l00276"></a>00276 
+<a name="l00277"></a>00277 
+<a name="l00278"></a>00278 <span class="comment">/* an alternative way of setting joint parameters, using joint parameter</span>
+<a name="l00279"></a>00279 <span class="comment"> * structures and member constants. we don't actually do this yet.</span>
+<a name="l00280"></a>00280 <span class="comment"> */</span>
+<a name="l00281"></a>00281 
+<a name="l00282"></a>00282 <span class="comment">/*</span>
+<a name="l00283"></a>00283 <span class="comment">typedef struct dLimot {</span>
+<a name="l00284"></a>00284 <span class="comment">  int mode;</span>
+<a name="l00285"></a>00285 <span class="comment">  dReal lostop, histop;</span>
+<a name="l00286"></a>00286 <span class="comment">  dReal vel, fmax;</span>
+<a name="l00287"></a>00287 <span class="comment">  dReal fudge_factor;</span>
+<a name="l00288"></a>00288 <span class="comment">  dReal bounce, soft;</span>
+<a name="l00289"></a>00289 <span class="comment">  dReal suspension_erp, suspension_cfm;</span>
+<a name="l00290"></a>00290 <span class="comment">} dLimot;</span>
+<a name="l00291"></a>00291 <span class="comment"></span>
+<a name="l00292"></a>00292 <span class="comment">enum {</span>
+<a name="l00293"></a>00293 <span class="comment">  dLimotLoStop    = 0x0001,</span>
+<a name="l00294"></a>00294 <span class="comment">  dLimotHiStop    = 0x0002,</span>
+<a name="l00295"></a>00295 <span class="comment">  dLimotVel    = 0x0004,</span>
+<a name="l00296"></a>00296 <span class="comment">  dLimotFMax      = 0x0008,</span>
+<a name="l00297"></a>00297 <span class="comment">  dLimotFudgeFactor  = 0x0010,</span>
+<a name="l00298"></a>00298 <span class="comment">  dLimotBounce    = 0x0020,</span>
+<a name="l00299"></a>00299 <span class="comment">  dLimotSoft      = 0x0040</span>
+<a name="l00300"></a>00300 <span class="comment">};</span>
+<a name="l00301"></a>00301 <span class="comment">*/</span>
+<a name="l00302"></a>00302 
+<a name="l00303"></a>00303 
+<a name="l00304"></a>00304 <span class="comment">/* standard joint parameter names. why are these here? - because we don't want</span>
+<a name="l00305"></a>00305 <span class="comment"> * to include all the joint function definitions in joint.cpp. hmmmm.</span>
+<a name="l00306"></a>00306 <span class="comment"> * MSVC complains if we call D_ALL_PARAM_NAMES_X with a blank second argument,</span>
+<a name="l00307"></a>00307 <span class="comment"> * which is why we have the D_ALL_PARAM_NAMES macro as well. please copy and</span>
+<a name="l00308"></a>00308 <span class="comment"> * paste between these two.</span>
+<a name="l00309"></a>00309 <span class="comment"> */</span>
+<a name="l00310"></a>00310 
+<a name="l00311"></a>00311 <span class="preprocessor">#define D_ALL_PARAM_NAMES(start) \</span>
+<a name="l00312"></a>00312 <span class="preprocessor">  </span><span class="comment">/* parameters for limits and motors */</span> \
+<a name="l00313"></a>00313   dParamLoStop = start, \
+<a name="l00314"></a>00314   dParamHiStop, \
+<a name="l00315"></a>00315   dParamVel, \
+<a name="l00316"></a>00316   dParamFMax, \
+<a name="l00317"></a>00317   dParamFudgeFactor, \
+<a name="l00318"></a>00318   dParamBounce, \
+<a name="l00319"></a>00319   dParamCFM, \
+<a name="l00320"></a>00320   dParamStopERP, \
+<a name="l00321"></a>00321   dParamStopCFM, \
+<a name="l00322"></a>00322   <span class="comment">/* parameters for suspension */</span> \
+<a name="l00323"></a>00323   dParamSuspensionERP, \
+<a name="l00324"></a>00324   dParamSuspensionCFM, \
+<a name="l00325"></a>00325   dParamERP, \
+<a name="l00326"></a>00326 
+<a name="l00327"></a>00327 <span class="preprocessor">#define D_ALL_PARAM_NAMES_X(start,x) \</span>
+<a name="l00328"></a>00328 <span class="preprocessor">  </span><span class="comment">/* parameters for limits and motors */</span> \
+<a name="l00329"></a>00329   dParamLoStop ## x = start, \
+<a name="l00330"></a>00330   dParamHiStop ## x, \
+<a name="l00331"></a>00331   dParamVel ## x, \
+<a name="l00332"></a>00332   dParamFMax ## x, \
+<a name="l00333"></a>00333   dParamFudgeFactor ## x, \
+<a name="l00334"></a>00334   dParamBounce ## x, \
+<a name="l00335"></a>00335   dParamCFM ## x, \
+<a name="l00336"></a>00336   dParamStopERP ## x, \
+<a name="l00337"></a>00337   dParamStopCFM ## x, \
+<a name="l00338"></a>00338   <span class="comment">/* parameters for suspension */</span> \
+<a name="l00339"></a>00339   dParamSuspensionERP ## x, \
+<a name="l00340"></a>00340   dParamSuspensionCFM ## x, \
+<a name="l00341"></a>00341   dParamERP ## x,
+<a name="l00342"></a>00342 
+<a name="l00343"></a>00343 <span class="keyword">enum</span> {
+<a name="l00344"></a>00344   D_ALL_PARAM_NAMES(0)
+<a name="l00345"></a>00345   D_ALL_PARAM_NAMES_X(0x100,2)
+<a name="l00346"></a>00346   D_ALL_PARAM_NAMES_X(0x200,3)
+<a name="l00347"></a>00347 
+<a name="l00348"></a>00348   <span class="comment">/* add a multiple of this constant to the basic parameter numbers to get</span>
+<a name="l00349"></a>00349 <span class="comment">   * the parameters for the second, third etc axes.</span>
+<a name="l00350"></a>00350 <span class="comment">   */</span>
+<a name="l00351"></a>00351   dParamGroup=0x100
+<a name="l00352"></a>00352 };
+<a name="l00353"></a>00353 
+<a name="l00354"></a>00354 
+<a name="l00355"></a>00355 <span class="comment">/* angular motor mode numbers */</span>
+<a name="l00356"></a>00356 
+<a name="l00357"></a>00357 enum{
+<a name="l00358"></a>00358   dAMotorUser = 0,
+<a name="l00359"></a>00359   dAMotorEuler = 1
+<a name="l00360"></a>00360 };
+<a name="l00361"></a>00361 
+<a name="l00362"></a>00362 
+<a name="l00363"></a>00363 <span class="comment">/* joint force feedback information */</span>
+<a name="l00364"></a>00364 
+<a name="l00365"></a>00365 <span class="keyword">typedef</span> <span class="keyword">struct </span>dJointFeedback {
+<a name="l00366"></a>00366   dVector3 f1;    <span class="comment">/* force applied to body 1 */</span>
+<a name="l00367"></a>00367   dVector3 t1;    <span class="comment">/* torque applied to body 1 */</span>
+<a name="l00368"></a>00368   dVector3 f2;    <span class="comment">/* force applied to body 2 */</span>
+<a name="l00369"></a>00369   dVector3 t2;    <span class="comment">/* torque applied to body 2 */</span>
+<a name="l00370"></a>00370 } dJointFeedback;
+<a name="l00371"></a>00371 
+<a name="l00372"></a>00372 
+<a name="l00373"></a>00373 <span class="comment">/* private functions that must be implemented by the collision library:</span>
+<a name="l00374"></a>00374 <span class="comment"> * (1) indicate that a geom has moved, (2) get the next geom in a body list.</span>
+<a name="l00375"></a>00375 <span class="comment"> * these functions are called whenever the position of geoms connected to a</span>
+<a name="l00376"></a>00376 <span class="comment"> * body have changed, e.g. with dBodySetPosition(), dBodySetRotation(), or</span>
+<a name="l00377"></a>00377 <span class="comment"> * when the ODE step function updates the body state.</span>
+<a name="l00378"></a>00378 <span class="comment"> */</span>
+<a name="l00379"></a>00379 
+<a name="l00380"></a>00380 <span class="keywordtype">void</span> dGeomMoved (dGeomID);
+<a name="l00381"></a>00381 dGeomID dGeomGetBodyNext (dGeomID);
+<a name="l00382"></a>00382 
+<a name="l00383"></a>00383 
+<a name="l00384"></a>00384 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00385"></a>00385 <span class="preprocessor"></span>}
+<a name="l00386"></a>00386 <span class="preprocessor">#endif</span>
+<a name="l00387"></a>00387 <span class="preprocessor"></span>
+<a name="l00388"></a>00388 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/compatibility_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/compatibility_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/compatibility_8h-source.html	(revision 216)
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: compatibility.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>compatibility.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_COMPATIBILITY_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_COMPATIBILITY_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="comment">/*</span>
+<a name="l00027"></a>00027 <span class="comment"> * ODE's backward compatibility system ensures that as ODE's API</span>
+<a name="l00028"></a>00028 <span class="comment"> * evolves, user code will not break.</span>
+<a name="l00029"></a>00029 <span class="comment"> */</span>
+<a name="l00030"></a>00030 
+<a name="l00031"></a>00031 <span class="comment">/*</span>
+<a name="l00032"></a>00032 <span class="comment"> * These new rotation function names are more consistent with the</span>
+<a name="l00033"></a>00033 <span class="comment"> * rest of the API.</span>
+<a name="l00034"></a>00034 <span class="comment"> */</span>
+<a name="l00035"></a>00035 <span class="preprocessor">#define dQtoR(q,R) dRfromQ((R),(q))</span>
+<a name="l00036"></a>00036 <span class="preprocessor"></span><span class="preprocessor">#define dRtoQ(R,q) dQfromR((q),(R))</span>
+<a name="l00037"></a>00037 <span class="preprocessor"></span><span class="preprocessor">#define dWtoDQ(w,q,dq) dDQfromW((dq),(w),(q))</span>
+<a name="l00038"></a>00038 <span class="preprocessor"></span>
+<a name="l00039"></a>00039 
+<a name="l00040"></a>00040 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/config_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/config_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/config_8h-source.html	(revision 216)
@@ -0,0 +1,196 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: config.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>config.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/* This file was autogenerated by Premake */</span>
+<a name="l00002"></a>00002 <span class="preprocessor">#ifndef _ODE_CONFIG_H_</span>
+<a name="l00003"></a>00003 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_CONFIG_H_</span>
+<a name="l00004"></a>00004 <span class="preprocessor"></span>
+<a name="l00005"></a>00005 
+<a name="l00006"></a>00006 <span class="comment">/******************************************************************</span>
+<a name="l00007"></a>00007 <span class="comment"> * CONFIGURATON SETTINGS - you can change these, and then rebuild</span>
+<a name="l00008"></a>00008 <span class="comment"> *   ODE to modify the behavior of the library.</span>
+<a name="l00009"></a>00009 <span class="comment"> *</span>
+<a name="l00010"></a>00010 <span class="comment"> *   dSINGLE/dDOUBLE   - force ODE to use single-precision (float)</span>
+<a name="l00011"></a>00011 <span class="comment"> *                       or double-precision (double) for numbers.</span>
+<a name="l00012"></a>00012 <span class="comment"> *                       Only one should be defined.</span>
+<a name="l00013"></a>00013 <span class="comment"> *</span>
+<a name="l00014"></a>00014 <span class="comment"> *   dTRIMESH_ENABLED  - enable/disable trimesh support</span>
+<a name="l00015"></a>00015 <span class="comment"> *   dTRIMESH_OPCODE   - use the OPCODE trimesh engine</span>
+<a name="l00016"></a>00016 <span class="comment"> *   dTRIMESH_GIMPACT  - use the GIMPACT trimesh engine</span>
+<a name="l00017"></a>00017 <span class="comment"> *                       Only one trimesh engine should be enabled.</span>
+<a name="l00018"></a>00018 <span class="comment"> *</span>
+<a name="l00019"></a>00019 <span class="comment"> *   dUSE_MALLOC_FOR_ALLOCA (experimental)-</span>
+<a name="l00020"></a>00020 <span class="comment"> *                       Use malloc() instead of alloca(). Slower,</span>
+<a name="l00021"></a>00021 <span class="comment"> *                       but allows for larger systems and more</span>
+<a name="l00022"></a>00022 <span class="comment"> *                       graceful out-of-memory handling.</span>
+<a name="l00023"></a>00023 <span class="comment"> *</span>
+<a name="l00024"></a>00024 <span class="comment"> *   dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER (experimental)-</span>
+<a name="l00025"></a>00025 <span class="comment"> *                       Use an alternative trimesh-trimesh collider</span>
+<a name="l00026"></a>00026 <span class="comment"> *                       which should yield better results.</span>
+<a name="l00027"></a>00027 <span class="comment"> *</span>
+<a name="l00028"></a>00028 <span class="comment"> ******************************************************************/</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 <span class="preprocessor">#define dSINGLE</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="comment">/* #define dDOUBLE */</span>
+<a name="l00032"></a>00032 
+<a name="l00033"></a>00033 <span class="preprocessor">#define dTRIMESH_ENABLED 1</span>
+<a name="l00034"></a>00034 <span class="preprocessor"></span><span class="preprocessor">#define dTRIMESH_OPCODE 1</span>
+<a name="l00035"></a>00035 <span class="preprocessor"></span>
+<a name="l00036"></a>00036 <span class="preprocessor">#define dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER 0</span>
+<a name="l00037"></a>00037 <span class="preprocessor"></span>
+<a name="l00038"></a>00038 <span class="comment">/* #define dUSE_MALLOC_FOR_ALLOCA */</span>
+<a name="l00039"></a>00039 
+<a name="l00040"></a>00040 
+<a name="l00041"></a>00041 <span class="comment">/******************************************************************</span>
+<a name="l00042"></a>00042 <span class="comment"> * SYSTEM SETTINGS - you shouldn't need to change these. If you</span>
+<a name="l00043"></a>00043 <span class="comment"> *   run into an issue with these settings, please report it to</span>
+<a name="l00044"></a>00044 <span class="comment"> *   the ODE bug tracker at:</span>
+<a name="l00045"></a>00045 <span class="comment"> *      http://sf.net/tracker/?group_id=24884&amp;atid=382799</span>
+<a name="l00046"></a>00046 <span class="comment"> ******************************************************************/</span>
+<a name="l00047"></a>00047 
+<a name="l00048"></a>00048 <span class="comment">/* Try to identify the platform */</span>
+<a name="l00049"></a>00049 <span class="preprocessor">#if defined(_XENON)</span>
+<a name="l00050"></a>00050 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_PLATFORM_XBOX360</span>
+<a name="l00051"></a>00051 <span class="preprocessor"></span><span class="preprocessor">#elif defined(SN_TARGET_PSP_HW)</span>
+<a name="l00052"></a>00052 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_PLATFORM_PSP</span>
+<a name="l00053"></a>00053 <span class="preprocessor"></span><span class="preprocessor">#elif defined(SN_TARGET_PS3)</span>
+<a name="l00054"></a>00054 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_PLATFORM_PS3</span>
+<a name="l00055"></a>00055 <span class="preprocessor"></span><span class="preprocessor">#elif defined(_MSC_VER) || defined(__CYGWIN32__) || defined(__MINGW32__)</span>
+<a name="l00056"></a>00056 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_PLATFORM_WINDOWS</span>
+<a name="l00057"></a>00057 <span class="preprocessor"></span><span class="preprocessor">#elif defined(__linux__)</span>
+<a name="l00058"></a>00058 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_PLATFORM_LINUX</span>
+<a name="l00059"></a>00059 <span class="preprocessor"></span><span class="preprocessor">#elif defined(__APPLE__) &amp;&amp; defined(__MACH__)</span>
+<a name="l00060"></a>00060 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_PLATFORM_OSX</span>
+<a name="l00061"></a>00061 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00062"></a>00062 <span class="preprocessor"></span><span class="preprocessor">  #error "Need some help identifying the platform!"</span>
+<a name="l00063"></a>00063 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00064"></a>00064 <span class="preprocessor"></span>
+<a name="l00065"></a>00065 <span class="comment">/* Additional platform defines used in the code */</span>
+<a name="l00066"></a>00066 <span class="preprocessor">#if defined(ODE_PLATFORM_WINDOWS) &amp;&amp; !defined(WIN32)</span>
+<a name="l00067"></a>00067 <span class="preprocessor"></span><span class="preprocessor">  #define WIN32</span>
+<a name="l00068"></a>00068 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00069"></a>00069 <span class="preprocessor"></span>
+<a name="l00070"></a>00070 <span class="preprocessor">#if defined(__CYGWIN32__) || defined(__MINGW32__)</span>
+<a name="l00071"></a>00071 <span class="preprocessor"></span><span class="preprocessor">  #define CYGWIN</span>
+<a name="l00072"></a>00072 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00073"></a>00073 <span class="preprocessor"></span>
+<a name="l00074"></a>00074 <span class="preprocessor">#if defined(ODE_PLATFORM_OSX)</span>
+<a name="l00075"></a>00075 <span class="preprocessor"></span><span class="preprocessor">  #define macintosh</span>
+<a name="l00076"></a>00076 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00077"></a>00077 <span class="preprocessor"></span>
+<a name="l00078"></a>00078 
+<a name="l00079"></a>00079 <span class="comment">/* Define a DLL export symbol for those platforms that need it */</span>
+<a name="l00080"></a>00080 <span class="preprocessor">#if defined(ODE_PLATFORM_WINDOWS)</span>
+<a name="l00081"></a>00081 <span class="preprocessor"></span><span class="preprocessor">  #if defined(ODE_DLL)</span>
+<a name="l00082"></a>00082 <span class="preprocessor"></span><span class="preprocessor">    #define ODE_API __declspec(dllexport)</span>
+<a name="l00083"></a>00083 <span class="preprocessor"></span><span class="preprocessor">  #elif !defined(ODE_LIB)</span>
+<a name="l00084"></a>00084 <span class="preprocessor"></span><span class="preprocessor">    #define ODE_DLL_API __declspec(dllimport)</span>
+<a name="l00085"></a>00085 <span class="preprocessor"></span><span class="preprocessor">  #endif</span>
+<a name="l00086"></a>00086 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00087"></a>00087 <span class="preprocessor"></span>
+<a name="l00088"></a>00088 <span class="preprocessor">#if !defined(ODE_API)</span>
+<a name="l00089"></a>00089 <span class="preprocessor"></span><span class="preprocessor">  #define ODE_API</span>
+<a name="l00090"></a>00090 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00091"></a>00091 <span class="preprocessor"></span>
+<a name="l00092"></a>00092 
+<a name="l00093"></a>00093 <span class="comment">/* Pull in the standard headers */</span>
+<a name="l00094"></a>00094 <span class="preprocessor">#include &lt;stdio.h&gt;</span>
+<a name="l00095"></a>00095 <span class="preprocessor">#include &lt;stdlib.h&gt;</span>
+<a name="l00096"></a>00096 <span class="preprocessor">#include &lt;stdarg.h&gt;</span>
+<a name="l00097"></a>00097 <span class="preprocessor">#include &lt;math.h&gt;</span>
+<a name="l00098"></a>00098 <span class="preprocessor">#include &lt;string.h&gt;</span>
+<a name="l00099"></a>00099 <span class="preprocessor">#include &lt;float.h&gt;</span>
+<a name="l00100"></a>00100 
+<a name="l00101"></a>00101 <span class="preprocessor">#if !defined(ODE_PLATFORM_PS3)</span>
+<a name="l00102"></a>00102 <span class="preprocessor"></span><span class="preprocessor">  #include &lt;malloc.h&gt;</span>
+<a name="l00103"></a>00103 <span class="preprocessor">#endif</span>
+<a name="l00104"></a>00104 <span class="preprocessor"></span>
+<a name="l00105"></a>00105 <span class="preprocessor">#if !defined(ODE_PLATFORM_WINDOWS)</span>
+<a name="l00106"></a>00106 <span class="preprocessor"></span><span class="preprocessor">  #include &lt;alloca.h&gt;</span>
+<a name="l00107"></a>00107 <span class="preprocessor">#endif</span>
+<a name="l00108"></a>00108 <span class="preprocessor"></span>
+<a name="l00109"></a>00109 
+<a name="l00110"></a>00110 <span class="comment">/* Visual C does not define these functions */</span>
+<a name="l00111"></a>00111 <span class="preprocessor">#if defined(_MSC_VER)</span>
+<a name="l00112"></a>00112 <span class="preprocessor"></span><span class="preprocessor">  #define copysignf _copysign</span>
+<a name="l00113"></a>00113 <span class="preprocessor"></span><span class="preprocessor">  #define copysign _copysign</span>
+<a name="l00114"></a>00114 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00115"></a>00115 <span class="preprocessor"></span>
+<a name="l00116"></a>00116 
+<a name="l00117"></a>00117 <span class="comment">/* Define a value for infinity */</span>
+<a name="l00118"></a>00118 <span class="preprocessor">#if defined(HUGE_VALF)</span>
+<a name="l00119"></a>00119 <span class="preprocessor"></span><span class="preprocessor">   #define ODE_INFINITY4 HUGE_VALF</span>
+<a name="l00120"></a>00120 <span class="preprocessor"></span><span class="preprocessor">   #define ODE_INFINITY8 HUGE_VAL</span>
+<a name="l00121"></a>00121 <span class="preprocessor"></span><span class="preprocessor">#elif defined(FLT_MAX)</span>
+<a name="l00122"></a>00122 <span class="preprocessor"></span><span class="preprocessor">   #define ODE_INFINITY4 FLT_MAX</span>
+<a name="l00123"></a>00123 <span class="preprocessor"></span><span class="preprocessor">   #define ODE_INFINITY8 DBL_MAX</span>
+<a name="l00124"></a>00124 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00125"></a>00125 <span class="preprocessor"></span>   <span class="keyword">static</span> <span class="keyword">union </span>{ <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> __c[4]; <span class="keywordtype">float</span>  __f; }  __ode_huge_valf = {{0,0,0x80,0x7f}};
+<a name="l00126"></a>00126    <span class="keyword">static</span> <span class="keyword">union </span>{ <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> __c[8]; <span class="keywordtype">double</span> __d; }  __ode_huge_val  = {{0,0,0,0,0,0,0xf0,0x7f}};
+<a name="l00127"></a>00127 <span class="preprocessor">   #define ODE_INFINITY4 (__ode_huge_valf.__f)</span>
+<a name="l00128"></a>00128 <span class="preprocessor"></span><span class="preprocessor">   #define ODE_INFINITY8 (__ode_huge_val.__d)</span>
+<a name="l00129"></a>00129 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00130"></a>00130 <span class="preprocessor"></span>
+<a name="l00131"></a>00131 <span class="preprocessor">#ifdef dSINGLE</span>
+<a name="l00132"></a>00132 <span class="preprocessor"></span><span class="preprocessor">   #define dInfinity ODE_INFINITY4</span>
+<a name="l00133"></a>00133 <span class="preprocessor"></span><span class="preprocessor">   #define dEpsilon  FLT_EPSILON</span>
+<a name="l00134"></a>00134 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00135"></a>00135 <span class="preprocessor"></span><span class="preprocessor">   #define dInfinity ODE_INFINITY8</span>
+<a name="l00136"></a>00136 <span class="preprocessor"></span><span class="preprocessor">   #define dEpsilon  DBL_EPSILON</span>
+<a name="l00137"></a>00137 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00138"></a>00138 <span class="preprocessor"></span>
+<a name="l00139"></a>00139 
+<a name="l00140"></a>00140 <span class="comment">/* Well-defined common data types...need to define for 64 bit systems */</span>
+<a name="l00141"></a>00141 <span class="preprocessor">#if defined(_M_IA64) || defined(__ia64__) || defined(_M_AMD64) || defined(__x86_64__)</span>
+<a name="l00142"></a>00142 <span class="preprocessor"></span><span class="preprocessor">  #define X86_64_SYSTEM   1</span>
+<a name="l00143"></a>00143 <span class="preprocessor"></span>  <span class="keyword">typedef</span> <span class="keywordtype">int</span>             int32;
+<a name="l00144"></a>00144   <span class="keyword">typedef</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>    uint32;
+<a name="l00145"></a>00145   <span class="keyword">typedef</span> <span class="keywordtype">short</span>           int16;
+<a name="l00146"></a>00146   <span class="keyword">typedef</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span>  uint16;
+<a name="l00147"></a>00147   <span class="keyword">typedef</span> <span class="keywordtype">char</span>            int8;
+<a name="l00148"></a>00148   <span class="keyword">typedef</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span>   uint8;
+<a name="l00149"></a>00149 <span class="preprocessor">#else</span>
+<a name="l00150"></a>00150 <span class="preprocessor"></span>  <span class="keyword">typedef</span> <span class="keywordtype">int</span>             int32;
+<a name="l00151"></a>00151   <span class="keyword">typedef</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>    uint32;
+<a name="l00152"></a>00152   <span class="keyword">typedef</span> <span class="keywordtype">short</span>           int16;
+<a name="l00153"></a>00153   <span class="keyword">typedef</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span>  uint16;
+<a name="l00154"></a>00154   <span class="keyword">typedef</span> <span class="keywordtype">char</span>            int8;
+<a name="l00155"></a>00155   <span class="keyword">typedef</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span>   uint8;
+<a name="l00156"></a>00156 <span class="preprocessor">#endif</span>
+<a name="l00157"></a>00157 <span class="preprocessor"></span>
+<a name="l00158"></a>00158 <span class="comment">/* An integer type that can be safely cast to a pointer. This definition</span>
+<a name="l00159"></a>00159 <span class="comment"> * should be safe even on 64-bit systems */</span>
+<a name="l00160"></a>00160 <span class="keyword">typedef</span> <span class="keywordtype">size_t</span> intP;
+<a name="l00161"></a>00161 
+<a name="l00162"></a>00162 
+<a name="l00163"></a>00163 <span class="comment">/* The efficient alignment. most platforms align data structures to some</span>
+<a name="l00164"></a>00164 <span class="comment"> * number of bytes, but this is not always the most efficient alignment.</span>
+<a name="l00165"></a>00165 <span class="comment"> * for example, many x86 compilers align to 4 bytes, but on a pentium it is</span>
+<a name="l00166"></a>00166 <span class="comment"> * important to align doubles to 8 byte boundaries (for speed), and the 4</span>
+<a name="l00167"></a>00167 <span class="comment"> * floats in a SIMD register to 16 byte boundaries. many other platforms have</span>
+<a name="l00168"></a>00168 <span class="comment"> * similar behavior. setting a larger alignment can waste a (very) small</span>
+<a name="l00169"></a>00169 <span class="comment"> * amount of memory. NOTE: this number must be a power of two. */</span>
+<a name="l00170"></a>00170 <span class="preprocessor">#define EFFICIENT_ALIGNMENT 16</span>
+<a name="l00171"></a>00171 <span class="preprocessor"></span>
+<a name="l00172"></a>00172 
+<a name="l00173"></a>00173 <span class="comment">/* Define this if your system supports anonymous memory maps (linux does) */</span>
+<a name="l00174"></a>00174 <span class="preprocessor">#define MMAP_ANONYMOUS</span>
+<a name="l00175"></a>00175 <span class="preprocessor"></span>
+<a name="l00176"></a>00176 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/contact_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/contact_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/contact_8h-source.html	(revision 216)
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: contact.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>contact.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_CONTACT_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_CONTACT_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00030"></a>00030 <span class="preprocessor">#endif</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span>
+<a name="l00032"></a>00032 
+<a name="l00033"></a>00033 <span class="keyword">enum</span> {
+<a name="l00034"></a>00034   dContactMu2     = 0x001,
+<a name="l00035"></a>00035   dContactFDir1      = 0x002,
+<a name="l00036"></a>00036   dContactBounce  = 0x004,
+<a name="l00037"></a>00037   dContactSoftERP = 0x008,
+<a name="l00038"></a>00038   dContactSoftCFM = 0x010,
+<a name="l00039"></a>00039   dContactMotion1 = 0x020,
+<a name="l00040"></a>00040   dContactMotion2 = 0x040,
+<a name="l00041"></a>00041   dContactSlip1      = 0x080,
+<a name="l00042"></a>00042   dContactSlip2      = 0x100,
+<a name="l00043"></a>00043 
+<a name="l00044"></a>00044   dContactApprox0 = 0x0000,
+<a name="l00045"></a>00045   dContactApprox1_1  = 0x1000,
+<a name="l00046"></a>00046   dContactApprox1_2  = 0x2000,
+<a name="l00047"></a>00047   dContactApprox1 = 0x3000
+<a name="l00048"></a>00048 };
+<a name="l00049"></a>00049 
+<a name="l00050"></a>00050 
+<a name="l00051"></a>00051 <span class="keyword">typedef</span> <span class="keyword">struct </span>dSurfaceParameters {
+<a name="l00052"></a>00052   <span class="comment">/* must always be defined */</span>
+<a name="l00053"></a>00053   <span class="keywordtype">int</span> mode;
+<a name="l00054"></a>00054   dReal mu;
+<a name="l00055"></a>00055 
+<a name="l00056"></a>00056   <span class="comment">/* only defined if the corresponding flag is set in mode */</span>
+<a name="l00057"></a>00057   dReal mu2;
+<a name="l00058"></a>00058   dReal bounce;
+<a name="l00059"></a>00059   dReal bounce_vel;
+<a name="l00060"></a>00060   dReal soft_erp;
+<a name="l00061"></a>00061   dReal soft_cfm;
+<a name="l00062"></a>00062   dReal motion1,motion2;
+<a name="l00063"></a>00063   dReal slip1,slip2;
+<a name="l00064"></a>00064 } dSurfaceParameters;
+<a name="l00065"></a>00065 
+<a name="l00066"></a>00066 
+<a name="l00081"></a><a class="code" href="structd_contact_geom.html">00081</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> {
+<a name="l00082"></a><a class="code" href="structd_contact_geom.html#2fa7323ee3826d1f55c8cad6157e38a5">00082</a>   dVector3 <a class="code" href="structd_contact_geom.html#2fa7323ee3826d1f55c8cad6157e38a5" title="contact position">pos</a>;          
+<a name="l00083"></a><a class="code" href="structd_contact_geom.html#7665d3379904821bbdb7b7d1028fcda3">00083</a>   dVector3 <a class="code" href="structd_contact_geom.html#7665d3379904821bbdb7b7d1028fcda3" title="normal vector">normal</a>;       
+<a name="l00084"></a><a class="code" href="structd_contact_geom.html#29c32c1cb4355186d4110b7abeb58bf0">00084</a>   dReal <a class="code" href="structd_contact_geom.html#29c32c1cb4355186d4110b7abeb58bf0" title="penetration depth">depth</a>;           
+<a name="l00085"></a><a class="code" href="structd_contact_geom.html#7dd16e7bbc0c5b5e17116c1e5179281b">00085</a>   dGeomID g1,<a class="code" href="structd_contact_geom.html#7dd16e7bbc0c5b5e17116c1e5179281b" title="the colliding geoms">g2</a>;         
+<a name="l00086"></a><a class="code" href="structd_contact_geom.html#7a8a080b98c12e0d1f52c86d2738552e">00086</a>   <span class="keywordtype">int</span> side1,<a class="code" href="structd_contact_geom.html#7a8a080b98c12e0d1f52c86d2738552e" title="(to be documented)">side2</a>;       
+<a name="l00087"></a>00087 } <a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a>;
+<a name="l00088"></a>00088 
+<a name="l00089"></a>00089 
+<a name="l00090"></a>00090 <span class="comment">/* contact info used by contact joint */</span>
+<a name="l00091"></a>00091 
+<a name="l00092"></a>00092 <span class="keyword">typedef</span> <span class="keyword">struct </span>dContact {
+<a name="l00093"></a>00093   dSurfaceParameters surface;
+<a name="l00094"></a>00094   <a class="code" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> geom;
+<a name="l00095"></a>00095   dVector3 fdir1;
+<a name="l00096"></a>00096 } dContact;
+<a name="l00097"></a>00097 
+<a name="l00098"></a>00098 
+<a name="l00099"></a>00099 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00100"></a>00100 <span class="preprocessor"></span>}
+<a name="l00101"></a>00101 <span class="preprocessor">#endif</span>
+<a name="l00102"></a>00102 <span class="preprocessor"></span>
+<a name="l00103"></a>00103 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/doxygen.css
===================================================================
--- /code/branches/ode/ode-0.9/docs/doxygen.css	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/doxygen.css	(revision 216)
@@ -0,0 +1,358 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+	font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+       font-size: 90%;
+}
+H1 {
+	text-align: center;
+       font-size: 160%;
+}
+H2 {
+       font-size: 120%;
+}
+H3 {
+       font-size: 100%;
+}
+CAPTION { font-weight: bold }
+DIV.qindex {
+	width: 100%;
+	background-color: #e8eef2;
+	border: 1px solid #84b0c7;
+	text-align: center;
+	margin: 2px;
+	padding: 2px;
+	line-height: 140%;
+}
+DIV.nav {
+	width: 100%;
+	background-color: #e8eef2;
+	border: 1px solid #84b0c7;
+	text-align: center;
+	margin: 2px;
+	padding: 2px;
+	line-height: 140%;
+}
+DIV.navtab {
+       background-color: #e8eef2;
+       border: 1px solid #84b0c7;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+TD.navtab {
+       font-size: 70%;
+}
+A.qindex {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D;
+}
+A.qindex:visited {
+       text-decoration: none;
+       font-weight: bold;
+       color: #1A419D
+}
+A.qindex:hover {
+	text-decoration: none;
+	background-color: #ddddff;
+}
+A.qindexHL {
+	text-decoration: none;
+	font-weight: bold;
+	background-color: #6666cc;
+	color: #ffffff;
+	border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+	text-decoration: none;
+	background-color: #6666cc;
+	color: #ffffff;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { font-weight: normal; color: #0000FF}
+A.codeRef:visited { font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+.fragment {
+       font-family: monospace, fixed;
+       font-size: 95%;
+}
+PRE.fragment {
+	border: 1px solid #CCCCCC;
+	background-color: #f5f5f5;
+	margin-top: 4px;
+	margin-bottom: 4px;
+	margin-left: 2px;
+	margin-right: 8px;
+	padding-left: 6px;
+	padding-right: 6px;
+	padding-top: 4px;
+	padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+
+DIV.groupHeader {
+       margin-left: 16px;
+       margin-top: 12px;
+       margin-bottom: 6px;
+       font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
+BODY {
+	background: white;
+	color: black;
+	margin-right: 20px;
+	margin-left: 20px;
+}
+TD.indexkey {
+	background-color: #e8eef2;
+	font-weight: bold;
+	padding-right  : 10px;
+	padding-top    : 2px;
+	padding-left   : 10px;
+	padding-bottom : 2px;
+	margin-left    : 0px;
+	margin-right   : 0px;
+	margin-top     : 2px;
+	margin-bottom  : 2px;
+	border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+	background-color: #e8eef2;
+	font-style: italic;
+	padding-right  : 10px;
+	padding-top    : 2px;
+	padding-left   : 10px;
+	padding-bottom : 2px;
+	margin-left    : 0px;
+	margin-right   : 0px;
+	margin-top     : 2px;
+	margin-bottom  : 2px;
+	border: 1px solid #CCCCCC;
+}
+TR.memlist {
+   background-color: #f0f0f0; 
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword       { color: #008000 }
+SPAN.keywordtype   { color: #604020 }
+SPAN.keywordflow   { color: #e08000 }
+SPAN.comment       { color: #800000 }
+SPAN.preprocessor  { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral   { color: #008080 }
+.mdescLeft {
+       padding: 0px 8px 4px 8px;
+	font-size: 80%;
+	font-style: italic;
+	background-color: #FAFAFA;
+	border-top: 1px none #E0E0E0;
+	border-right: 1px none #E0E0E0;
+	border-bottom: 1px none #E0E0E0;
+	border-left: 1px none #E0E0E0;
+	margin: 0px;
+}
+.mdescRight {
+       padding: 0px 8px 4px 8px;
+	font-size: 80%;
+	font-style: italic;
+	background-color: #FAFAFA;
+	border-top: 1px none #E0E0E0;
+	border-right: 1px none #E0E0E0;
+	border-bottom: 1px none #E0E0E0;
+	border-left: 1px none #E0E0E0;
+	margin: 0px;
+}
+.memItemLeft {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-top-style: solid;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #FAFAFA;
+	font-size: 80%;
+}
+.memItemRight {
+	padding: 1px 8px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-top-style: solid;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #FAFAFA;
+	font-size: 80%;
+}
+.memTemplItemLeft {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-top-style: none;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #FAFAFA;
+	font-size: 80%;
+}
+.memTemplItemRight {
+	padding: 1px 8px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-top-style: none;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #FAFAFA;
+	font-size: 80%;
+}
+.memTemplParams {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-top-style: solid;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+       color: #606060;
+	background-color: #FAFAFA;
+	font-size: 80%;
+}
+.search     { color: #003399;
+              font-weight: bold;
+}
+FORM.search {
+              margin-bottom: 0px;
+              margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+               color: #000080;
+               font-weight: normal;
+               background-color: #e8eef2;
+}
+TD.tiny      { font-size: 75%;
+}
+a {
+	color: #1A41A8;
+}
+a:visited {
+	color: #2A3798;
+}
+.dirtab { padding: 4px;
+          border-collapse: collapse;
+          border: 1px solid #84b0c7;
+}
+TH.dirtab { background: #e8eef2;
+            font-weight: bold;
+}
+HR { height: 1px;
+     border: none;
+     border-top: 1px solid black;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+  font-size: 80%;
+  color: #606060;
+  font-weight: normal;
+} 
+.memnav { 
+  background-color: #e8eef2;
+  border: 1px solid #84b0c7;
+  text-align: center;
+  margin: 2px;
+  margin-right: 15px;
+  padding: 2px;
+}
+.memitem {
+  padding: 4px;
+  background-color: #eef3f5;
+  border-width: 1px;
+  border-style: solid;
+  border-color: #dedeee;
+  -moz-border-radius: 8px 8px 8px 8px;
+}
+.memname {
+  white-space: nowrap;
+  font-weight: bold;
+}
+.memdoc{
+  padding-left: 10px;
+}
+.memproto {
+  background-color: #d5e1e8;
+  width: 100%;
+  border-width: 1px;
+  border-style: solid;
+  border-color: #84b0c7;
+  font-weight: bold;
+  -moz-border-radius: 8px 8px 8px 8px;
+}
+.paramkey {
+  text-align: right;
+}
+.paramtype {
+  white-space: nowrap;
+}
+.paramname {
+  color: #602020;
+  font-style: italic;
+  white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+	font-family: sans-serif;
+	margin:0.5em;
+}
+.directory { font-size: 9pt; font-weight: bold; }
+.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
+.directory > h3 { margin-top: 0; }
+.directory p { margin: 0px; white-space: nowrap; }
+.directory div { display: none; margin: 0px; }
+.directory img { vertical-align: -30%; }
Index: /code/branches/ode/ode-0.9/docs/drawstuff_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/drawstuff_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/drawstuff_8h-source.html	(revision 216)
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: drawstuff.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>drawstuff.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00041"></a>00041 <span class="preprocessor">#ifndef __DRAWSTUFF_H__</span>
+<a name="l00042"></a>00042 <span class="preprocessor"></span><span class="preprocessor">#define __DRAWSTUFF_H__</span>
+<a name="l00043"></a>00043 <span class="preprocessor"></span>
+<a name="l00044"></a>00044 <span class="comment">/* Define a DLL export symbol for those platforms that need it */</span>
+<a name="l00045"></a>00045 <span class="preprocessor">#if defined(ODE_PLATFORM_WINDOWS)</span>
+<a name="l00046"></a>00046 <span class="preprocessor"></span><span class="preprocessor">  #if defined(DS_DLL)</span>
+<a name="l00047"></a>00047 <span class="preprocessor"></span><span class="preprocessor">    #define DS_API __declspec(dllexport)</span>
+<a name="l00048"></a>00048 <span class="preprocessor"></span><span class="preprocessor">  #elif !defined(DS_LIB)</span>
+<a name="l00049"></a>00049 <span class="preprocessor"></span><span class="preprocessor">    #define DS_DLL_API __declspec(dllimport)</span>
+<a name="l00050"></a>00050 <span class="preprocessor"></span><span class="preprocessor">  #endif</span>
+<a name="l00051"></a>00051 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00052"></a>00052 <span class="preprocessor"></span>    
+<a name="l00053"></a>00053 <span class="preprocessor">#if !defined(DS_API)</span>
+<a name="l00054"></a>00054 <span class="preprocessor"></span><span class="preprocessor">  #define DS_API</span>
+<a name="l00055"></a>00055 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00056"></a>00056 <span class="preprocessor"></span>
+<a name="l00057"></a>00057 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00058"></a>00058 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00059"></a>00059 <span class="preprocessor">#endif</span>
+<a name="l00060"></a>00060 <span class="preprocessor"></span>
+<a name="l00061"></a>00061 
+<a name="l00062"></a>00062 <span class="preprocessor">#include &lt;drawstuff/version.h&gt;</span>
+<a name="l00063"></a>00063 
+<a name="l00064"></a>00064 
+<a name="l00065"></a>00065 <span class="comment">/* texture numbers */</span>
+<a name="l00066"></a>00066 <span class="preprocessor">#define DS_NONE   0  </span><span class="comment">/* uses the current color instead of a texture */</span>
+<a name="l00067"></a>00067 <span class="preprocessor">#define DS_WOOD   1</span>
+<a name="l00068"></a>00068 <span class="preprocessor"></span>
+<a name="l00069"></a>00069 
+<a name="l00075"></a><a class="code" href="structds_functions.html">00075</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structds_functions.html" title="Set of functions to be used as callbacks by the simulation loop.">dsFunctions</a> {
+<a name="l00076"></a>00076   <span class="keywordtype">int</span> version;       <span class="comment">/* put DS_VERSION here */</span>
+<a name="l00077"></a>00077   <span class="comment">/* version 1 data */</span>
+<a name="l00078"></a>00078   void (*start)();      <span class="comment">/* called before sim loop starts */</span>
+<a name="l00079"></a>00079   void (*step) (<span class="keywordtype">int</span> pause);   <span class="comment">/* called before every frame */</span>
+<a name="l00080"></a>00080   void (*command) (<span class="keywordtype">int</span> cmd);  <span class="comment">/* called if a command key is pressed */</span>
+<a name="l00081"></a>00081   void (*stop)();    <span class="comment">/* called after sim loop exits */</span>
+<a name="l00082"></a>00082   <span class="comment">/* version 2 data */</span>
+<a name="l00083"></a>00083   <span class="keywordtype">char</span> *path_to_textures;  <span class="comment">/* if nonzero, path to texture files */</span>
+<a name="l00084"></a>00084 } <a class="code" href="structds_functions.html" title="Set of functions to be used as callbacks by the simulation loop.">dsFunctions</a>;
+<a name="l00085"></a>00085 
+<a name="l00086"></a>00086 
+<a name="l00095"></a>00095 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g28560ea1b64c1d83095bcdfce9caf9dc" title="Does the complete simulation.">dsSimulationLoop</a> (<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv,
+<a name="l00096"></a>00096              <span class="keywordtype">int</span> window_width, <span class="keywordtype">int</span> window_height,
+<a name="l00097"></a>00097              <span class="keyword">struct</span> <a class="code" href="structds_functions.html" title="Set of functions to be used as callbacks by the simulation loop.">dsFunctions</a> *fn);
+<a name="l00098"></a>00098 
+<a name="l00105"></a>00105 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g7a2a69ac611d5dc6ffc8e43b0a743472" title="exit with error message.">dsError</a> (<span class="keywordtype">char</span> *msg, ...);
+<a name="l00106"></a>00106 
+<a name="l00113"></a>00113 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#ga84175b14c3c31daae08a9c88acc2b02" title="exit with error message and core dump.">dsDebug</a> (<span class="keywordtype">char</span> *msg, ...);
+<a name="l00114"></a>00114 
+<a name="l00120"></a>00120 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#gbca5fa4076aa9e45caa049f33e8cf168" title="print log message">dsPrint</a> (<span class="keywordtype">char</span> *msg, ...);
+<a name="l00121"></a>00121 
+<a name="l00130"></a>00130 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g8e4ea933c31d207ec57949fbb3a75815" title="Sets the viewpoint.">dsSetViewpoint</a> (<span class="keywordtype">float</span> xyz[3], <span class="keywordtype">float</span> hpr[3]);
+<a name="l00131"></a>00131 
+<a name="l00132"></a>00132 
+<a name="l00139"></a>00139 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#gaa22f45ad00e0010a1440985ac51b18b" title="Gets the viewpoint.">dsGetViewpoint</a> (<span class="keywordtype">float</span> xyz[3], <span class="keywordtype">float</span> hpr[3]);
+<a name="l00140"></a>00140 
+<a name="l00149"></a>00149 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g6c13a5a310b9e00c45150058e669ebad" title="Stop the simulation loop.">dsStop</a>();
+<a name="l00150"></a>00150 
+<a name="l00156"></a>00156 DS_API <span class="keywordtype">double</span> <a class="code" href="group__drawstuff.html#g02f3f096703d49f5a9e497aec0b85f75" title="Get the elapsed time (on wall-clock).">dsElapsedTime</a>();
+<a name="l00157"></a>00157 
+<a name="l00168"></a>00168 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g8a3d6f8fecc8c7d5a206bed35f17ba7a" title="Toggle the rendering of textures.">dsSetTexture</a> (<span class="keywordtype">int</span> texture_number);
+<a name="l00169"></a>00169 
+<a name="l00177"></a>00177 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g3221a0d1360621eaad7c54597671c092" title="Set the color with which geometry is drawn.">dsSetColor</a> (<span class="keywordtype">float</span> red, <span class="keywordtype">float</span> green, <span class="keywordtype">float</span> blue);
+<a name="l00178"></a>00178 
+<a name="l00185"></a>00185 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g440940cfaef61775e37c33b055b832af" title="Set the color and transparency with which geometry is drawn.">dsSetColorAlpha</a> (<span class="keywordtype">float</span> red, <span class="keywordtype">float</span> green, <span class="keywordtype">float</span> blue, <span class="keywordtype">float</span> alpha);
+<a name="l00186"></a>00186 
+<a name="l00197"></a>00197 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#gfba4fde6b0b74f6cd422036dedd08836" title="Draw a box.">dsDrawBox</a> (<span class="keyword">const</span> <span class="keywordtype">float</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">float</span> R[12], <span class="keyword">const</span> <span class="keywordtype">float</span> sides[3]);
+<a name="l00198"></a>00198 
+<a name="l00206"></a>00206 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g0802e7641f8028182b69fabc729a6704" title="Draw a sphere.">dsDrawSphere</a> (<span class="keyword">const</span> <span class="keywordtype">float</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">float</span> R[12], <span class="keywordtype">float</span> radius);
+<a name="l00207"></a>00207 
+<a name="l00218"></a>00218 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#gcfcbae15cee67eceb45cd96bf01484d4" title="Draw a triangle.">dsDrawTriangle</a> (<span class="keyword">const</span> <span class="keywordtype">float</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">float</span> R[12],
+<a name="l00219"></a>00219            <span class="keyword">const</span> <span class="keywordtype">float</span> *v0, <span class="keyword">const</span> <span class="keywordtype">float</span> *v1, <span class="keyword">const</span> <span class="keywordtype">float</span> *v2, <span class="keywordtype">int</span> solid);
+<a name="l00220"></a>00220 
+<a name="l00225"></a>00225 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g0b09b41f1f6500b293678aa1691f1537" title="Draw a z-aligned cylinder.">dsDrawCylinder</a> (<span class="keyword">const</span> <span class="keywordtype">float</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">float</span> R[12],
+<a name="l00226"></a>00226            <span class="keywordtype">float</span> length, <span class="keywordtype">float</span> radius);
+<a name="l00227"></a>00227 
+<a name="l00232"></a>00232 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#gce8f6c8a9f2871dac2f5e7f159b96feb" title="Draw a z-aligned capsule.">dsDrawCapsule</a> (<span class="keyword">const</span> <span class="keywordtype">float</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">float</span> R[12],
+<a name="l00233"></a>00233           <span class="keywordtype">float</span> length, <span class="keywordtype">float</span> radius);
+<a name="l00234"></a>00234 
+<a name="l00239"></a>00239 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g61b166a9b7c04063a27be982051f4af5" title="Draw a line.">dsDrawLine</a> (<span class="keyword">const</span> <span class="keywordtype">float</span> pos1[3], <span class="keyword">const</span> <span class="keywordtype">float</span> pos2[3]);
+<a name="l00240"></a>00240 
+<a name="l00245"></a>00245 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g4b8754994a4cca9d51fce16445f0d612" title="Draw a convex shape.">dsDrawConvex</a>(<span class="keyword">const</span> <span class="keywordtype">float</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">float</span> R[12],
+<a name="l00246"></a>00246         <span class="keywordtype">float</span> *_planes,
+<a name="l00247"></a>00247         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _planecount,
+<a name="l00248"></a>00248         <span class="keywordtype">float</span> *_points,
+<a name="l00249"></a>00249         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _pointcount,
+<a name="l00250"></a>00250         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> *_polygons);
+<a name="l00251"></a>00251 
+<a name="l00252"></a>00252  <span class="comment">/* these drawing functions are identical to the ones above, except they take</span>
+<a name="l00253"></a>00253 <span class="comment"> * double arrays for `pos' and `R'.</span>
+<a name="l00254"></a>00254 <span class="comment"> */</span>
+<a name="l00255"></a>00255 DS_API <span class="keywordtype">void</span> dsDrawBoxD (<span class="keyword">const</span> <span class="keywordtype">double</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">double</span> R[12],
+<a name="l00256"></a>00256        <span class="keyword">const</span> <span class="keywordtype">double</span> sides[3]);
+<a name="l00257"></a>00257 DS_API <span class="keywordtype">void</span> dsDrawSphereD (<span class="keyword">const</span> <span class="keywordtype">double</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">double</span> R[12],
+<a name="l00258"></a>00258           <span class="keyword">const</span> <span class="keywordtype">float</span> radius);
+<a name="l00259"></a>00259 DS_API <span class="keywordtype">void</span> dsDrawTriangleD (<span class="keyword">const</span> <span class="keywordtype">double</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">double</span> R[12],
+<a name="l00260"></a>00260             <span class="keyword">const</span> <span class="keywordtype">double</span> *v0, <span class="keyword">const</span> <span class="keywordtype">double</span> *v1, <span class="keyword">const</span> <span class="keywordtype">double</span> *v2, <span class="keywordtype">int</span> solid);
+<a name="l00261"></a>00261 DS_API <span class="keywordtype">void</span> dsDrawCylinderD (<span class="keyword">const</span> <span class="keywordtype">double</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">double</span> R[12],
+<a name="l00262"></a>00262             <span class="keywordtype">float</span> length, <span class="keywordtype">float</span> radius);
+<a name="l00263"></a>00263 DS_API <span class="keywordtype">void</span> dsDrawCapsuleD (<span class="keyword">const</span> <span class="keywordtype">double</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">double</span> R[12],
+<a name="l00264"></a>00264            <span class="keywordtype">float</span> length, <span class="keywordtype">float</span> radius);
+<a name="l00265"></a>00265 DS_API <span class="keywordtype">void</span> dsDrawLineD (<span class="keyword">const</span> <span class="keywordtype">double</span> pos1[3], <span class="keyword">const</span> <span class="keywordtype">double</span> pos2[3]);
+<a name="l00266"></a>00266 DS_API <span class="keywordtype">void</span> dsDrawConvexD(<span class="keyword">const</span> <span class="keywordtype">double</span> pos[3], <span class="keyword">const</span> <span class="keywordtype">double</span> R[12],
+<a name="l00267"></a>00267         <span class="keywordtype">double</span> *_planes,
+<a name="l00268"></a>00268         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _planecount,
+<a name="l00269"></a>00269         <span class="keywordtype">double</span> *_points,
+<a name="l00270"></a>00270         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> _pointcount,
+<a name="l00271"></a>00271         <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> *_polygons);
+<a name="l00272"></a>00272 
+<a name="l00280"></a>00280 DS_API <span class="keywordtype">void</span> <a class="code" href="group__drawstuff.html#g211aa83d5c5d102cdda303cc7aeb2fd5" title="Set the quality with which curved objects are rendered.">dsSetSphereQuality</a> (<span class="keywordtype">int</span> n);      <span class="comment">/* default = 1 */</span>
+<a name="l00281"></a>00281 DS_API <span class="keywordtype">void</span> dsSetCapsuleQuality (<span class="keywordtype">int</span> n);     <span class="comment">/* default = 3 */</span>
+<a name="l00282"></a>00282 
+<a name="l00283"></a>00283 <span class="comment">// Backwards compatible API</span>
+<a name="l00284"></a>00284 <span class="preprocessor">#define dsDrawCappedCylinder dsDrawCapsule</span>
+<a name="l00285"></a>00285 <span class="preprocessor"></span><span class="preprocessor">#define dsDrawCappedCylinderD dsDrawCapsuleD</span>
+<a name="l00286"></a>00286 <span class="preprocessor"></span><span class="preprocessor">#define dsSetCappedCylinderQuality dsSetCapsuleQuality</span>
+<a name="l00287"></a>00287 <span class="preprocessor"></span>
+<a name="l00288"></a>00288 <span class="comment">/* closing bracket for extern "C" */</span>
+<a name="l00289"></a>00289 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00290"></a>00290 <span class="preprocessor"></span>}
+<a name="l00291"></a>00291 <span class="preprocessor">#endif</span>
+<a name="l00292"></a>00292 <span class="preprocessor"></span>
+<a name="l00293"></a>00293 <span class="preprocessor">#endif</span>
+<a name="l00294"></a>00294 <span class="preprocessor"></span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/error_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/error_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/error_8h-source.html	(revision 216)
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: error.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>error.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/* this comes from the `reuse' library. copy any changes back to the source */</span>
+<a name="l00024"></a>00024 
+<a name="l00025"></a>00025 <span class="preprocessor">#ifndef _ODE_ERROR_H_</span>
+<a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_ERROR_H_</span>
+<a name="l00027"></a>00027 <span class="preprocessor"></span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;ode/config.h&gt;</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00032"></a>00032 <span class="preprocessor">#endif</span>
+<a name="l00033"></a>00033 <span class="preprocessor"></span>
+<a name="l00034"></a>00034 <span class="comment">/* all user defined error functions have this type. error and debug functions</span>
+<a name="l00035"></a>00035 <span class="comment"> * should not return.</span>
+<a name="l00036"></a>00036 <span class="comment"> */</span>
+<a name="l00037"></a>00037 <span class="keyword">typedef</span> <span class="keywordtype">void</span> dMessageFunction (<span class="keywordtype">int</span> errnum, <span class="keyword">const</span> <span class="keywordtype">char</span> *msg, va_list ap);
+<a name="l00038"></a>00038 
+<a name="l00039"></a>00039 <span class="comment">/* set a new error, debug or warning handler. if fn is 0, the default handlers</span>
+<a name="l00040"></a>00040 <span class="comment"> * are used.</span>
+<a name="l00041"></a>00041 <span class="comment"> */</span>
+<a name="l00042"></a>00042 ODE_API <span class="keywordtype">void</span> dSetErrorHandler (dMessageFunction *fn);
+<a name="l00043"></a>00043 ODE_API <span class="keywordtype">void</span> dSetDebugHandler (dMessageFunction *fn);
+<a name="l00044"></a>00044 ODE_API <span class="keywordtype">void</span> dSetMessageHandler (dMessageFunction *fn);
+<a name="l00045"></a>00045 
+<a name="l00046"></a>00046 <span class="comment">/* return the current error, debug or warning handler. if the return value is</span>
+<a name="l00047"></a>00047 <span class="comment"> * 0, the default handlers are in place.</span>
+<a name="l00048"></a>00048 <span class="comment"> */</span>
+<a name="l00049"></a>00049 ODE_API dMessageFunction *dGetErrorHandler(<span class="keywordtype">void</span>);
+<a name="l00050"></a>00050 ODE_API dMessageFunction *dGetDebugHandler(<span class="keywordtype">void</span>);
+<a name="l00051"></a>00051 ODE_API dMessageFunction *dGetMessageHandler(<span class="keywordtype">void</span>);
+<a name="l00052"></a>00052 
+<a name="l00053"></a>00053 <span class="comment">/* generate a fatal error, debug trap or a message. */</span>
+<a name="l00054"></a>00054 ODE_API <span class="keywordtype">void</span> dError (<span class="keywordtype">int</span> num, <span class="keyword">const</span> <span class="keywordtype">char</span> *msg, ...);
+<a name="l00055"></a>00055 ODE_API <span class="keywordtype">void</span> dDebug (<span class="keywordtype">int</span> num, <span class="keyword">const</span> <span class="keywordtype">char</span> *msg, ...);
+<a name="l00056"></a>00056 ODE_API <span class="keywordtype">void</span> dMessage (<span class="keywordtype">int</span> num, <span class="keyword">const</span> <span class="keywordtype">char</span> *msg, ...);
+<a name="l00057"></a>00057 
+<a name="l00058"></a>00058 
+<a name="l00059"></a>00059 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00060"></a>00060 <span class="preprocessor"></span>}
+<a name="l00061"></a>00061 <span class="preprocessor">#endif</span>
+<a name="l00062"></a>00062 <span class="preprocessor"></span>
+<a name="l00063"></a>00063 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/export-dif_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/export-dif_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/export-dif_8h-source.html	(revision 216)
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: export-dif.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>export-dif.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_EXPORT_DIF_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_EXPORT_DIF_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 
+<a name="l00029"></a>00029 ODE_API <span class="keywordtype">void</span> dWorldExportDIF (dWorldID w, FILE *file, <span class="keyword">const</span> <span class="keywordtype">char</span> *world_name);
+<a name="l00030"></a>00030 
+<a name="l00031"></a>00031 
+<a name="l00032"></a>00032 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/files.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/files.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/files.html	(revision 216)
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: File Index</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Open Dynamics Engine File List</h1>Here is a list of all documented files with brief descriptions:<table>
+  <tr><td class="indexkey"><b>collision.h</b> <a href="collision_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>collision_space.h</b> <a href="collision__space_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>collision_trimesh.h</b> <a href="collision__trimesh_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>common.h</b> <a href="common_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>compatibility.h</b> <a href="compatibility_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>config.h</b> <a href="config_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>contact.h</b> <a href="contact_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>drawstuff.h</b> <a href="drawstuff_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>error.h</b> <a href="error_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>export-dif.h</b> <a href="export-dif_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>mass.h</b> <a href="mass_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>matrix.h</b> <a href="matrix_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>memory.h</b> <a href="memory_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>misc.h</b> <a href="misc_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>objects.h</b> <a href="objects_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>ode.h</b> <a href="ode_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>odecpp.h</b> <a href="odecpp_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>odecpp_collision.h</b> <a href="odecpp__collision_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>odemath.h</b> <a href="odemath_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>rotation.h</b> <a href="rotation_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>timer.h</b> <a href="timer_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+  <tr><td class="indexkey"><b>version.h</b> <a href="version_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+</table>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/functions.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/functions.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/functions.html	(revision 216)
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Data Fields</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li class="current"><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="functions.html"><span>Data&nbsp;Fields</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li class="current"><a href="functions.html"><span>All</span></a></li>
+    <li><a href="functions_vars.html"><span>Variables</span></a></li>
+  </ul>
+</div>
+Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:
+<p>
+<ul>
+<li>depth
+: <a class="el" href="structd_contact_geom.html#29c32c1cb4355186d4110b7abeb58bf0">dContactGeom</a>
+<li>g2
+: <a class="el" href="structd_contact_geom.html#7dd16e7bbc0c5b5e17116c1e5179281b">dContactGeom</a>
+<li>normal
+: <a class="el" href="structd_contact_geom.html#7665d3379904821bbdb7b7d1028fcda3">dContactGeom</a>
+<li>pos
+: <a class="el" href="structd_contact_geom.html#2fa7323ee3826d1f55c8cad6157e38a5">dContactGeom</a>
+<li>side2
+: <a class="el" href="structd_contact_geom.html#7a8a080b98c12e0d1f52c86d2738552e">dContactGeom</a>
+</ul>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/functions_vars.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/functions_vars.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/functions_vars.html	(revision 216)
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Data Fields - Variables</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li class="current"><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="functions.html"><span>Data&nbsp;Fields</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li><a href="functions.html"><span>All</span></a></li>
+    <li class="current"><a href="functions_vars.html"><span>Variables</span></a></li>
+  </ul>
+</div>
+&nbsp;
+<p>
+<ul>
+<li>depth
+: <a class="el" href="structd_contact_geom.html#29c32c1cb4355186d4110b7abeb58bf0">dContactGeom</a>
+<li>g2
+: <a class="el" href="structd_contact_geom.html#7dd16e7bbc0c5b5e17116c1e5179281b">dContactGeom</a>
+<li>normal
+: <a class="el" href="structd_contact_geom.html#7665d3379904821bbdb7b7d1028fcda3">dContactGeom</a>
+<li>pos
+: <a class="el" href="structd_contact_geom.html#2fa7323ee3826d1f55c8cad6157e38a5">dContactGeom</a>
+<li>side2
+: <a class="el" href="structd_contact_geom.html#7a8a080b98c12e0d1f52c86d2738552e">dContactGeom</a>
+</ul>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__bodies.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__bodies.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__bodies.html	(revision 216)
@@ -0,0 +1,1827 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Rigid Bodies</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Rigid Bodies</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g57c1e1b1bd50fdcafc5140c1ed89c7d7">dBodyGetAutoDisableLinearThreshold</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable linear average threshold.  <a href="#g57c1e1b1bd50fdcafc5140c1ed89c7d7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gb8f6e736830cfea86c35e7a0cdfa3112">dBodySetAutoDisableLinearThreshold</a> (dBodyID, dReal linear_average_threshold)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable linear average threshold.  <a href="#gb8f6e736830cfea86c35e7a0cdfa3112"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g5b988719423e9bc3af1be2146872e2d6">dBodyGetAutoDisableAngularThreshold</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable angular average threshold.  <a href="#g5b988719423e9bc3af1be2146872e2d6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g206ccf22f027a62aaf5e45a16ddc4040">dBodySetAutoDisableAngularThreshold</a> (dBodyID, dReal angular_average_threshold)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable angular average threshold.  <a href="#g206ccf22f027a62aaf5e45a16ddc4040"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gf398254a02ab5bedcdf7e4fb2918a902">dBodyGetAutoDisableAverageSamplesCount</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable average size (samples count).  <a href="#gf398254a02ab5bedcdf7e4fb2918a902"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g4bce13aaa5ffb7d4b3452191974c3be6">dBodySetAutoDisableAverageSamplesCount</a> (dBodyID, unsigned int average_samples_count)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable average buffer size (average steps).  <a href="#g4bce13aaa5ffb7d4b3452191974c3be6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g797ad84c737a2ae4ef3f8a37dfa02183">dBodyGetAutoDisableSteps</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto steps a body must be thought of as idle to disable.  <a href="#g797ad84c737a2ae4ef3f8a37dfa02183"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g03cc329bdc8e19e59c4bfe62cf736578">dBodySetAutoDisableSteps</a> (dBodyID, int steps)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable steps.  <a href="#g03cc329bdc8e19e59c4bfe62cf736578"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ga2f4d01a8fb5c4d7e77efd5f0e4dd72b">dBodyGetAutoDisableTime</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable time.  <a href="#ga2f4d01a8fb5c4d7e77efd5f0e4dd72b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g0ae2f08bb38359934151f9420cdef341">dBodySetAutoDisableTime</a> (dBodyID, dReal time)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable time.  <a href="#g0ae2f08bb38359934151f9420cdef341"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gfe44b3ae620abb1091472089cb07f64e">dBodyGetAutoDisableFlag</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable flag.  <a href="#gfe44b3ae620abb1091472089cb07f64e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ge352fdcd8851224f07da53f35691ceb7">dBodySetAutoDisableFlag</a> (dBodyID, int do_auto_disable)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable flag.  <a href="#ge352fdcd8851224f07da53f35691ceb7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g00969db4aebc2e8629cd9c45f3b7385e">dBodySetAutoDisableDefaults</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable defaults.  <a href="#g00969db4aebc2e8629cd9c45f3b7385e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dWorldID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gb044b0a466f2ec2af3fd29ae399e822e">dBodyGetWorld</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Retrives the world attached to te given body.  <a href="#gb044b0a466f2ec2af3fd29ae399e822e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dBodyID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g578137bbaf82d4b8896d2baee3a032a6">dBodyCreate</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a body in given world.  <a href="#g578137bbaf82d4b8896d2baee3a032a6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gc1a0ee96898f14017a29b2afa0eafe13">dBodyDestroy</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Destroy a body.  <a href="#gc1a0ee96898f14017a29b2afa0eafe13"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gf9cbe9e1ed1bd4559bb5603b8d0f92f2">dBodySetData</a> (dBodyID, void *data)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the body's user-data pointer.  <a href="#gf9cbe9e1ed1bd4559bb5603b8d0f92f2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g68d3d80c7476776dd4512d577bf70325">dBodyGetData</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the body's user-data pointer.  <a href="#g68d3d80c7476776dd4512d577bf70325"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gb84612b793366f18ff5b5cbdbed092da">dBodySetPosition</a> (dBodyID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set position of a body.  <a href="#gb84612b793366f18ff5b5cbdbed092da"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gb5f04968ec37ef46d2aaffad6c344468">dBodySetRotation</a> (dBodyID, const dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the orientation of a body.  <a href="#gb5f04968ec37ef46d2aaffad6c344468"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ga5f51dd3605c402320e9eae4231d7ad4">dBodySetQuaternion</a> (dBodyID, const dQuaternion q)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the orientation of a body.  <a href="#ga5f51dd3605c402320e9eae4231d7ad4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gafe72e03c1df0f2150e2d7b8677e1460"></a><!-- doxytag: member="bodies::dBodySetLinearVel" ref="gafe72e03c1df0f2150e2d7b8677e1460" args="(dBodyID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gafe72e03c1df0f2150e2d7b8677e1460">dBodySetLinearVel</a> (dBodyID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the linear velocity of a body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g7b4f90c1986333395375c086c4f3ec41"></a><!-- doxytag: member="bodies::dBodySetAngularVel" ref="g7b4f90c1986333395375c086c4f3ec41" args="(dBodyID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g7b4f90c1986333395375c086c4f3ec41">dBodySetAngularVel</a> (dBodyID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the angular velocity of a body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g2bddae29591b9f14c5175411b783d570">dBodyGetPosition</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the position of a body.  <a href="#g2bddae29591b9f14c5175411b783d570"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gf69c1ebd1c8d7d165fe740c9f1146217">dBodyCopyPosition</a> (dBodyID body, dVector3 pos)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Copy the position of a body into a vector.  <a href="#gf69c1ebd1c8d7d165fe740c9f1146217"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g2374da7ff88a2bac607e2fbce529ad27">dBodyGetRotation</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the rotation of a body.  <a href="#g2374da7ff88a2bac607e2fbce529ad27"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ga992006681bc720c6c6ef644768226e5">dBodyCopyRotation</a> (dBodyID, dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Copy the rotation of a body.  <a href="#ga992006681bc720c6c6ef644768226e5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g36b7e19622ed47fe6b9dcfbac20237e7">dBodyGetQuaternion</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the rotation of a body.  <a href="#g36b7e19622ed47fe6b9dcfbac20237e7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gd906c3ad061b7f70d1c60d6957aa2d0f">dBodyCopyQuaternion</a> (dBodyID body, dQuaternion quat)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Copy the orientation of a body into a quaternion.  <a href="#gd906c3ad061b7f70d1c60d6957aa2d0f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g2a0a986c12d53efd5a3753dd4b509cac"></a><!-- doxytag: member="bodies::dBodyGetLinearVel" ref="g2a0a986c12d53efd5a3753dd4b509cac" args="(dBodyID)" -->
+ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g2a0a986c12d53efd5a3753dd4b509cac">dBodyGetLinearVel</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the linear velocity of a body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g54dc73be9562cdece52d0a7d8decd1d0"></a><!-- doxytag: member="bodies::dBodyGetAngularVel" ref="g54dc73be9562cdece52d0a7d8decd1d0" args="(dBodyID)" -->
+ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g54dc73be9562cdece52d0a7d8decd1d0">dBodyGetAngularVel</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the angular velocity of a body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gf3609b58548e34471ef8ad4727b33e52"></a><!-- doxytag: member="bodies::dBodySetMass" ref="gf3609b58548e34471ef8ad4727b33e52" args="(dBodyID, const dMass *mass)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gf3609b58548e34471ef8ad4727b33e52">dBodySetMass</a> (dBodyID, const dMass *mass)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the mass of a body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g7aa7944f6e36a96d3e578f3369ac4171"></a><!-- doxytag: member="bodies::dBodyGetMass" ref="g7aa7944f6e36a96d3e578f3369ac4171" args="(dBodyID, dMass *mass)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g7aa7944f6e36a96d3e578f3369ac4171">dBodyGetMass</a> (dBodyID, dMass *mass)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the mass of a body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1e1352dc350ad42bff5818f2200ba792"></a><!-- doxytag: member="bodies::dBodyAddForce" ref="g1e1352dc350ad42bff5818f2200ba792" args="(dBodyID, dReal fx, dReal fy, dReal fz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g1e1352dc350ad42bff5818f2200ba792">dBodyAddForce</a> (dBodyID, dReal fx, dReal fy, dReal fz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add force at centre of mass of body in absolute coordinates. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g8378560dd168ee8d7a4b74e3de510ebc"></a><!-- doxytag: member="bodies::dBodyAddTorque" ref="g8378560dd168ee8d7a4b74e3de510ebc" args="(dBodyID, dReal fx, dReal fy, dReal fz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc">dBodyAddTorque</a> (dBodyID, dReal fx, dReal fy, dReal fz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add torque at centre of mass of body in absolute coordinates. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g0a91e5416c5af7729177c465346837ad"></a><!-- doxytag: member="bodies::dBodyAddRelForce" ref="g0a91e5416c5af7729177c465346837ad" args="(dBodyID, dReal fx, dReal fy, dReal fz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g0a91e5416c5af7729177c465346837ad">dBodyAddRelForce</a> (dBodyID, dReal fx, dReal fy, dReal fz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add force at centre of mass of body in coordinates relative to body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g172a59e64f6dfa4a59bcd45b694585de"></a><!-- doxytag: member="bodies::dBodyAddRelTorque" ref="g172a59e64f6dfa4a59bcd45b694585de" args="(dBodyID, dReal fx, dReal fy, dReal fz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g172a59e64f6dfa4a59bcd45b694585de">dBodyAddRelTorque</a> (dBodyID, dReal fx, dReal fy, dReal fz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add torque at centre of mass of body in coordinates relative to body. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gfa134c6b7b455680b890b677c5789c2b"></a><!-- doxytag: member="bodies::dBodyAddForceAtPos" ref="gfa134c6b7b455680b890b677c5789c2b" args="(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gfa134c6b7b455680b890b677c5789c2b">dBodyAddForceAtPos</a> (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add force at specified point in body in global coordinates. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g77606cdb23029337a7ed43dee5a59ee1"></a><!-- doxytag: member="bodies::dBodyAddForceAtRelPos" ref="g77606cdb23029337a7ed43dee5a59ee1" args="(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g77606cdb23029337a7ed43dee5a59ee1">dBodyAddForceAtRelPos</a> (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add force at specified point in body in local coordinates. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga024b08f8dfb85705b86e18b99a0ef8e"></a><!-- doxytag: member="bodies::dBodyAddRelForceAtPos" ref="ga024b08f8dfb85705b86e18b99a0ef8e" args="(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ga024b08f8dfb85705b86e18b99a0ef8e">dBodyAddRelForceAtPos</a> (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add force at specified point in body in global coordinates. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g7e5d20b6bb36f74d0dedb08f5eefddcb"></a><!-- doxytag: member="bodies::dBodyAddRelForceAtRelPos" ref="g7e5d20b6bb36f74d0dedb08f5eefddcb" args="(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g7e5d20b6bb36f74d0dedb08f5eefddcb">dBodyAddRelForceAtRelPos</a> (dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Add force at specified point in body in local coordinates. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g3b458397a79f09b1957cb6e5a85e9eba">dBodyGetForce</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Return the current accumulated force vector.  <a href="#g3b458397a79f09b1957cb6e5a85e9eba"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gfe88a5bc363fc812c8f154e3d5f8ea5d">dBodyGetTorque</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Return the current accumulated torque vector.  <a href="#gfe88a5bc363fc812c8f154e3d5f8ea5d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gbd56079db36d4562db0e18aebea4f95f">dBodySetForce</a> (dBodyID b, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the body force accumulation vector.  <a href="#gbd56079db36d4562db0e18aebea4f95f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gfcd3e44223a878ba52428ad3a124fa94">dBodySetTorque</a> (dBodyID b, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the body torque accumulation vector.  <a href="#gfcd3e44223a878ba52428ad3a124fa94"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gfcf00cd9c4c754c82189fb9d1eb9f102">dBodyGetRelPointPos</a> (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get world position of a relative point on body.  <a href="#gfcf00cd9c4c754c82189fb9d1eb9f102"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g7fd4f4c7e70c59380da11277b2e97510">dBodyGetRelPointVel</a> (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get velocity vector in global coords of a relative point on body.  <a href="#g7fd4f4c7e70c59380da11277b2e97510"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g89dd6a4a3c6f3cd98c8377e8d4dec015">dBodyGetPointVel</a> (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get velocity vector in global coords of a globally specified point on a body.  <a href="#g89dd6a4a3c6f3cd98c8377e8d4dec015"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g0334d9d523cbfeec742ac4a814834199">dBodyGetPosRelPoint</a> (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">takes a point in global coordinates and returns the point's position in body-relative coordinates.  <a href="#g0334d9d523cbfeec742ac4a814834199"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g0a2cd6f7499bcfeb8275cbb981465bbf">dBodyVectorToWorld</a> (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Convert from local to world coordinates.  <a href="#g0a2cd6f7499bcfeb8275cbb981465bbf"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g1e3ac3ef038e806d4942ea8b399ab575">dBodyVectorFromWorld</a> (dBodyID, dReal px, dReal py, dReal pz, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Convert from world to local coordinates.  <a href="#g1e3ac3ef038e806d4942ea8b399ab575"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gc474ca36d734fb67b8bd504b672527fa">dBodySetFiniteRotationMode</a> (dBodyID, int mode)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">controls the way a body's orientation is updated at each timestep.  <a href="#gc474ca36d734fb67b8bd504b672527fa"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ga9546c1ea6119fcbf80c71a96f56d052">dBodySetFiniteRotationAxis</a> (dBodyID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">sets the finite rotation axis for a body.  <a href="#ga9546c1ea6119fcbf80c71a96f56d052"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g3fb10ac984d64c92e4f138e50b704f9e">dBodyGetFiniteRotationMode</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the way a body's orientation is updated each timestep.  <a href="#g3fb10ac984d64c92e4f138e50b704f9e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gfc8853ff678be731881665ff7abf61ad">dBodyGetFiniteRotationAxis</a> (dBodyID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the finite rotation axis.  <a href="#gfc8853ff678be731881665ff7abf61ad"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g79fd517a57ac9c3594cb71850f649af7">dBodyGetNumJoints</a> (dBodyID b)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the number of joints that are attached to this body.  <a href="#g79fd517a57ac9c3594cb71850f649af7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g095e41c5b5632b22aa9bd1a4bd051f8d">dBodyGetJoint</a> (dBodyID, int index)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Return a joint attached to this body, given by index.  <a href="#g095e41c5b5632b22aa9bd1a4bd051f8d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#gd0776c40f667b235f8642e10755543f8">dBodyEnable</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Manually enable a body.  <a href="#gd0776c40f667b235f8642e10755543f8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#ga78092d7cadae36373441aa9be7e6157">dBodyDisable</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Manually disable a body.  <a href="#ga78092d7cadae36373441aa9be7e6157"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g7e7803132dfcfceee04a6ab0ca1e0bf8">dBodyIsEnabled</a> (dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Check wether a body is enabled.  <a href="#g7e7803132dfcfceee04a6ab0ca1e0bf8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g5465d605e7fbe82d63a0d4e1000da731">dBodySetGravityMode</a> (dBodyID b, int mode)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set whether the body is influenced by the world's gravity or not.  <a href="#g5465d605e7fbe82d63a0d4e1000da731"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__bodies.html#g0df2f4fed454c567f10fc8bbb8c70455">dBodyGetGravityMode</a> (dBodyID b)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get whether the body is influenced by the world's gravity or not.  <a href="#g0df2f4fed454c567f10fc8bbb8c70455"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+A rigid body has various properties from the point of view of the simulation. Some properties change over time:<p>
+<ul>
+<li>Position vector (x,y,z) of the body's point of reference. Currently the point of reference must correspond to the body's center of mass. </li>
+<li>Linear velocity of the point of reference, a vector (vx,vy,vz). </li>
+<li>Orientation of a body, represented by a quaternion (qs,qx,qy,qz) or a 3x3 rotation matrix. </li>
+<li>Angular velocity vector (wx,wy,wz) which describes how the orientation changes over time.</li>
+</ul>
+Other body properties are usually constant over time:<p>
+<ul>
+<li>Mass of the body. </li>
+<li>Position of the center of mass with respect to the point of reference. In the current implementation the center of mass and the point of reference must coincide. </li>
+<li>Inertia matrix. This is a 3x3 matrix that describes how the body's mass is distributed around the center of mass. Conceptually each body has an x-y-z coordinate frame embedded in it that moves and rotates with the body.</li>
+</ul>
+The origin of this coordinate frame is the body's point of reference. Some values in ODE (vectors, matrices etc) are relative to the body coordinate frame, and others are relative to the global coordinate frame.<p>
+Note that the shape of a rigid body is not a dynamical property (except insofar as it influences the various mass properties). It is only collision detection that cares about the detailed shape of the body. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="gf69c1ebd1c8d7d165fe740c9f1146217"></a><!-- doxytag: member="objects.h::dBodyCopyPosition" ref="gf69c1ebd1c8d7d165fe740c9f1146217" args="(dBodyID body, dVector3 pos)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyCopyPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>pos</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Copy the position of a body into a vector. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>body</em>&nbsp;</td><td>the body to query </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>a copy of the body position </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#g2bddae29591b9f14c5175411b783d570" title="Get the position of a body.">dBodyGetPosition</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd906c3ad061b7f70d1c60d6957aa2d0f"></a><!-- doxytag: member="objects.h::dBodyCopyQuaternion" ref="gd906c3ad061b7f70d1c60d6957aa2d0f" args="(dBodyID body, dQuaternion quat)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyCopyQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dQuaternion&nbsp;</td>
+          <td class="paramname"> <em>quat</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Copy the orientation of a body into a quaternion. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>body</em>&nbsp;</td><td>the body to query </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>quat</em>&nbsp;</td><td>a copy of the orientation quaternion </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#g36b7e19622ed47fe6b9dcfbac20237e7" title="Get the rotation of a body.">dBodyGetQuaternion</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga992006681bc720c6c6ef644768226e5"></a><!-- doxytag: member="objects.h::dBodyCopyRotation" ref="ga992006681bc720c6c6ef644768226e5" args="(dBodyID, dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyCopyRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Copy the rotation of a body. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>body</em>&nbsp;</td><td>the body to query </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>a copy of the rotation matrix </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#g2374da7ff88a2bac607e2fbce529ad27" title="Get the rotation of a body.">dBodyGetRotation</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g578137bbaf82d4b8896d2baee3a032a6"></a><!-- doxytag: member="objects.h::dBodyCreate" ref="g578137bbaf82d4b8896d2baee3a032a6" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dBodyID dBodyCreate           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a body in given world. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Default mass parameters are at position (0,0,0). </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc1a0ee96898f14017a29b2afa0eafe13"></a><!-- doxytag: member="objects.h::dBodyDestroy" ref="gc1a0ee96898f14017a29b2afa0eafe13" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyDestroy           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Destroy a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>All joints that are attached to this body will be put into limbo: i.e. unattached and not affecting the simulation, but they will NOT be deleted. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga78092d7cadae36373441aa9be7e6157"></a><!-- doxytag: member="objects.h::dBodyDisable" ref="ga78092d7cadae36373441aa9be7e6157" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyDisable           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Manually disable a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>A disabled body that is connected through a joint to an enabled body will be automatically re-enabled at the next simulation step. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd0776c40f667b235f8642e10755543f8"></a><!-- doxytag: member="objects.h::dBodyEnable" ref="gd0776c40f667b235f8642e10755543f8" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyEnable           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Manually enable a body. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dBodyID</em>&nbsp;</td><td>identification of body. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g5b988719423e9bc3af1be2146872e2d6"></a><!-- doxytag: member="objects.h::dBodyGetAutoDisableAngularThreshold" ref="g5b988719423e9bc3af1be2146872e2d6" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dBodyGetAutoDisableAngularThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable angular average threshold. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf398254a02ab5bedcdf7e4fb2918a902"></a><!-- doxytag: member="objects.h::dBodyGetAutoDisableAverageSamplesCount" ref="gf398254a02ab5bedcdf7e4fb2918a902" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyGetAutoDisableAverageSamplesCount           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable average size (samples count). 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the nr of steps/size. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfe44b3ae620abb1091472089cb07f64e"></a><!-- doxytag: member="objects.h::dBodyGetAutoDisableFlag" ref="gfe44b3ae620abb1091472089cb07f64e" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyGetAutoDisableFlag           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable flag. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 or 1 </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g57c1e1b1bd50fdcafc5140c1ed89c7d7"></a><!-- doxytag: member="objects.h::dBodyGetAutoDisableLinearThreshold" ref="g57c1e1b1bd50fdcafc5140c1ed89c7d7" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dBodyGetAutoDisableLinearThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable linear average threshold. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g797ad84c737a2ae4ef3f8a37dfa02183"></a><!-- doxytag: member="objects.h::dBodyGetAutoDisableSteps" ref="g797ad84c737a2ae4ef3f8a37dfa02183" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyGetAutoDisableSteps           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto steps a body must be thought of as idle to disable. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the nr of steps </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga2f4d01a8fb5c4d7e77efd5f0e4dd72b"></a><!-- doxytag: member="objects.h::dBodyGetAutoDisableTime" ref="ga2f4d01a8fb5c4d7e77efd5f0e4dd72b" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dBodyGetAutoDisableTime           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable time. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>nr of seconds </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g68d3d80c7476776dd4512d577bf70325"></a><!-- doxytag: member="objects.h::dBodyGetData" ref="g68d3d80c7476776dd4512d577bf70325" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void* dBodyGetData           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the body's user-data pointer. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>a pointer to the user's data. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfc8853ff678be731881665ff7abf61ad"></a><!-- doxytag: member="objects.h::dBodyGetFiniteRotationAxis" ref="gfc8853ff678be731881665ff7abf61ad" args="(dBodyID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyGetFiniteRotationAxis           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the finite rotation axis. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the axis. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3fb10ac984d64c92e4f138e50b704f9e"></a><!-- doxytag: member="objects.h::dBodyGetFiniteRotationMode" ref="g3fb10ac984d64c92e4f138e50b704f9e" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyGetFiniteRotationMode           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the way a body's orientation is updated each timestep. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the mode 0 (infitesimal) or 1 (finite). </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3b458397a79f09b1957cb6e5a85e9eba"></a><!-- doxytag: member="objects.h::dBodyGetForce" ref="g3b458397a79f09b1957cb6e5a85e9eba" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dBodyGetForce           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the current accumulated force vector. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>points to an array of 3 reals. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The returned values are pointers to internal data structures, so the vectors are only valid until any changes are made to the rigid body system. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g0df2f4fed454c567f10fc8bbb8c70455"></a><!-- doxytag: member="objects.h::dBodyGetGravityMode" ref="g0df2f4fed454c567f10fc8bbb8c70455" args="(dBodyID b)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyGetGravityMode           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>b</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get whether the body is influenced by the world's gravity or not. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>nonzero means gravity affects this body. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g095e41c5b5632b22aa9bd1a4bd051f8d"></a><!-- doxytag: member="objects.h::dBodyGetJoint" ref="g095e41c5b5632b22aa9bd1a4bd051f8d" args="(dBodyID, int index)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dBodyGetJoint           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>index</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return a joint attached to this body, given by index. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>index</em>&nbsp;</td><td>valid range is 0 to n-1 where n is the value returned by <a class="el" href="group__bodies.html#g79fd517a57ac9c3594cb71850f649af7" title="Get the number of joints that are attached to this body.">dBodyGetNumJoints()</a>. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g79fd517a57ac9c3594cb71850f649af7"></a><!-- doxytag: member="objects.h::dBodyGetNumJoints" ref="g79fd517a57ac9c3594cb71850f649af7" args="(dBodyID b)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyGetNumJoints           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>b</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the number of joints that are attached to this body. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>nr of joints </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g89dd6a4a3c6f3cd98c8377e8d4dec015"></a><!-- doxytag: member="objects.h::dBodyGetPointVel" ref="g89dd6a4a3c6f3cd98c8377e8d4dec015" args="(dBodyID, dReal px, dReal py, dReal pz, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyGetPointVel           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>px</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>py</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>pz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get velocity vector in global coords of a globally specified point on a body. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the result. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2bddae29591b9f14c5175411b783d570"></a><!-- doxytag: member="objects.h::dBodyGetPosition" ref="g2bddae29591b9f14c5175411b783d570" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dBodyGetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the position of a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>When getting, the returned values are pointers to internal data structures, so the vectors are valid until any changes are made to the rigid body system structure. </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#gf69c1ebd1c8d7d165fe740c9f1146217" title="Copy the position of a body into a vector.">dBodyCopyPosition</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g0334d9d523cbfeec742ac4a814834199"></a><!-- doxytag: member="objects.h::dBodyGetPosRelPoint" ref="g0334d9d523cbfeec742ac4a814834199" args="(dBodyID, dReal px, dReal py, dReal pz, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyGetPosRelPoint           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>px</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>py</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>pz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+takes a point in global coordinates and returns the point's position in body-relative coordinates. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This is the inverse of <a class="el" href="group__bodies.html#gfcf00cd9c4c754c82189fb9d1eb9f102" title="Get world position of a relative point on body.">dBodyGetRelPointPos()</a></dd></dl>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the result. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g36b7e19622ed47fe6b9dcfbac20237e7"></a><!-- doxytag: member="objects.h::dBodyGetQuaternion" ref="g36b7e19622ed47fe6b9dcfbac20237e7" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dBodyGetQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the rotation of a body. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>pointer to 4 scalars that represent the quaternion. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfcf00cd9c4c754c82189fb9d1eb9f102"></a><!-- doxytag: member="objects.h::dBodyGetRelPointPos" ref="gfcf00cd9c4c754c82189fb9d1eb9f102" args="(dBodyID, dReal px, dReal py, dReal pz, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyGetRelPointPos           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>px</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>py</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>pz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get world position of a relative point on body. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the result. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7fd4f4c7e70c59380da11277b2e97510"></a><!-- doxytag: member="objects.h::dBodyGetRelPointVel" ref="g7fd4f4c7e70c59380da11277b2e97510" args="(dBodyID, dReal px, dReal py, dReal pz, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyGetRelPointVel           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>px</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>py</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>pz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get velocity vector in global coords of a relative point on body. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the result. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2374da7ff88a2bac607e2fbce529ad27"></a><!-- doxytag: member="objects.h::dBodyGetRotation" ref="g2374da7ff88a2bac607e2fbce529ad27" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dBodyGetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the rotation of a body. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>pointer to a 4x3 rotation matrix. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfe88a5bc363fc812c8f154e3d5f8ea5d"></a><!-- doxytag: member="objects.h::dBodyGetTorque" ref="gfe88a5bc363fc812c8f154e3d5f8ea5d" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dBodyGetTorque           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the current accumulated torque vector. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>points to an array of 3 reals. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The returned values are pointers to internal data structures, so the vectors are only valid until any changes are made to the rigid body system. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb044b0a466f2ec2af3fd29ae399e822e"></a><!-- doxytag: member="objects.h::dBodyGetWorld" ref="gb044b0a466f2ec2af3fd29ae399e822e" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dWorldID dBodyGetWorld           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrives the world attached to te given body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd></dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7e7803132dfcfceee04a6ab0ca1e0bf8"></a><!-- doxytag: member="objects.h::dBodyIsEnabled" ref="g7e7803132dfcfceee04a6ab0ca1e0bf8" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dBodyIsEnabled           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Check wether a body is enabled. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if a body is currently enabled or 0 if it is disabled. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g206ccf22f027a62aaf5e45a16ddc4040"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableAngularThreshold" ref="g206ccf22f027a62aaf5e45a16ddc4040" args="(dBodyID, dReal angular_average_threshold)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableAngularThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>angular_average_threshold</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable angular average threshold. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g4bce13aaa5ffb7d4b3452191974c3be6"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableAverageSamplesCount" ref="g4bce13aaa5ffb7d4b3452191974c3be6" args="(dBodyID, unsigned int average_samples_count)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableAverageSamplesCount           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">unsigned int&nbsp;</td>
+          <td class="paramname"> <em>average_samples_count</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable average buffer size (average steps). 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>average_samples_count</em>&nbsp;</td><td>the nr of samples to review. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g00969db4aebc2e8629cd9c45f3b7385e"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableDefaults" ref="g00969db4aebc2e8629cd9c45f3b7385e" args="(dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableDefaults           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable defaults. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Set the values for the body to those set as default for the world. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ge352fdcd8851224f07da53f35691ceb7"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableFlag" ref="ge352fdcd8851224f07da53f35691ceb7" args="(dBodyID, int do_auto_disable)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableFlag           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>do_auto_disable</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable flag. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>do_auto_disable</em>&nbsp;</td><td>0 or 1 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb8f6e736830cfea86c35e7a0cdfa3112"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableLinearThreshold" ref="gb8f6e736830cfea86c35e7a0cdfa3112" args="(dBodyID, dReal linear_average_threshold)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableLinearThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>linear_average_threshold</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable linear average threshold. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g03cc329bdc8e19e59c4bfe62cf736578"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableSteps" ref="g03cc329bdc8e19e59c4bfe62cf736578" args="(dBodyID, int steps)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableSteps           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>steps</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable steps. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>steps</em>&nbsp;</td><td>the nr of steps. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g0ae2f08bb38359934151f9420cdef341"></a><!-- doxytag: member="objects.h::dBodySetAutoDisableTime" ref="g0ae2f08bb38359934151f9420cdef341" args="(dBodyID, dReal time)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetAutoDisableTime           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>time</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable time. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>time</em>&nbsp;</td><td>nr of seconds. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf9cbe9e1ed1bd4559bb5603b8d0f92f2"></a><!-- doxytag: member="objects.h::dBodySetData" ref="gf9cbe9e1ed1bd4559bb5603b8d0f92f2" args="(dBodyID, void *data)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetData           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&nbsp;</td>
+          <td class="paramname"> <em>data</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the body's user-data pointer. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>arbitraty pointer </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga9546c1ea6119fcbf80c71a96f56d052"></a><!-- doxytag: member="objects.h::dBodySetFiniteRotationAxis" ref="ga9546c1ea6119fcbf80c71a96f56d052" args="(dBodyID, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetFiniteRotationAxis           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+sets the finite rotation axis for a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This is axis only has meaning when the finite rotation mode is set If this axis is zero (0,0,0), full finite rotations are performed on the body. If this axis is nonzero, the body is rotated by performing a partial finite rotation along the axis direction followed by an infinitesimal rotation along an orthogonal direction. <p>
+This can be useful to alleviate certain sources of error caused by quickly spinning bodies. For example, if a car wheel is rotating at high speed you can call this function with the wheel's hinge axis as the argument to try and improve its behavior. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc474ca36d734fb67b8bd504b672527fa"></a><!-- doxytag: member="objects.h::dBodySetFiniteRotationMode" ref="gc474ca36d734fb67b8bd504b672527fa" args="(dBodyID, int mode)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetFiniteRotationMode           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>mode</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+controls the way a body's orientation is updated at each timestep. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>mode</em>&nbsp;</td><td>can be 0 or 1: <ul>
+<li>0: An ``infinitesimal'' orientation update is used. This is fast to compute, but it can occasionally cause inaccuracies for bodies that are rotating at high speed, especially when those bodies are joined to other bodies. This is the default for every new body that is created. </li>
+<li>1: A ``finite'' orientation update is used. This is more costly to compute, but will be more accurate for high speed rotations. </li>
+</ul>
+</td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Note however that high speed rotations can result in many types of error in a simulation, and the finite mode will only fix one of those sources of error. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gbd56079db36d4562db0e18aebea4f95f"></a><!-- doxytag: member="objects.h::dBodySetForce" ref="gbd56079db36d4562db0e18aebea4f95f" args="(dBodyID b, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetForce           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>b</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the body force accumulation vector. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This is mostly useful to zero the force and torque for deactivated bodies before they are reactivated, in the case where the force-adding functions were called on them while they were deactivated. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g5465d605e7fbe82d63a0d4e1000da731"></a><!-- doxytag: member="objects.h::dBodySetGravityMode" ref="g5465d605e7fbe82d63a0d4e1000da731" args="(dBodyID b, int mode)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetGravityMode           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>b</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>mode</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set whether the body is influenced by the world's gravity or not. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>mode</em>&nbsp;</td><td>when nonzero gravity affects this body. </td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Newly created bodies are always influenced by the world's gravity. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb84612b793366f18ff5b5cbdbed092da"></a><!-- doxytag: member="objects.h::dBodySetPosition" ref="gb84612b793366f18ff5b5cbdbed092da" args="(dBodyID, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set position of a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>After setting, the outcome of the simulation is undefined if the new configuration is inconsistent with the joints/constraints that are present. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga5f51dd3605c402320e9eae4231d7ad4"></a><!-- doxytag: member="objects.h::dBodySetQuaternion" ref="ga5f51dd3605c402320e9eae4231d7ad4" args="(dBodyID, const dQuaternion q)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dQuaternion&nbsp;</td>
+          <td class="paramname"> <em>q</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the orientation of a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>After setting, the outcome of the simulation is undefined if the new configuration is inconsistent with the joints/constraints that are present. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb5f04968ec37ef46d2aaffad6c344468"></a><!-- doxytag: member="objects.h::dBodySetRotation" ref="gb5f04968ec37ef46d2aaffad6c344468" args="(dBodyID, const dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the orientation of a body. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>After setting, the outcome of the simulation is undefined if the new configuration is inconsistent with the joints/constraints that are present. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfcd3e44223a878ba52428ad3a124fa94"></a><!-- doxytag: member="objects.h::dBodySetTorque" ref="gfcd3e44223a878ba52428ad3a124fa94" args="(dBodyID b, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodySetTorque           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>b</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the body torque accumulation vector. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This is mostly useful to zero the force and torque for deactivated bodies before they are reactivated, in the case where the force-adding functions were called on them while they were deactivated. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g1e3ac3ef038e806d4942ea8b399ab575"></a><!-- doxytag: member="objects.h::dBodyVectorFromWorld" ref="g1e3ac3ef038e806d4942ea8b399ab575" args="(dBodyID, dReal px, dReal py, dReal pz, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyVectorFromWorld           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>px</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>py</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>pz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Convert from world to local coordinates. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the result. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g0a2cd6f7499bcfeb8275cbb981465bbf"></a><!-- doxytag: member="objects.h::dBodyVectorToWorld" ref="g0a2cd6f7499bcfeb8275cbb981465bbf" args="(dBodyID, dReal px, dReal py, dReal pz, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dBodyVectorToWorld           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>px</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>py</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>pz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Convert from local to world coordinates. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>will contain the result. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__collide.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__collide.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__collide.html	(revision 216)
@@ -0,0 +1,2452 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Collision Detection</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Collision Detection</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Modules</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__sphere.html">Sphere Class</a></td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__box.html">Box Class</a></td></tr>
+
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structd_contact_geom.html">dContactGeom</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Describe the contact point between two geoms.  <a href="structd_contact_geom.html#_details">More...</a><br></td></tr>
+<tr><td colspan="2"><br><h2>Typedefs</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9">dHeightfieldGetHeight</a> (void *p_user_data, int x, int z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Callback prototype.  <a href="#g32d2c58e3b2b589bd7672f3453102eb9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">typedef void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a> (void *data, dGeomID o1, dGeomID o2)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">User callback for geom-geom collision testing.  <a href="#g9f458413ace07fa9e3e7e52d6652ace0"></a><br></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6">dGeomDestroy</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Destroy a geom, removing it from any space.  <a href="#g96b9e7d3a7ca769b0c8f37eecfaf98c6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gf68eb443d5c66ab1aaa8a7d38d1dbc4f">dGeomSetData</a> (dGeomID geom, void *data)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the user-defined data pointer stored in the geom.  <a href="#gf68eb443d5c66ab1aaa8a7d38d1dbc4f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gc1a185e22b136814fd3afc8469d98996">dGeomGetData</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the user-defined data pointer stored in the geom.  <a href="#gc1a185e22b136814fd3afc8469d98996"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g97cad1194789477eac19fe364d986505">dGeomSetBody</a> (dGeomID geom, dBodyID body)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the body associated with a placeable geom.  <a href="#g97cad1194789477eac19fe364d986505"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dBodyID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gd6cedf77fde0dddf751c5d42fcc8eebf">dGeomGetBody</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the body associated with a placeable geom.  <a href="#gd6cedf77fde0dddf751c5d42fcc8eebf"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g71043b70a735e8f5451c3e13cef345fe">dGeomSetPosition</a> (dGeomID geom, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the position vector of a placeable geom.  <a href="#g71043b70a735e8f5451c3e13cef345fe"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g76c510f4b7d5a036d8a36f2d60d670e5">dGeomSetRotation</a> (dGeomID geom, const dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the rotation matrix of a placeable geom.  <a href="#g76c510f4b7d5a036d8a36f2d60d670e5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g989149d93162264d699444a57b045150">dGeomSetQuaternion</a> (dGeomID geom, const dQuaternion Q)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the rotation of a placeable geom.  <a href="#g989149d93162264d699444a57b045150"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g95b93f803880cac2619fe2635aa93ad8">dGeomGetPosition</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the position vector of a placeable geom.  <a href="#g95b93f803880cac2619fe2635aa93ad8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gd2cccf2b4c62bec58720d4f5fab8108d">dGeomCopyPosition</a> (dGeomID geom, dVector3 pos)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Copy the position of a geom into a vector.  <a href="#gd2cccf2b4c62bec58720d4f5fab8108d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g293b2264cefb12f9a6659cacc6a722f7">dGeomGetRotation</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the rotation matrix of a placeable geom.  <a href="#g293b2264cefb12f9a6659cacc6a722f7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g800b702e148a8c279596f591b910cfbd">dGeomCopyRotation</a> (dGeomID geom, dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the rotation matrix of a placeable geom.  <a href="#g800b702e148a8c279596f591b910cfbd"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g11ad7f0098639b06f4bcd2d681122842">dGeomGetQuaternion</a> (dGeomID geom, dQuaternion result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the rotation quaternion of a placeable geom.  <a href="#g11ad7f0098639b06f4bcd2d681122842"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g904e360ac6e9e85a05e67929990e5b72">dGeomGetAABB</a> (dGeomID geom, dReal aabb[6])</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Return the axis-aligned bounding box.  <a href="#g904e360ac6e9e85a05e67929990e5b72"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#ge5a58bdc78fb4f163a0e9c3ecabf64c9">dGeomIsSpace</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Determing if a geom is a space.  <a href="#ge5a58bdc78fb4f163a0e9c3ecabf64c9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dSpaceID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gfdc35eade2cbd0b6886ce957325d7c03">dGeomGetSpace</a> (dGeomID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Query for the space containing a particular geom.  <a href="#gfdc35eade2cbd0b6886ce957325d7c03"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g07b5ed5b915f756f419a4a7ce69dc67e">dGeomGetClass</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Given a geom, this returns its class.  <a href="#g07b5ed5b915f756f419a4a7ce69dc67e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g80fd5741701eb48472521780d5e2f9b9">dGeomSetCategoryBits</a> (dGeomID geom, unsigned long bits)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the "category" bitfield for the given geom.  <a href="#g80fd5741701eb48472521780d5e2f9b9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#ga55b4de01a61be41668685857b78455d">dGeomSetCollideBits</a> (dGeomID geom, unsigned long bits)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the "collide" bitfield for the given geom.  <a href="#ga55b4de01a61be41668685857b78455d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API unsigned long&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gfb62d3493b6789382f65776ab931e78d">dGeomGetCategoryBits</a> (dGeomID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the "category" bitfield for the given geom.  <a href="#gfb62d3493b6789382f65776ab931e78d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API unsigned long&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g5591e5c496a5a6f8b66dc57e03d0cd8d">dGeomGetCollideBits</a> (dGeomID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the "collide" bitfield for the given geom.  <a href="#g5591e5c496a5a6f8b66dc57e03d0cd8d"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#ga7c64b8fcae37ee9541208a0351f3d05">dGeomEnable</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Enable a geom.  <a href="#ga7c64b8fcae37ee9541208a0351f3d05"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g6cb32b4161435fe491859680b463fc12">dGeomDisable</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Disable a geom.  <a href="#g6cb32b4161435fe491859680b463fc12"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g6533d33f870cf0fb6684ec05e5c0562e">dGeomIsEnabled</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Check to see if a geom is enabled.  <a href="#g6533d33f870cf0fb6684ec05e5c0562e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gdc292bc01d5bed32f145ee42760d73b4">dGeomSetOffsetPosition</a> (dGeomID geom, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the local offset position of a geom from its body.  <a href="#gdc292bc01d5bed32f145ee42760d73b4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g805d896b4bc79ceb40e70aadb9629cab">dGeomSetOffsetRotation</a> (dGeomID geom, const dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the local offset rotation matrix of a geom from its body.  <a href="#g805d896b4bc79ceb40e70aadb9629cab"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g9eba87b7598eb6b3a9b6bde1abbeaa1a">dGeomSetOffsetQuaternion</a> (dGeomID geom, const dQuaternion Q)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the local offset rotation of a geom from its body.  <a href="#g9eba87b7598eb6b3a9b6bde1abbeaa1a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g934fe31c543d588991d28cd8571e52ed">dGeomSetOffsetWorldPosition</a> (dGeomID geom, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the offset position of a geom from its body.  <a href="#g934fe31c543d588991d28cd8571e52ed"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g2c1ef27e7e8ced6eb8488221a1a7c200">dGeomSetOffsetWorldRotation</a> (dGeomID geom, const dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the offset rotation of a geom from its body.  <a href="#g2c1ef27e7e8ced6eb8488221a1a7c200"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#ga04f2117ab18a1d3e27270defdad83a8">dGeomSetOffsetWorldQuaternion</a> (dGeomID geom, const dQuaternion)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the offset rotation of a geom from its body.  <a href="#ga04f2117ab18a1d3e27270defdad83a8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gc81929d988b21c4e5338017f2e92a6f2">dGeomClearOffset</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Clear any offset from the geom.  <a href="#gc81929d988b21c4e5338017f2e92a6f2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g46260e0668373aa600b1cf8f83276e10">dGeomIsOffset</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Check to see whether the geom has an offset.  <a href="#g46260e0668373aa600b1cf8f83276e10"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gb200f73800d253ab3a87f9856d4e18d2">dGeomGetOffsetPosition</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the offset position vector of a geom.  <a href="#gb200f73800d253ab3a87f9856d4e18d2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gd4a1e59ecc3c570e3c37c5b8fad71220">dGeomCopyOffsetPosition</a> (dGeomID geom, dVector3 pos)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Copy the offset position vector of a geom.  <a href="#gd4a1e59ecc3c570e3c37c5b8fad71220"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API const dReal *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gba28cf4ca8f552c782fc30ce3073dc73">dGeomGetOffsetRotation</a> (dGeomID geom)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the offset rotation matrix of a geom.  <a href="#gba28cf4ca8f552c782fc30ce3073dc73"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gcf96cd4f9913dc258e6f29da9979388c">dGeomCopyOffsetRotation</a> (dGeomID geom, dMatrix3 R)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Copy the offset rotation matrix of a geom.  <a href="#gcf96cd4f9913dc258e6f29da9979388c"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g8fc20f761daf36976e50d057cf2650ca">dGeomGetOffsetQuaternion</a> (dGeomID geom, dQuaternion result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the offset rotation quaternion of a geom.  <a href="#g8fc20f761daf36976e50d057cf2650ca"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g08508345384abb95e25d674b39157bf8">dCollide</a> (dGeomID o1, dGeomID o2, int flags, <a class="el" href="structd_contact_geom.html">dContactGeom</a> *contact, int skip)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Given two geoms o1 and o2 that potentially intersect, generate contact information for them.  <a href="#g08508345384abb95e25d674b39157bf8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gfd185829b6940e2b3238517e1acd2fbb">dSpaceCollide</a> (dSpaceID space, void *data, <a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a> *callback)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Determines which pairs of geoms in a space may potentially intersect, and calls the callback function for each candidate pair.  <a href="#gfd185829b6940e2b3238517e1acd2fbb"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g72a6bb0b550d3e181f8b7a9be7179db5">dSpaceCollide2</a> (dGeomID space1, dGeomID space2, void *data, <a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a> *callback)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Determines which geoms from one space may potentially intersect with geoms from another space, and calls the callback function for each candidate pair.  <a href="#g72a6bb0b550d3e181f8b7a9be7179db5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dGeomID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gd50d5cd5fea5bfc12584e60d4a936cfb">dCreateHeightfield</a> (dSpaceID space, dHeightfieldDataID data, int bPlaceable)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Creates a heightfield geom.  <a href="#gd50d5cd5fea5bfc12584e60d4a936cfb"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API <br>
+dHeightfieldDataID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g7de82d5cf9aa10bb3144d51f4360eea1">dGeomHeightfieldDataCreate</a> ()</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Creates a new empty dHeightfieldDataID.  <a href="#g7de82d5cf9aa10bb3144d51f4360eea1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gf98fc1f3d1784df5a5dff114b483d408">dGeomHeightfieldDataDestroy</a> (dHeightfieldDataID d)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Destroys a dHeightfieldDataID.  <a href="#gf98fc1f3d1784df5a5dff114b483d408"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g34566000a5a2673cc013294f0ed85926">dGeomHeightfieldDataBuildCallback</a> (dHeightfieldDataID d, void *pUserData, <a class="el" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9">dHeightfieldGetHeight</a> *pCallback, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Configures a dHeightfieldDataID to use a callback to retrieve height data.  <a href="#g34566000a5a2673cc013294f0ed85926"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g2c15b7c1a36c7526b66911beab1b7934">dGeomHeightfieldDataBuildByte</a> (dHeightfieldDataID d, const unsigned char *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Configures a dHeightfieldDataID to use height data in byte format.  <a href="#g2c15b7c1a36c7526b66911beab1b7934"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g2f7582d64cc8219141bc10efeca86d17">dGeomHeightfieldDataBuildShort</a> (dHeightfieldDataID d, const short *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Configures a dHeightfieldDataID to use height data in short format.  <a href="#g2f7582d64cc8219141bc10efeca86d17"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g8da529419317e7bd4e01dabbe94daa09">dGeomHeightfieldDataBuildSingle</a> (dHeightfieldDataID d, const float *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Configures a dHeightfieldDataID to use height data in single precision floating point format.  <a href="#g8da529419317e7bd4e01dabbe94daa09"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g98ec0c952b3b4e0fb3cd8cf66e267c86">dGeomHeightfieldDataBuildDouble</a> (dHeightfieldDataID d, const double *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Configures a dHeightfieldDataID to use height data in double precision floating point format.  <a href="#g98ec0c952b3b4e0fb3cd8cf66e267c86"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#gcdef420e65e3751388b315f5de2804b2">dGeomHeightfieldDataSetBounds</a> (dHeightfieldDataID d, dReal minHeight, dReal maxHeight)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Manually set the minimum and maximum height bounds.  <a href="#gcdef420e65e3751388b315f5de2804b2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g6c1ae1f3ca652d6410e7804cdf8f8491">dGeomHeightfieldSetHeightfieldData</a> (dGeomID g, dHeightfieldDataID d)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Assigns a dHeightfieldDataID to a heightfield geom.  <a href="#g6c1ae1f3ca652d6410e7804cdf8f8491"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API <br>
+dHeightfieldDataID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide.html#g747176d26ce4f9b10ebfa6c865ef1cca">dGeomHeightfieldGetHeightfieldData</a> (dGeomID g)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Gets the dHeightfieldDataID bound to a heightfield geom.  <a href="#g747176d26ce4f9b10ebfa6c865ef1cca"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+ODE has two main components: a dynamics simulation engine and a collision detection engine. The collision engine is given information about the shape of each body. At each time step it figures out which bodies touch each other and passes the resulting contact point information to the user. The user in turn creates contact joints between bodies.<p>
+Using ODE's collision detection is optional - an alternative collision detection system can be used as long as it can supply the right kinds of contact information. <hr><h2>Typedef Documentation</h2>
+<a class="anchor" name="g32d2c58e3b2b589bd7672f3453102eb9"></a><!-- doxytag: member="collision.h::dHeightfieldGetHeight" ref="g32d2c58e3b2b589bd7672f3453102eb9" args="(void *p_user_data, int x, int z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef dReal <a class="el" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9">dHeightfieldGetHeight</a>(void *p_user_data, int x, int z)          </td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Callback prototype. 
+<p>
+Used by the callback heightfield data type to sample a height for a given cell position.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>p_user_data</em>&nbsp;</td><td>User data specified when creating the dHeightfieldDataID </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>x</em>&nbsp;</td><td>The index of a sample in the local x axis. It is a value in the range zero to ( nWidthSamples - 1 ). </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>x</em>&nbsp;</td><td>The index of a sample in the local z axis. It is a value in the range zero to ( nDepthSamples - 1 ).</td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The sample height which is then scaled and offset using the values specified when the heightfield data was created. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g9f458413ace07fa9e3e7e52d6652ace0"></a><!-- doxytag: member="collision_space.h::dNearCallback" ref="g9f458413ace07fa9e3e7e52d6652ace0" args="(void *data, dGeomID o1, dGeomID o2)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef void <a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a>(void *data, dGeomID o1, dGeomID o2)          </td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+User callback for geom-geom collision testing. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>The user data object, as passed to dSpaceCollide. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>o1</em>&nbsp;</td><td>The first geom being tested. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>o2</em>&nbsp;</td><td>The second geom being test.</td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The callback function can call dCollide on o1 and o2 to generate contact points between each pair. Then these contact points may be added to the simulation as contact joints. The user's callback function can of course chose not to call dCollide for any pair, e.g. if the user decides that those pairs should not interact. </dd></dl>
+
+</div>
+</div><p>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g08508345384abb95e25d674b39157bf8"></a><!-- doxytag: member="collision.h::dCollide" ref="g08508345384abb95e25d674b39157bf8" args="(dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dCollide           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>o1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>o2</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>flags</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="structd_contact_geom.html">dContactGeom</a> *&nbsp;</td>
+          <td class="paramname"> <em>contact</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>skip</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Given two geoms o1 and o2 that potentially intersect, generate contact information for them. 
+<p>
+Internally, this just calls the correct class-specific collision functions for o1 and o2.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>o1</em>&nbsp;</td><td>The first geom to test. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>o2</em>&nbsp;</td><td>The second geom to test.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>flags</em>&nbsp;</td><td>The flags specify how contacts should be generated if the geoms touch. The lower 16 bits of flags is an integer that specifies the maximum number of contact points to generate. You must ask for at least one contact. Additionally, following bits may be set: CONTACTS_UNIMPORTANT -- just generate any contacts (skip contact refining). All other bits in flags must be set to zero. In the future the other bits may be used to select from different contact generation strategies.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>contact</em>&nbsp;</td><td>Points to an array of <a class="el" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> structures. The array must be able to hold at least the maximum number of contacts. These <a class="el" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> structures may be embedded within larger structures in the array -- the skip parameter is the byte offset from one <a class="el" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a> to the next in the array. If skip is sizeof(dContactGeom) then contact points to a normal (C-style) array. It is an error for skip to be smaller than sizeof(dContactGeom).</td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>If the geoms intersect, this function returns the number of contact points generated (and updates the contact array), otherwise it returns 0 (and the contact array is not touched).</dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>If a space is passed as o1 or o2 then this function will collide all objects contained in o1 with all objects contained in o2, and return the resulting contact points. This method for colliding spaces with geoms (or spaces with spaces) provides no user control over the individual collisions. To get that control, use dSpaceCollide or dSpaceCollide2 instead.<p>
+If o1 and o2 are the same geom then this function will do nothing and return 0. Technically speaking an object intersects with itself, but it is not useful to find contact points in this case.<p>
+This function does not care if o1 and o2 are in the same space or not (or indeed if they are in any space at all). </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd50d5cd5fea5bfc12584e60d4a936cfb"></a><!-- doxytag: member="collision.h::dCreateHeightfield" ref="gd50d5cd5fea5bfc12584e60d4a936cfb" args="(dSpaceID space, dHeightfieldDataID data, int bPlaceable)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dGeomID dCreateHeightfield           </td>
+          <td>(</td>
+          <td class="paramtype">dSpaceID&nbsp;</td>
+          <td class="paramname"> <em>space</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>data</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bPlaceable</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a heightfield geom. 
+<p>
+Uses the information in the given dHeightfieldDataID to construct a geom representing a heightfield in a collision space.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>space</em>&nbsp;</td><td>The space to add the geom to. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>The dHeightfieldDataID created by dGeomHeightfieldDataCreate and setup by dGeomHeightfieldDataBuildCallback, dGeomHeightfieldDataBuildByte, dGeomHeightfieldDataBuildShort or dGeomHeightfieldDataBuildFloat. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bPlaceable</em>&nbsp;</td><td>If non-zero this geom can be transformed in the world using the usual functions such as dGeomSetPosition and dGeomSetRotation. If the geom is not set as placeable, then it uses a fixed orientation where the global y axis represents the dynamic 'height' of the heightfield.</td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A geom id to reference this geom in other calls. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc81929d988b21c4e5338017f2e92a6f2"></a><!-- doxytag: member="collision.h::dGeomClearOffset" ref="gc81929d988b21c4e5338017f2e92a6f2" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomClearOffset           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Clear any offset from the geom. 
+<p>
+If the geom has an offset, it is eliminated and the geom is repositioned at the body's position. If the geom has no offset, this function does nothing. This is more efficient than calling dGeomSetOffsetPosition(zero) and dGeomSetOffsetRotation(identiy), because this function actually eliminates the offset, rather than leaving it as the identity transform.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to have its offset destroyed. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd4a1e59ecc3c570e3c37c5b8fad71220"></a><!-- doxytag: member="collision.h::dGeomCopyOffsetPosition" ref="gd4a1e59ecc3c570e3c37c5b8fad71220" args="(dGeomID geom, dVector3 pos)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomCopyOffsetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>pos</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Copy the offset position vector of a geom. 
+<p>
+Returns the positional offset of the geom in local coordinates. If the geom has no offset, this function returns the zero vector.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>returns the offset position </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gcf96cd4f9913dc258e6f29da9979388c"></a><!-- doxytag: member="collision.h::dGeomCopyOffsetRotation" ref="gcf96cd4f9913dc258e6f29da9979388c" args="(dGeomID geom, dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomCopyOffsetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Copy the offset rotation matrix of a geom. 
+<p>
+Returns the rotational offset of the geom in local coordinates. If the geom has no offset, this function returns the identity matrix.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>returns the rotation matrix. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd2cccf2b4c62bec58720d4f5fab8108d"></a><!-- doxytag: member="collision.h::dGeomCopyPosition" ref="gd2cccf2b4c62bec58720d4f5fab8108d" args="(dGeomID geom, dVector3 pos)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomCopyPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>pos</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Copy the position of a geom into a vector. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>a copy of the geom position </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g95b93f803880cac2619fe2635aa93ad8" title="Get the position vector of a placeable geom.">dGeomGetPosition</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g800b702e148a8c279596f591b910cfbd"></a><!-- doxytag: member="collision.h::dGeomCopyRotation" ref="g800b702e148a8c279596f591b910cfbd" args="(dGeomID geom, dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomCopyRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the rotation matrix of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's rotation will be returned.<p>
+Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>a copy of the geom rotation </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g293b2264cefb12f9a6659cacc6a722f7" title="Get the rotation matrix of a placeable geom.">dGeomGetRotation</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g96b9e7d3a7ca769b0c8f37eecfaf98c6"></a><!-- doxytag: member="collision.h::dGeomDestroy" ref="g96b9e7d3a7ca769b0c8f37eecfaf98c6" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomDestroy           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Destroy a geom, removing it from any space. 
+<p>
+Destroy a geom, removing it from any space it is in first. This one function destroys a geom of any type, but to create a geom you must call a creation function for that type.<p>
+When a space is destroyed, if its cleanup mode is 1 (the default) then all the geoms in that space are automatically destroyed as well.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to be destroyed. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g6cb32b4161435fe491859680b463fc12"></a><!-- doxytag: member="collision.h::dGeomDisable" ref="g6cb32b4161435fe491859680b463fc12" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomDisable           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Disable a geom. 
+<p>
+Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2, although they can still be members of a space. New geoms are created in the enabled state.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to disable </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g6cb32b4161435fe491859680b463fc12" title="Disable a geom.">dGeomDisable</a> <p>
+<a class="el" href="group__collide.html#g6533d33f870cf0fb6684ec05e5c0562e" title="Check to see if a geom is enabled.">dGeomIsEnabled</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga7c64b8fcae37ee9541208a0351f3d05"></a><!-- doxytag: member="collision.h::dGeomEnable" ref="ga7c64b8fcae37ee9541208a0351f3d05" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomEnable           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Enable a geom. 
+<p>
+Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2, although they can still be members of a space. New geoms are created in the enabled state.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to enable </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g6cb32b4161435fe491859680b463fc12" title="Disable a geom.">dGeomDisable</a> <p>
+<a class="el" href="group__collide.html#g6533d33f870cf0fb6684ec05e5c0562e" title="Check to see if a geom is enabled.">dGeomIsEnabled</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g904e360ac6e9e85a05e67929990e5b72"></a><!-- doxytag: member="collision.h::dGeomGetAABB" ref="g904e360ac6e9e85a05e67929990e5b72" args="(dGeomID geom, dReal aabb[6])" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomGetAABB           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>aabb</em>[6]</td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the axis-aligned bounding box. 
+<p>
+Return in aabb an axis aligned bounding box that surrounds the given geom. The aabb array has elements (minx, maxx, miny, maxy, minz, maxz). If the geom is a space, a bounding box that surrounds all contained geoms is returned.<p>
+This function may return a pre-computed cached bounding box, if it can determine that the geom has not moved since the last time the bounding box was computed.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>aabb</em>&nbsp;</td><td>the returned bounding box </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd6cedf77fde0dddf751c5d42fcc8eebf"></a><!-- doxytag: member="collision.h::dGeomGetBody" ref="gd6cedf77fde0dddf751c5d42fcc8eebf" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dBodyID dGeomGetBody           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the body associated with a placeable geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g97cad1194789477eac19fe364d986505" title="Set the body associated with a placeable geom.">dGeomSetBody</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfb62d3493b6789382f65776ab931e78d"></a><!-- doxytag: member="collision.h::dGeomGetCategoryBits" ref="gfb62d3493b6789382f65776ab931e78d" args="(dGeomID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API unsigned long dGeomGetCategoryBits           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the "category" bitfield for the given geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bits</em>&nbsp;</td><td>the new bitfield value </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g80fd5741701eb48472521780d5e2f9b9" title="Set the &quot;category&quot; bitfield for the given geom.">dGeomSetCategoryBits</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g07b5ed5b915f756f419a4a7ce69dc67e"></a><!-- doxytag: member="collision.h::dGeomGetClass" ref="g07b5ed5b915f756f419a4a7ce69dc67e" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dGeomGetClass           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Given a geom, this returns its class. 
+<p>
+The ODE classes are: <ul>
+<li>dSphereClass </li>
+<li>dBoxClass </li>
+<li>dCylinderClass </li>
+<li>dPlaneClass </li>
+<li>dRayClass </li>
+<li>dConvexClass </li>
+<li>dGeomTransformClass </li>
+<li>dTriMeshClass </li>
+<li>dSimpleSpaceClass </li>
+<li>dHashSpaceClass </li>
+<li>dQuadTreeSpaceClass </li>
+<li>dFirstUserClass </li>
+<li>dLastUserClass</li>
+</ul>
+User-defined class will return their own number.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The geom class ID. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g5591e5c496a5a6f8b66dc57e03d0cd8d"></a><!-- doxytag: member="collision.h::dGeomGetCollideBits" ref="g5591e5c496a5a6f8b66dc57e03d0cd8d" args="(dGeomID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API unsigned long dGeomGetCollideBits           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the "collide" bitfield for the given geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bits</em>&nbsp;</td><td>the new bitfield value </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#ga55b4de01a61be41668685857b78455d" title="Set the &quot;collide&quot; bitfield for the given geom.">dGeomSetCollideBits</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc1a185e22b136814fd3afc8469d98996"></a><!-- doxytag: member="collision.h::dGeomGetData" ref="gc1a185e22b136814fd3afc8469d98996" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void* dGeomGetData           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the user-defined data pointer stored in the geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom containing the data </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb200f73800d253ab3a87f9856d4e18d2"></a><!-- doxytag: member="collision.h::dGeomGetOffsetPosition" ref="gb200f73800d253ab3a87f9856d4e18d2" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dGeomGetOffsetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the offset position vector of a geom. 
+<p>
+Returns the positional offset of the geom in local coordinates. If the geom has no offset, this function returns the zero vector.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the geom's offset vector. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The returned value is a pointer to the geom's internal data structure. It is valid until any changes are made to the geom. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8fc20f761daf36976e50d057cf2650ca"></a><!-- doxytag: member="collision.h::dGeomGetOffsetQuaternion" ref="g8fc20f761daf36976e50d057cf2650ca" args="(dGeomID geom, dQuaternion result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomGetOffsetQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dQuaternion&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the offset rotation quaternion of a geom. 
+<p>
+Returns the rotation offset of the geom as a quaternion. If the geom has no offset, the identity quaternion is returned.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>a copy of the rotation quaternion. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gba28cf4ca8f552c782fc30ce3073dc73"></a><!-- doxytag: member="collision.h::dGeomGetOffsetRotation" ref="gba28cf4ca8f552c782fc30ce3073dc73" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dGeomGetOffsetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the offset rotation matrix of a geom. 
+<p>
+Returns the rotational offset of the geom in local coordinates. If the geom has no offset, this function returns the identity matrix.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the geom's offset rotation matrix. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The returned value is a pointer to the geom's internal data structure. It is valid until any changes are made to the geom. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g95b93f803880cac2619fe2635aa93ad8"></a><!-- doxytag: member="collision.h::dGeomGetPosition" ref="g95b93f803880cac2619fe2635aa93ad8" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dGeomGetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the position vector of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's position will be returned.<p>
+Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the geom's position vector. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The returned value is a pointer to the geom's internal data structure. It is valid until any changes are made to the geom. </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#g2bddae29591b9f14c5175411b783d570" title="Get the position of a body.">dBodyGetPosition</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g11ad7f0098639b06f4bcd2d681122842"></a><!-- doxytag: member="collision.h::dGeomGetQuaternion" ref="g11ad7f0098639b06f4bcd2d681122842" args="(dGeomID geom, dQuaternion result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomGetQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dQuaternion&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the rotation quaternion of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's quaternion will be returned.<p>
+Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>a copy of the rotation quaternion. </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#g36b7e19622ed47fe6b9dcfbac20237e7" title="Get the rotation of a body.">dBodyGetQuaternion</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g293b2264cefb12f9a6659cacc6a722f7"></a><!-- doxytag: member="collision.h::dGeomGetRotation" ref="g293b2264cefb12f9a6659cacc6a722f7" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API const dReal* dGeomGetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the rotation matrix of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's rotation will be returned.<p>
+Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the geom's rotation matrix. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The returned value is a pointer to the geom's internal data structure. It is valid until any changes are made to the geom. </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#g2374da7ff88a2bac607e2fbce529ad27" title="Get the rotation of a body.">dBodyGetRotation</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfdc35eade2cbd0b6886ce957325d7c03"></a><!-- doxytag: member="collision.h::dGeomGetSpace" ref="gfdc35eade2cbd0b6886ce957325d7c03" args="(dGeomID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dSpaceID dGeomGetSpace           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Query for the space containing a particular geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The space that contains the geom, or NULL if the geom is not contained by a space. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2c15b7c1a36c7526b66911beab1b7934"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataBuildByte" ref="g2c15b7c1a36c7526b66911beab1b7934" args="(dHeightfieldDataID d, const unsigned char *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataBuildByte           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const unsigned char *&nbsp;</td>
+          <td class="paramname"> <em>pHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bCopyHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>width</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>depth</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>widthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>depthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>scale</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>thickness</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bWrap</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Configures a dHeightfieldDataID to use height data in byte format. 
+<p>
+Before a dHeightfieldDataID can be used by a geom it must be configured to specify the format of the height data. This call specifies that the heightfield data is stored as a rectangular array of bytes (8 bit unsigned) representing the height at each sample point.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A new dHeightfieldDataID created by dGeomHeightfieldDataCreate</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pHeightData</em>&nbsp;</td><td>A pointer to the height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bCopyHeightData</em>&nbsp;</td><td>When non-zero the height data is copied to an internal store. When zero the height data is accessed by reference and so must persist throughout the lifetime of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>width</em>&nbsp;</td><td>Specifies the total 'width' of the heightfield along the geom's local x axis. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depth</em>&nbsp;</td><td>Specifies the total 'depth' of the heightfield along the geom's local z axis.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>widthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the width of the heightfield. Each vertex has a corresponding height value which forms the overall shape. Naturally this value must be at least two or more. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the depth of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>scale</em>&nbsp;</td><td>A uniform scale applied to all raw height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>offset</em>&nbsp;</td><td>An offset applied to the scaled height data.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>thickness</em>&nbsp;</td><td>A value subtracted from the lowest height value which in effect adds an additional cuboid to the base of the heightfield. This is used to prevent geoms from looping under the desired terrain and not registering as a collision. Note that the thickness is not affected by the scale or offset parameters.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bWrap</em>&nbsp;</td><td>If non-zero the heightfield will infinitely tile in both directions along the local x and z axes. If zero the heightfield is bounded from zero to width in the local x axis, and zero to depth in the local z axis. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g34566000a5a2673cc013294f0ed85926"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataBuildCallback" ref="g34566000a5a2673cc013294f0ed85926" args="(dHeightfieldDataID d, void *pUserData, dHeightfieldGetHeight *pCallback, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataBuildCallback           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&nbsp;</td>
+          <td class="paramname"> <em>pUserData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="group__collide.html#g32d2c58e3b2b589bd7672f3453102eb9">dHeightfieldGetHeight</a> *&nbsp;</td>
+          <td class="paramname"> <em>pCallback</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>width</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>depth</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>widthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>depthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>scale</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>thickness</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bWrap</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Configures a dHeightfieldDataID to use a callback to retrieve height data. 
+<p>
+Before a dHeightfieldDataID can be used by a geom it must be configured to specify the format of the height data. This call specifies that the heightfield data is computed by the user and it should use the given callback when determining the height of a given element of it's shape.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A new dHeightfieldDataID created by dGeomHeightfieldDataCreate</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>width</em>&nbsp;</td><td>Specifies the total 'width' of the heightfield along the geom's local x axis. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depth</em>&nbsp;</td><td>Specifies the total 'depth' of the heightfield along the geom's local z axis.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>widthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the width of the heightfield. Each vertex has a corresponding height value which forms the overall shape. Naturally this value must be at least two or more. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the depth of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>scale</em>&nbsp;</td><td>A uniform scale applied to all raw height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>offset</em>&nbsp;</td><td>An offset applied to the scaled height data.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>thickness</em>&nbsp;</td><td>A value subtracted from the lowest height value which in effect adds an additional cuboid to the base of the heightfield. This is used to prevent geoms from looping under the desired terrain and not registering as a collision. Note that the thickness is not affected by the scale or offset parameters.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bWrap</em>&nbsp;</td><td>If non-zero the heightfield will infinitely tile in both directions along the local x and z axes. If zero the heightfield is bounded from zero to width in the local x axis, and zero to depth in the local z axis. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g98ec0c952b3b4e0fb3cd8cf66e267c86"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataBuildDouble" ref="g98ec0c952b3b4e0fb3cd8cf66e267c86" args="(dHeightfieldDataID d, const double *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataBuildDouble           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const double *&nbsp;</td>
+          <td class="paramname"> <em>pHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bCopyHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>width</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>depth</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>widthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>depthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>scale</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>thickness</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bWrap</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Configures a dHeightfieldDataID to use height data in double precision floating point format. 
+<p>
+Before a dHeightfieldDataID can be used by a geom it must be configured to specify the format of the height data. This call specifies that the heightfield data is stored as a rectangular array of double precision floats representing the height at each sample point.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A new dHeightfieldDataID created by dGeomHeightfieldDataCreate</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pHeightData</em>&nbsp;</td><td>A pointer to the height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bCopyHeightData</em>&nbsp;</td><td>When non-zero the height data is copied to an internal store. When zero the height data is accessed by reference and so must persist throughout the lifetime of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>width</em>&nbsp;</td><td>Specifies the total 'width' of the heightfield along the geom's local x axis. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depth</em>&nbsp;</td><td>Specifies the total 'depth' of the heightfield along the geom's local z axis.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>widthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the width of the heightfield. Each vertex has a corresponding height value which forms the overall shape. Naturally this value must be at least two or more. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the depth of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>scale</em>&nbsp;</td><td>A uniform scale applied to all raw height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>offset</em>&nbsp;</td><td>An offset applied to the scaled height data.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>thickness</em>&nbsp;</td><td>A value subtracted from the lowest height value which in effect adds an additional cuboid to the base of the heightfield. This is used to prevent geoms from looping under the desired terrain and not registering as a collision. Note that the thickness is not affected by the scale or offset parameters.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bWrap</em>&nbsp;</td><td>If non-zero the heightfield will infinitely tile in both directions along the local x and z axes. If zero the heightfield is bounded from zero to width in the local x axis, and zero to depth in the local z axis. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2f7582d64cc8219141bc10efeca86d17"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataBuildShort" ref="g2f7582d64cc8219141bc10efeca86d17" args="(dHeightfieldDataID d, const short *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataBuildShort           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const short *&nbsp;</td>
+          <td class="paramname"> <em>pHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bCopyHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>width</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>depth</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>widthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>depthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>scale</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>thickness</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bWrap</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Configures a dHeightfieldDataID to use height data in short format. 
+<p>
+Before a dHeightfieldDataID can be used by a geom it must be configured to specify the format of the height data. This call specifies that the heightfield data is stored as a rectangular array of shorts (16 bit signed) representing the height at each sample point.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A new dHeightfieldDataID created by dGeomHeightfieldDataCreate</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pHeightData</em>&nbsp;</td><td>A pointer to the height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bCopyHeightData</em>&nbsp;</td><td>When non-zero the height data is copied to an internal store. When zero the height data is accessed by reference and so must persist throughout the lifetime of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>width</em>&nbsp;</td><td>Specifies the total 'width' of the heightfield along the geom's local x axis. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depth</em>&nbsp;</td><td>Specifies the total 'depth' of the heightfield along the geom's local z axis.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>widthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the width of the heightfield. Each vertex has a corresponding height value which forms the overall shape. Naturally this value must be at least two or more. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the depth of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>scale</em>&nbsp;</td><td>A uniform scale applied to all raw height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>offset</em>&nbsp;</td><td>An offset applied to the scaled height data.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>thickness</em>&nbsp;</td><td>A value subtracted from the lowest height value which in effect adds an additional cuboid to the base of the heightfield. This is used to prevent geoms from looping under the desired terrain and not registering as a collision. Note that the thickness is not affected by the scale or offset parameters.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bWrap</em>&nbsp;</td><td>If non-zero the heightfield will infinitely tile in both directions along the local x and z axes. If zero the heightfield is bounded from zero to width in the local x axis, and zero to depth in the local z axis. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8da529419317e7bd4e01dabbe94daa09"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataBuildSingle" ref="g8da529419317e7bd4e01dabbe94daa09" args="(dHeightfieldDataID d, const float *pHeightData, int bCopyHeightData, dReal width, dReal depth, int widthSamples, int depthSamples, dReal scale, dReal offset, dReal thickness, int bWrap)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataBuildSingle           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float *&nbsp;</td>
+          <td class="paramname"> <em>pHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bCopyHeightData</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>width</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>depth</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>widthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>depthSamples</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>scale</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>thickness</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>bWrap</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Configures a dHeightfieldDataID to use height data in single precision floating point format. 
+<p>
+Before a dHeightfieldDataID can be used by a geom it must be configured to specify the format of the height data. This call specifies that the heightfield data is stored as a rectangular array of single precision floats representing the height at each sample point.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A new dHeightfieldDataID created by dGeomHeightfieldDataCreate</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>pHeightData</em>&nbsp;</td><td>A pointer to the height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bCopyHeightData</em>&nbsp;</td><td>When non-zero the height data is copied to an internal store. When zero the height data is accessed by reference and so must persist throughout the lifetime of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>width</em>&nbsp;</td><td>Specifies the total 'width' of the heightfield along the geom's local x axis. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depth</em>&nbsp;</td><td>Specifies the total 'depth' of the heightfield along the geom's local z axis.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>widthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the width of the heightfield. Each vertex has a corresponding height value which forms the overall shape. Naturally this value must be at least two or more. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>depthSamples</em>&nbsp;</td><td>Specifies the number of vertices to sample along the depth of the heightfield.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>scale</em>&nbsp;</td><td>A uniform scale applied to all raw height data. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>offset</em>&nbsp;</td><td>An offset applied to the scaled height data.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>thickness</em>&nbsp;</td><td>A value subtracted from the lowest height value which in effect adds an additional cuboid to the base of the heightfield. This is used to prevent geoms from looping under the desired terrain and not registering as a collision. Note that the thickness is not affected by the scale or offset parameters.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bWrap</em>&nbsp;</td><td>If non-zero the heightfield will infinitely tile in both directions along the local x and z axes. If zero the heightfield is bounded from zero to width in the local x axis, and zero to depth in the local z axis. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7de82d5cf9aa10bb3144d51f4360eea1"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataCreate" ref="g7de82d5cf9aa10bb3144d51f4360eea1" args="()" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dHeightfieldDataID dGeomHeightfieldDataCreate           </td>
+          <td>(</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a new empty dHeightfieldDataID. 
+<p>
+Allocates a new dHeightfieldDataID and returns it. You must call dGeomHeightfieldDataDestroy to destroy it after the geom has been removed. The dHeightfieldDataID value is used when specifying a data format type.<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A dHeightfieldDataID for use with dGeomHeightfieldDataBuildCallback, dGeomHeightfieldDataBuildByte, dGeomHeightfieldDataBuildShort or dGeomHeightfieldDataBuildFloat. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf98fc1f3d1784df5a5dff114b483d408"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataDestroy" ref="gf98fc1f3d1784df5a5dff114b483d408" args="(dHeightfieldDataID d)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataDestroy           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Destroys a dHeightfieldDataID. 
+<p>
+Deallocates a given dHeightfieldDataID and all managed resources.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A dHeightfieldDataID created by dGeomHeightfieldDataCreate </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gcdef420e65e3751388b315f5de2804b2"></a><!-- doxytag: member="collision.h::dGeomHeightfieldDataSetBounds" ref="gcdef420e65e3751388b315f5de2804b2" args="(dHeightfieldDataID d, dReal minHeight, dReal maxHeight)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldDataSetBounds           </td>
+          <td>(</td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>minHeight</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>maxHeight</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Manually set the minimum and maximum height bounds. 
+<p>
+This call allows you to set explicit min / max values after initial creation typically for callback heightfields which default to +/- infinity, or those whose data has changed. This must be set prior to binding with a geom, as the the AABB is not recomputed after it's first generation.<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The minimum and maximum values are used to compute the AABB for the heightfield which is used for early rejection of collisions. A close fit will yield a more efficient collision check.</dd></dl>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A dHeightfieldDataID created by dGeomHeightfieldDataCreate </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>min_height</em>&nbsp;</td><td>The new minimum height value. Scale, offset and thickness is then applied. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>max_height</em>&nbsp;</td><td>The new maximum height value. Scale and offset is then applied. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g747176d26ce4f9b10ebfa6c865ef1cca"></a><!-- doxytag: member="collision.h::dGeomHeightfieldGetHeightfieldData" ref="g747176d26ce4f9b10ebfa6c865ef1cca" args="(dGeomID g)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dHeightfieldDataID dGeomHeightfieldGetHeightfieldData           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>g</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the dHeightfieldDataID bound to a heightfield geom. 
+<p>
+Returns the dHeightfieldDataID associated with a heightfield geom.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>g</em>&nbsp;</td><td>A geom created by dCreateHeightfield </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The dHeightfieldDataID which may be NULL if none was assigned. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g6c1ae1f3ca652d6410e7804cdf8f8491"></a><!-- doxytag: member="collision.h::dGeomHeightfieldSetHeightfieldData" ref="g6c1ae1f3ca652d6410e7804cdf8f8491" args="(dGeomID g, dHeightfieldDataID d)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomHeightfieldSetHeightfieldData           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>g</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dHeightfieldDataID&nbsp;</td>
+          <td class="paramname"> <em>d</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Assigns a dHeightfieldDataID to a heightfield geom. 
+<p>
+Associates the given dHeightfieldDataID with a heightfield geom. This is done without affecting the GEOM_PLACEABLE flag.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>g</em>&nbsp;</td><td>A geom created by dCreateHeightfield </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>A dHeightfieldDataID created by dGeomHeightfieldDataCreate </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g6533d33f870cf0fb6684ec05e5c0562e"></a><!-- doxytag: member="collision.h::dGeomIsEnabled" ref="g6533d33f870cf0fb6684ec05e5c0562e" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dGeomIsEnabled           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Check to see if a geom is enabled. 
+<p>
+Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2, although they can still be members of a space. New geoms are created in the enabled state.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>Non-zero if the geom is enabled, zero otherwise. </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g6cb32b4161435fe491859680b463fc12" title="Disable a geom.">dGeomDisable</a> <p>
+<a class="el" href="group__collide.html#g6533d33f870cf0fb6684ec05e5c0562e" title="Check to see if a geom is enabled.">dGeomIsEnabled</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g46260e0668373aa600b1cf8f83276e10"></a><!-- doxytag: member="collision.h::dGeomIsOffset" ref="g46260e0668373aa600b1cf8f83276e10" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dGeomIsOffset           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Check to see whether the geom has an offset. 
+<p>
+This function will return non-zero if the offset has been created. Note that there is a difference between a geom with no offset, and a geom with an offset that is the identity transform. In the latter case, although the observed behaviour is identical, there is a unnecessary computation involved because the geom will be applying the transform whenever it needs to recalculate its world position.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query. </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>Non-zero if the geom has an offset, zero otherwise. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ge5a58bdc78fb4f163a0e9c3ecabf64c9"></a><!-- doxytag: member="collision.h::dGeomIsSpace" ref="ge5a58bdc78fb4f163a0e9c3ecabf64c9" args="(dGeomID geom)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dGeomIsSpace           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Determing if a geom is a space. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to query </td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>Non-zero if the geom is a space, zero otherwise. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g97cad1194789477eac19fe364d986505"></a><!-- doxytag: member="collision.h::dGeomSetBody" ref="g97cad1194789477eac19fe364d986505" args="(dGeomID geom, dBodyID body)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetBody           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the body associated with a placeable geom. 
+<p>
+Setting a body on a geom automatically combines the position vector and rotation matrix of the body and geom, so that setting the position or orientation of one will set the value for both objects. Setting a body ID of zero gives the geom its own position and rotation, independent from any body. If the geom was previously connected to a body then its new independent position/rotation is set to the current position/rotation of the body.<p>
+Calling these functions on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to connect </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>body</em>&nbsp;</td><td>the body to attach to the geom </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g80fd5741701eb48472521780d5e2f9b9"></a><!-- doxytag: member="collision.h::dGeomSetCategoryBits" ref="g80fd5741701eb48472521780d5e2f9b9" args="(dGeomID geom, unsigned long bits)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetCategoryBits           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">unsigned long&nbsp;</td>
+          <td class="paramname"> <em>bits</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the "category" bitfield for the given geom. 
+<p>
+The category bitfield is used by spaces to govern which geoms will interact with each other. The bitfield is guaranteed to be at least 32 bits wide. The default category values for newly created geoms have all bits set.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bits</em>&nbsp;</td><td>the new bitfield value </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga55b4de01a61be41668685857b78455d"></a><!-- doxytag: member="collision.h::dGeomSetCollideBits" ref="ga55b4de01a61be41668685857b78455d" args="(dGeomID geom, unsigned long bits)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetCollideBits           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">unsigned long&nbsp;</td>
+          <td class="paramname"> <em>bits</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the "collide" bitfield for the given geom. 
+<p>
+The collide bitfield is used by spaces to govern which geoms will interact with each other. The bitfield is guaranteed to be at least 32 bits wide. The default category values for newly created geoms have all bits set.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>bits</em>&nbsp;</td><td>the new bitfield value </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf68eb443d5c66ab1aaa8a7d38d1dbc4f"></a><!-- doxytag: member="collision.h::dGeomSetData" ref="gf68eb443d5c66ab1aaa8a7d38d1dbc4f" args="(dGeomID geom, void *data)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetData           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&nbsp;</td>
+          <td class="paramname"> <em>data</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the user-defined data pointer stored in the geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to hold the data </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>the data pointer to be stored </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gdc292bc01d5bed32f145ee42760d73b4"></a><!-- doxytag: member="collision.h::dGeomSetOffsetPosition" ref="gdc292bc01d5bed32f145ee42760d73b4" args="(dGeomID geom, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetOffsetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the local offset position of a geom from its body. 
+<p>
+Sets the geom's positional offset in local coordinates. After this call, the geom will be at a new position determined from the body's position and the offset. The geom must be attached to a body. If the geom did not have an offset, it is automatically created.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>x</em>&nbsp;</td><td>the new X coordinate. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>y</em>&nbsp;</td><td>the new Y coordinate. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>z</em>&nbsp;</td><td>the new Z coordinate. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g9eba87b7598eb6b3a9b6bde1abbeaa1a"></a><!-- doxytag: member="collision.h::dGeomSetOffsetQuaternion" ref="g9eba87b7598eb6b3a9b6bde1abbeaa1a" args="(dGeomID geom, const dQuaternion Q)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetOffsetQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dQuaternion&nbsp;</td>
+          <td class="paramname"> <em>Q</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the local offset rotation of a geom from its body. 
+<p>
+Sets the geom's rotational offset in local coordinates. After this call, the geom will be at a new position determined from the body's position and the offset. The geom must be attached to a body. If the geom did not have an offset, it is automatically created.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>Q</em>&nbsp;</td><td>the new rotation. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g805d896b4bc79ceb40e70aadb9629cab"></a><!-- doxytag: member="collision.h::dGeomSetOffsetRotation" ref="g805d896b4bc79ceb40e70aadb9629cab" args="(dGeomID geom, const dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetOffsetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the local offset rotation matrix of a geom from its body. 
+<p>
+Sets the geom's rotational offset in local coordinates. After this call, the geom will be at a new position determined from the body's position and the offset. The geom must be attached to a body. If the geom did not have an offset, it is automatically created.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>the new rotation matrix. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g934fe31c543d588991d28cd8571e52ed"></a><!-- doxytag: member="collision.h::dGeomSetOffsetWorldPosition" ref="g934fe31c543d588991d28cd8571e52ed" args="(dGeomID geom, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetOffsetWorldPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the offset position of a geom from its body. 
+<p>
+Sets the geom's positional offset to move it to the new world coordinates. After this call, the geom will be at the world position passed in, and the offset will be the difference from the current body position. The geom must be attached to a body. If the geom did not have an offset, it is automatically created.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>x</em>&nbsp;</td><td>the new X coordinate. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>y</em>&nbsp;</td><td>the new Y coordinate. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>z</em>&nbsp;</td><td>the new Z coordinate. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga04f2117ab18a1d3e27270defdad83a8"></a><!-- doxytag: member="collision.h::dGeomSetOffsetWorldQuaternion" ref="ga04f2117ab18a1d3e27270defdad83a8" args="(dGeomID geom, const dQuaternion)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetOffsetWorldQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const &nbsp;</td>
+          <td class="paramname"> <em>dQuaternion</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the offset rotation of a geom from its body. 
+<p>
+Sets the geom's rotational offset to orient it to the new world rotation matrix. After this call, the geom will be at the world orientation passed in, and the offset will be the difference from the current body orientation. The geom must be attached to a body. If the geom did not have an offset, it is automatically created.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>Q</em>&nbsp;</td><td>the new rotation. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2c1ef27e7e8ced6eb8488221a1a7c200"></a><!-- doxytag: member="collision.h::dGeomSetOffsetWorldRotation" ref="g2c1ef27e7e8ced6eb8488221a1a7c200" args="(dGeomID geom, const dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetOffsetWorldRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the offset rotation of a geom from its body. 
+<p>
+Sets the geom's rotational offset to orient it to the new world rotation matrix. After this call, the geom will be at the world orientation passed in, and the offset will be the difference from the current body orientation. The geom must be attached to a body. If the geom did not have an offset, it is automatically created.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>the new rotation matrix. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g71043b70a735e8f5451c3e13cef345fe"></a><!-- doxytag: member="collision.h::dGeomSetPosition" ref="g71043b70a735e8f5451c3e13cef345fe" args="(dGeomID geom, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the position vector of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's position will also be changed. Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>x</em>&nbsp;</td><td>the new X coordinate. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>y</em>&nbsp;</td><td>the new Y coordinate. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>z</em>&nbsp;</td><td>the new Z coordinate. </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#gb84612b793366f18ff5b5cbdbed092da" title="Set position of a body.">dBodySetPosition</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g989149d93162264d699444a57b045150"></a><!-- doxytag: member="collision.h::dGeomSetQuaternion" ref="g989149d93162264d699444a57b045150" args="(dGeomID geom, const dQuaternion Q)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetQuaternion           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dQuaternion&nbsp;</td>
+          <td class="paramname"> <em>Q</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the rotation of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's rotation will also be changed.<p>
+Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>Q</em>&nbsp;</td><td>the new rotation. </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#ga5f51dd3605c402320e9eae4231d7ad4" title="Set the orientation of a body.">dBodySetQuaternion</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g76c510f4b7d5a036d8a36f2d60d670e5"></a><!-- doxytag: member="collision.h::dGeomSetRotation" ref="g76c510f4b7d5a036d8a36f2d60d670e5" args="(dGeomID geom, const dMatrix3 R)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSetRotation           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>geom</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dMatrix3&nbsp;</td>
+          <td class="paramname"> <em>R</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the rotation matrix of a placeable geom. 
+<p>
+If the geom is attached to a body, the body's rotation will also be changed. Calling this function on a non-placeable geom results in a runtime error in the debug build of ODE.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>geom</em>&nbsp;</td><td>the geom to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>the new rotation matrix. </td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__bodies.html#gb5f04968ec37ef46d2aaffad6c344468" title="Set the orientation of a body.">dBodySetRotation</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfd185829b6940e2b3238517e1acd2fbb"></a><!-- doxytag: member="collision.h::dSpaceCollide" ref="gfd185829b6940e2b3238517e1acd2fbb" args="(dSpaceID space, void *data, dNearCallback *callback)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dSpaceCollide           </td>
+          <td>(</td>
+          <td class="paramtype">dSpaceID&nbsp;</td>
+          <td class="paramname"> <em>space</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&nbsp;</td>
+          <td class="paramname"> <em>data</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a> *&nbsp;</td>
+          <td class="paramname"> <em>callback</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Determines which pairs of geoms in a space may potentially intersect, and calls the callback function for each candidate pair. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>space</em>&nbsp;</td><td>The space to test.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>Passed from dSpaceCollide directly to the callback function. Its meaning is user defined. The o1 and o2 arguments are the geoms that may be near each other.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>callback</em>&nbsp;</td><td>A callback function is of type <a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a>.</td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Other spaces that are contained within the colliding space are not treated specially, i.e. they are not recursed into. The callback function may be passed these contained spaces as one or both geom arguments.<p>
+<a class="el" href="group__collide.html#gfd185829b6940e2b3238517e1acd2fbb" title="Determines which pairs of geoms in a space may potentially intersect, and calls the...">dSpaceCollide()</a> is guaranteed to pass all intersecting geom pairs to the callback function, but may also pass close but non-intersecting pairs. The number of these calls depends on the internal algorithms used by the space. Thus you should not expect that dCollide will return contacts for every pair passed to the callback.</dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g72a6bb0b550d3e181f8b7a9be7179db5" title="Determines which geoms from one space may potentially intersect with geoms from another...">dSpaceCollide2</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g72a6bb0b550d3e181f8b7a9be7179db5"></a><!-- doxytag: member="collision.h::dSpaceCollide2" ref="g72a6bb0b550d3e181f8b7a9be7179db5" args="(dGeomID space1, dGeomID space2, void *data, dNearCallback *callback)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dSpaceCollide2           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>space1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>space2</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&nbsp;</td>
+          <td class="paramname"> <em>data</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a> *&nbsp;</td>
+          <td class="paramname"> <em>callback</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Determines which geoms from one space may potentially intersect with geoms from another space, and calls the callback function for each candidate pair. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>space1</em>&nbsp;</td><td>The first space to test.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>space2</em>&nbsp;</td><td>The second space to test.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>Passed from dSpaceCollide directly to the callback function. Its meaning is user defined. The o1 and o2 arguments are the geoms that may be near each other.</td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>callback</em>&nbsp;</td><td>A callback function is of type <a class="el" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0">dNearCallback</a>.</td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This function can also test a single non-space geom against a space. This function is useful when there is a collision hierarchy, i.e. when there are spaces that contain other spaces.<p>
+Other spaces that are contained within the colliding space are not treated specially, i.e. they are not recursed into. The callback function may be passed these contained spaces as one or both geom arguments.<p>
+<a class="el" href="group__collide.html#g72a6bb0b550d3e181f8b7a9be7179db5" title="Determines which geoms from one space may potentially intersect with geoms from another...">dSpaceCollide2()</a> is guaranteed to pass all intersecting geom pairs to the callback function, but may also pass close but non-intersecting pairs. The number of these calls depends on the internal algorithms used by the space. Thus you should not expect that dCollide will return contacts for every pair passed to the callback.</dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#gfd185829b6940e2b3238517e1acd2fbb" title="Determines which pairs of geoms in a space may potentially intersect, and calls the...">dSpaceCollide</a> </dd></dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__collide__box.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__collide__box.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__collide__box.html	(revision 216)
@@ -0,0 +1,182 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Box Class</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Box Class<br>
+<small>
+[<a class="el" href="group__collide.html">Collision Detection</a>]</small>
+</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dGeomID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__box.html#g3e3b0b249a8ccd40a9969e3a26548397">dCreateBox</a> (dSpaceID space, dReal lx, dReal ly, dReal lz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a box geom with the provided side lengths.  <a href="#g3e3b0b249a8ccd40a9969e3a26548397"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__box.html#g4c7060780be9eaf74228565910168273">dGeomBoxSetLengths</a> (dGeomID box, dReal lx, dReal ly, dReal lz)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the side lengths of the given box.  <a href="#g4c7060780be9eaf74228565910168273"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__box.html#ge24d9264235d2487b2e2d52b2c62c879">dGeomBoxGetLengths</a> (dGeomID box, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the side lengths of a box.  <a href="#ge24d9264235d2487b2e2d52b2c62c879"></a><br></td></tr>
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g3e3b0b249a8ccd40a9969e3a26548397"></a><!-- doxytag: member="collision.h::dCreateBox" ref="g3e3b0b249a8ccd40a9969e3a26548397" args="(dSpaceID space, dReal lx, dReal ly, dReal lz)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dGeomID dCreateBox           </td>
+          <td>(</td>
+          <td class="paramtype">dSpaceID&nbsp;</td>
+          <td class="paramname"> <em>space</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>lx</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>ly</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>lz</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a box geom with the provided side lengths. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>space</em>&nbsp;</td><td>a space to contain the new geom. May be null. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>lx</em>&nbsp;</td><td>the length of the box along the X axis </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>ly</em>&nbsp;</td><td>the length of the box along the Y axis </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>lz</em>&nbsp;</td><td>the length of the box along the Z axis</td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A new box geom.</dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The point of reference for a box is its center.</dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> <p>
+<a class="el" href="group__collide__box.html#g4c7060780be9eaf74228565910168273" title="Set the side lengths of the given box.">dGeomBoxSetLengths</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ge24d9264235d2487b2e2d52b2c62c879"></a><!-- doxytag: member="collision.h::dGeomBoxGetLengths" ref="ge24d9264235d2487b2e2d52b2c62c879" args="(dGeomID box, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomBoxGetLengths           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>box</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the side lengths of a box. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>box</em>&nbsp;</td><td>the box to query </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>the returned side lengths</td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide__box.html#g4c7060780be9eaf74228565910168273" title="Set the side lengths of the given box.">dGeomBoxSetLengths</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g4c7060780be9eaf74228565910168273"></a><!-- doxytag: member="collision.h::dGeomBoxSetLengths" ref="g4c7060780be9eaf74228565910168273" args="(dGeomID box, dReal lx, dReal ly, dReal lz)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomBoxSetLengths           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>box</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>lx</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>ly</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>lz</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the side lengths of the given box. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>box</em>&nbsp;</td><td>the box to set </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>lx</em>&nbsp;</td><td>the length of the box along the X axis </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>ly</em>&nbsp;</td><td>the length of the box along the Y axis </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>lz</em>&nbsp;</td><td>the length of the box along the Z axis</td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide__box.html#ge24d9264235d2487b2e2d52b2c62c879" title="Get the side lengths of a box.">dGeomBoxGetLengths</a> </dd></dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__collide__sphere.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__collide__sphere.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__collide__sphere.html	(revision 216)
@@ -0,0 +1,199 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Sphere Class</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Sphere Class<br>
+<small>
+[<a class="el" href="group__collide.html">Collision Detection</a>]</small>
+</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dGeomID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__sphere.html#g53c79c860638ca3600744a193da68474">dCreateSphere</a> (dSpaceID space, dReal radius)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a sphere geom of the given radius, and return its ID.  <a href="#g53c79c860638ca3600744a193da68474"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__sphere.html#g2341ae9b3b733571eff7a1857109f394">dGeomSphereSetRadius</a> (dGeomID sphere, dReal radius)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the radius of a sphere geom.  <a href="#g2341ae9b3b733571eff7a1857109f394"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__sphere.html#g0e7f664deb9f557a6a24f93705b29fa9">dGeomSphereGetRadius</a> (dGeomID sphere)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Retrieves the radius of a sphere geom.  <a href="#g0e7f664deb9f557a6a24f93705b29fa9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__collide__sphere.html#gee86d3744471e447ffc85f85ee6578b1">dGeomSpherePointDepth</a> (dGeomID sphere, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Calculate the depth of the a given point within a sphere.  <a href="#gee86d3744471e447ffc85f85ee6578b1"></a><br></td></tr>
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g53c79c860638ca3600744a193da68474"></a><!-- doxytag: member="collision.h::dCreateSphere" ref="g53c79c860638ca3600744a193da68474" args="(dSpaceID space, dReal radius)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dGeomID dCreateSphere           </td>
+          <td>(</td>
+          <td class="paramtype">dSpaceID&nbsp;</td>
+          <td class="paramname"> <em>space</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>radius</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a sphere geom of the given radius, and return its ID. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>space</em>&nbsp;</td><td>a space to contain the new geom. May be null. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>radius</em>&nbsp;</td><td>the radius of the sphere.</td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A new sphere geom.</dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The point of reference for a sphere is its center.</dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> <p>
+<a class="el" href="group__collide__sphere.html#g2341ae9b3b733571eff7a1857109f394" title="Set the radius of a sphere geom.">dGeomSphereSetRadius</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g0e7f664deb9f557a6a24f93705b29fa9"></a><!-- doxytag: member="collision.h::dGeomSphereGetRadius" ref="g0e7f664deb9f557a6a24f93705b29fa9" args="(dGeomID sphere)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dGeomSphereGetRadius           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>sphere</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrieves the radius of a sphere geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>sphere</em>&nbsp;</td><td>the sphere to query.</td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide__sphere.html#g2341ae9b3b733571eff7a1857109f394" title="Set the radius of a sphere geom.">dGeomSphereSetRadius</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gee86d3744471e447ffc85f85ee6578b1"></a><!-- doxytag: member="collision.h::dGeomSpherePointDepth" ref="gee86d3744471e447ffc85f85ee6578b1" args="(dGeomID sphere, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dGeomSpherePointDepth           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>sphere</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Calculate the depth of the a given point within a sphere. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>sphere</em>&nbsp;</td><td>the sphere to query. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>x</em>&nbsp;</td><td>the X coordinate of the point. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>y</em>&nbsp;</td><td>the Y coordinate of the point. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>z</em>&nbsp;</td><td>the Z coordinate of the point.</td></tr>
+  </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The depth of the point. Points inside the sphere will have a positive depth, points outside it will have a negative depth, and points on the surface will have a depth of zero. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2341ae9b3b733571eff7a1857109f394"></a><!-- doxytag: member="collision.h::dGeomSphereSetRadius" ref="g2341ae9b3b733571eff7a1857109f394" args="(dGeomID sphere, dReal radius)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dGeomSphereSetRadius           </td>
+          <td>(</td>
+          <td class="paramtype">dGeomID&nbsp;</td>
+          <td class="paramname"> <em>sphere</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>radius</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the radius of a sphere geom. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>sphere</em>&nbsp;</td><td>the sphere to set. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>radius</em>&nbsp;</td><td>the new radius.</td></tr>
+  </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__collide__sphere.html#g0e7f664deb9f557a6a24f93705b29fa9" title="Retrieves the radius of a sphere geom.">dGeomSphereGetRadius</a> </dd></dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__disable.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__disable.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__disable.html	(revision 216)
@@ -0,0 +1,563 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Automatic Enabling and Disabling</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Automatic Enabling and Disabling</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g280c6deffe6b4b8ba39d60bf25355347"></a><!-- doxytag: member="disable::dWorldSetAutoEnableDepthSF1" ref="g280c6deffe6b4b8ba39d60bf25355347" args="(dWorldID, int autoEnableDepth)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g280c6deffe6b4b8ba39d60bf25355347">dWorldSetAutoEnableDepthSF1</a> (dWorldID, int autoEnableDepth)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the AutoEnableDepth parameter used by the StepFast1 algorithm. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g5438f43d9c71d8090a44171f685de196"></a><!-- doxytag: member="disable::dWorldGetAutoEnableDepthSF1" ref="g5438f43d9c71d8090a44171f685de196" args="(dWorldID)" -->
+ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g5438f43d9c71d8090a44171f685de196">dWorldGetAutoEnableDepthSF1</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the AutoEnableDepth parameter used by the StepFast1 algorithm. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g48802a9736cc8cc9c1a14cbc3125d9b2">dWorldGetAutoDisableLinearThreshold</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable linear threshold for newly created bodies.  <a href="#g48802a9736cc8cc9c1a14cbc3125d9b2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#ga1070c6f127352fb0a87ab1d42677b8e">dWorldSetAutoDisableLinearThreshold</a> (dWorldID, dReal linear_threshold)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable linear threshold for newly created bodies.  <a href="#ga1070c6f127352fb0a87ab1d42677b8e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g9d32b31b5d343c324897434a97387abc">dWorldGetAutoDisableAngularThreshold</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable angular threshold for newly created bodies.  <a href="#g9d32b31b5d343c324897434a97387abc"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g61cae2bd156129a918c3a1e69ac1b6dd">dWorldSetAutoDisableAngularThreshold</a> (dWorldID, dReal angular_threshold)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable angular threshold for newly created bodies.  <a href="#g61cae2bd156129a918c3a1e69ac1b6dd"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g947e2d43df920a26fb52b5273ea9856b">dWorldGetAutoDisableLinearAverageThreshold</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable linear average threshold for newly created bodies.  <a href="#g947e2d43df920a26fb52b5273ea9856b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g3e5ef82227b955c545efc40d60ef1b21">dWorldSetAutoDisableLinearAverageThreshold</a> (dWorldID, dReal linear_average_threshold)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable linear average threshold for newly created bodies.  <a href="#g3e5ef82227b955c545efc40d60ef1b21"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#gb9bd57f1bef49a8d9d6985462c078b02">dWorldGetAutoDisableAngularAverageThreshold</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable angular average threshold for newly created bodies.  <a href="#gb9bd57f1bef49a8d9d6985462c078b02"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#gca94337cc27914fe4bc00ebce83f231a">dWorldSetAutoDisableAngularAverageThreshold</a> (dWorldID, dReal angular_average_threshold)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable angular average threshold for newly created bodies.  <a href="#gca94337cc27914fe4bc00ebce83f231a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g4343cfd23eb87f3ee629a9d13833c2ac">dWorldGetAutoDisableAverageSamplesCount</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable sample count for newly created bodies.  <a href="#g4343cfd23eb87f3ee629a9d13833c2ac"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g2babd1af3df87518e5bac9dfcb392593">dWorldSetAutoDisableAverageSamplesCount</a> (dWorldID, unsigned int average_samples_count)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable average sample count for newly created bodies.  <a href="#g2babd1af3df87518e5bac9dfcb392593"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#gb0a26f648b9e40d8d4639bf187d5ac94">dWorldGetAutoDisableSteps</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable steps for newly created bodies.  <a href="#gb0a26f648b9e40d8d4639bf187d5ac94"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#gdb9f69119d1aa259a0e32a8ff94e2535">dWorldSetAutoDisableSteps</a> (dWorldID, int steps)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable steps for newly created bodies.  <a href="#gdb9f69119d1aa259a0e32a8ff94e2535"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#gbc004c37efff5f962fa2ac271b3be8e1">dWorldGetAutoDisableTime</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable time for newly created bodies.  <a href="#gbc004c37efff5f962fa2ac271b3be8e1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g06828866a19cab7aeb129ca9ec76863b">dWorldSetAutoDisableTime</a> (dWorldID, dReal time)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable time for newly created bodies.  <a href="#g06828866a19cab7aeb129ca9ec76863b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g7617d19f08c7b1d22cf17ccf22bbdc00">dWorldGetAutoDisableFlag</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get auto disable flag for newly created bodies.  <a href="#g7617d19f08c7b1d22cf17ccf22bbdc00"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__disable.html#g58959b92ae4706e612bca673e85bfc50">dWorldSetAutoDisableFlag</a> (dWorldID, int do_auto_disable)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set auto disable flag for newly created bodies.  <a href="#g58959b92ae4706e612bca673e85bfc50"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Every body can be enabled or disabled. Enabled bodies participate in the simulation, while disabled bodies are turned off and do not get updated during a simulation step. New bodies are always created in the enabled state.<p>
+A disabled body that is connected through a joint to an enabled body will be automatically re-enabled at the next simulation step.<p>
+Disabled bodies do not consume CPU time, therefore to speed up the simulation bodies should be disabled when they come to rest. This can be done automatically with the auto-disable feature.<p>
+If a body has its auto-disable flag turned on, it will automatically disable itself when <ul>
+<li>It has been idle for a given number of simulation steps. </li>
+<li>It has also been idle for a given amount of simulation time.</li>
+</ul>
+A body is considered to be idle when the magnitudes of both its linear average velocity and angular average velocity are below given thresholds. The sample size for the average defaults to one and can be disabled by setting to zero with<p>
+Thus, every body has six auto-disable parameters: an enabled flag, a idle step count, an idle time, linear/angular average velocity thresholds, and the average samples count.<p>
+Newly created bodies get these parameters from world. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="gb9bd57f1bef49a8d9d6985462c078b02"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableAngularAverageThreshold" ref="gb9bd57f1bef49a8d9d6985462c078b02" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetAutoDisableAngularAverageThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable angular average threshold for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g9d32b31b5d343c324897434a97387abc"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableAngularThreshold" ref="g9d32b31b5d343c324897434a97387abc" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetAutoDisableAngularThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable angular threshold for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g4343cfd23eb87f3ee629a9d13833c2ac"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableAverageSamplesCount" ref="g4343cfd23eb87f3ee629a9d13833c2ac" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dWorldGetAutoDisableAverageSamplesCount           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable sample count for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>number of samples used </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7617d19f08c7b1d22cf17ccf22bbdc00"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableFlag" ref="g7617d19f08c7b1d22cf17ccf22bbdc00" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dWorldGetAutoDisableFlag           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable flag for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 or 1 </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g947e2d43df920a26fb52b5273ea9856b"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableLinearAverageThreshold" ref="g947e2d43df920a26fb52b5273ea9856b" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetAutoDisableLinearAverageThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable linear average threshold for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g48802a9736cc8cc9c1a14cbc3125d9b2"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableLinearThreshold" ref="g48802a9736cc8cc9c1a14cbc3125d9b2" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetAutoDisableLinearThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable linear threshold for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the threshold </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb0a26f648b9e40d8d4639bf187d5ac94"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableSteps" ref="gb0a26f648b9e40d8d4639bf187d5ac94" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dWorldGetAutoDisableSteps           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable steps for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>nr of steps </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gbc004c37efff5f962fa2ac271b3be8e1"></a><!-- doxytag: member="objects.h::dWorldGetAutoDisableTime" ref="gbc004c37efff5f962fa2ac271b3be8e1" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetAutoDisableTime           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get auto disable time for newly created bodies. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>nr of seconds </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gca94337cc27914fe4bc00ebce83f231a"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableAngularAverageThreshold" ref="gca94337cc27914fe4bc00ebce83f231a" args="(dWorldID, dReal angular_average_threshold)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableAngularAverageThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>angular_average_threshold</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable angular average threshold for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>linear_average_threshold</em>&nbsp;</td><td>default is 0.01 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g61cae2bd156129a918c3a1e69ac1b6dd"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableAngularThreshold" ref="g61cae2bd156129a918c3a1e69ac1b6dd" args="(dWorldID, dReal angular_threshold)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableAngularThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>angular_threshold</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable angular threshold for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>linear_threshold</em>&nbsp;</td><td>default is 0.01 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2babd1af3df87518e5bac9dfcb392593"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableAverageSamplesCount" ref="g2babd1af3df87518e5bac9dfcb392593" args="(dWorldID, unsigned int average_samples_count)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableAverageSamplesCount           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">unsigned int&nbsp;</td>
+          <td class="paramname"> <em>average_samples_count</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable average sample count for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>average_samples_count</em>&nbsp;</td><td>Default is 1, meaning only instantaneous velocity is used. Set to zero to disable sampling and thus prevent any body from auto-disabling. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g58959b92ae4706e612bca673e85bfc50"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableFlag" ref="g58959b92ae4706e612bca673e85bfc50" args="(dWorldID, int do_auto_disable)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableFlag           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>do_auto_disable</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable flag for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>do_auto_disable</em>&nbsp;</td><td>default is false. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3e5ef82227b955c545efc40d60ef1b21"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableLinearAverageThreshold" ref="g3e5ef82227b955c545efc40d60ef1b21" args="(dWorldID, dReal linear_average_threshold)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableLinearAverageThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>linear_average_threshold</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable linear average threshold for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>linear_average_threshold</em>&nbsp;</td><td>default is 0.01 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga1070c6f127352fb0a87ab1d42677b8e"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableLinearThreshold" ref="ga1070c6f127352fb0a87ab1d42677b8e" args="(dWorldID, dReal linear_threshold)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableLinearThreshold           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>linear_threshold</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable linear threshold for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>linear_threshold</em>&nbsp;</td><td>default is 0.01 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gdb9f69119d1aa259a0e32a8ff94e2535"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableSteps" ref="gdb9f69119d1aa259a0e32a8ff94e2535" args="(dWorldID, int steps)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableSteps           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>steps</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable steps for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>steps</em>&nbsp;</td><td>default is 10 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g06828866a19cab7aeb129ca9ec76863b"></a><!-- doxytag: member="objects.h::dWorldSetAutoDisableTime" ref="g06828866a19cab7aeb129ca9ec76863b" args="(dWorldID, dReal time)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetAutoDisableTime           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>time</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set auto disable time for newly created bodies. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>time</em>&nbsp;</td><td>default is 0 seconds </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__drawstuff.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__drawstuff.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__drawstuff.html	(revision 216)
@@ -0,0 +1,668 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: DrawStuff</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>DrawStuff</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structds_functions.html">dsFunctions</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set of functions to be used as callbacks by the simulation loop.  <a href="structds_functions.html#_details">More...</a><br></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g28560ea1b64c1d83095bcdfce9caf9dc">dsSimulationLoop</a> (int argc, char **argv, int window_width, int window_height, struct <a class="el" href="structds_functions.html">dsFunctions</a> *fn)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Does the complete simulation.  <a href="#g28560ea1b64c1d83095bcdfce9caf9dc"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g7a2a69ac611d5dc6ffc8e43b0a743472">dsError</a> (char *msg,...)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">exit with error message.  <a href="#g7a2a69ac611d5dc6ffc8e43b0a743472"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#ga84175b14c3c31daae08a9c88acc2b02">dsDebug</a> (char *msg,...)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">exit with error message and core dump.  <a href="#ga84175b14c3c31daae08a9c88acc2b02"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#gbca5fa4076aa9e45caa049f33e8cf168">dsPrint</a> (char *msg,...)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">print log message  <a href="#gbca5fa4076aa9e45caa049f33e8cf168"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g8e4ea933c31d207ec57949fbb3a75815">dsSetViewpoint</a> (float xyz[3], float hpr[3])</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Sets the viewpoint.  <a href="#g8e4ea933c31d207ec57949fbb3a75815"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#gaa22f45ad00e0010a1440985ac51b18b">dsGetViewpoint</a> (float xyz[3], float hpr[3])</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Gets the viewpoint.  <a href="#gaa22f45ad00e0010a1440985ac51b18b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g6c13a5a310b9e00c45150058e669ebad">dsStop</a> ()</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Stop the simulation loop.  <a href="#g6c13a5a310b9e00c45150058e669ebad"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API double&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g02f3f096703d49f5a9e497aec0b85f75">dsElapsedTime</a> ()</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the elapsed time (on wall-clock).  <a href="#g02f3f096703d49f5a9e497aec0b85f75"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g8a3d6f8fecc8c7d5a206bed35f17ba7a">dsSetTexture</a> (int texture_number)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Toggle the rendering of textures.  <a href="#g8a3d6f8fecc8c7d5a206bed35f17ba7a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g3221a0d1360621eaad7c54597671c092">dsSetColor</a> (float red, float green, float blue)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the color with which geometry is drawn.  <a href="#g3221a0d1360621eaad7c54597671c092"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g440940cfaef61775e37c33b055b832af">dsSetColorAlpha</a> (float red, float green, float blue, float alpha)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the color and transparency with which geometry is drawn.  <a href="#g440940cfaef61775e37c33b055b832af"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#gfba4fde6b0b74f6cd422036dedd08836">dsDrawBox</a> (const float pos[3], const float R[12], const float sides[3])</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a box.  <a href="#gfba4fde6b0b74f6cd422036dedd08836"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g0802e7641f8028182b69fabc729a6704">dsDrawSphere</a> (const float pos[3], const float R[12], float radius)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a sphere.  <a href="#g0802e7641f8028182b69fabc729a6704"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#gcfcbae15cee67eceb45cd96bf01484d4">dsDrawTriangle</a> (const float pos[3], const float R[12], const float *v0, const float *v1, const float *v2, int solid)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a triangle.  <a href="#gcfcbae15cee67eceb45cd96bf01484d4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g0b09b41f1f6500b293678aa1691f1537"></a><!-- doxytag: member="drawstuff::dsDrawCylinder" ref="g0b09b41f1f6500b293678aa1691f1537" args="(const float pos[3], const float R[12], float length, float radius)" -->
+DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g0b09b41f1f6500b293678aa1691f1537">dsDrawCylinder</a> (const float pos[3], const float R[12], float length, float radius)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a z-aligned cylinder. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gce8f6c8a9f2871dac2f5e7f159b96feb"></a><!-- doxytag: member="drawstuff::dsDrawCapsule" ref="gce8f6c8a9f2871dac2f5e7f159b96feb" args="(const float pos[3], const float R[12], float length, float radius)" -->
+DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#gce8f6c8a9f2871dac2f5e7f159b96feb">dsDrawCapsule</a> (const float pos[3], const float R[12], float length, float radius)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a z-aligned capsule. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g61b166a9b7c04063a27be982051f4af5"></a><!-- doxytag: member="drawstuff::dsDrawLine" ref="g61b166a9b7c04063a27be982051f4af5" args="(const float pos1[3], const float pos2[3])" -->
+DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g61b166a9b7c04063a27be982051f4af5">dsDrawLine</a> (const float pos1[3], const float pos2[3])</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a line. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g4b8754994a4cca9d51fce16445f0d612"></a><!-- doxytag: member="drawstuff::dsDrawConvex" ref="g4b8754994a4cca9d51fce16445f0d612" args="(const float pos[3], const float R[12], float *_planes, unsigned int _planecount, float *_points, unsigned int _pointcount, unsigned int *_polygons)" -->
+DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g4b8754994a4cca9d51fce16445f0d612">dsDrawConvex</a> (const float pos[3], const float R[12], float *_planes, unsigned int _planecount, float *_points, unsigned int _pointcount, unsigned int *_polygons)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Draw a convex shape. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">DS_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__drawstuff.html#g211aa83d5c5d102cdda303cc7aeb2fd5">dsSetSphereQuality</a> (int n)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the quality with which curved objects are rendered.  <a href="#g211aa83d5c5d102cdda303cc7aeb2fd5"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+DrawStuff is a library for rendering simple 3D objects in a virtual environment, for the purposes of demonstrating the features of ODE. It is provided for demonstration purposes and is not intended for production use.<h2><a class="anchor" name="Notes">
+Notes</a></h2>
+In the virtual world, the z axis is "up" and z=0 is the floor.<p>
+The user is able to click+drag in the main window to move the camera: left button - pan and tilt. right button - forward and sideways. left + right button (or middle button) - sideways and up. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="ga84175b14c3c31daae08a9c88acc2b02"></a><!-- doxytag: member="drawstuff.h::dsDebug" ref="ga84175b14c3c31daae08a9c88acc2b02" args="(char *msg,...)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsDebug           </td>
+          <td>(</td>
+          <td class="paramtype">char *&nbsp;</td>
+          <td class="paramname"> <em>msg</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&nbsp;</td>
+          <td class="paramname"> <em>...</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+exit with error message and core dump. 
+<p>
+this functions tries to dump core or start the debugger. <dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>msg</em>&nbsp;</td><td>format strin, like printf, without the newline character. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfba4fde6b0b74f6cd422036dedd08836"></a><!-- doxytag: member="drawstuff.h::dsDrawBox" ref="gfba4fde6b0b74f6cd422036dedd08836" args="(const float pos[3], const float R[12], const float sides[3])" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsDrawBox           </td>
+          <td>(</td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>pos</em>[3], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>R</em>[12], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>sides</em>[3]</td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Draw a box. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>is the x,y,z of the center of the object. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>is a 3x3 rotation matrix for the object, stored by row like this: [ R11 R12 R13 0 ] [ R21 R22 R23 0 ] [ R31 R32 R33 0 ] </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>sides[]</em>&nbsp;</td><td>is an array of x,y,z side lengths. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g0802e7641f8028182b69fabc729a6704"></a><!-- doxytag: member="drawstuff.h::dsDrawSphere" ref="g0802e7641f8028182b69fabc729a6704" args="(const float pos[3], const float R[12], float radius)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsDrawSphere           </td>
+          <td>(</td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>pos</em>[3], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>R</em>[12], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>radius</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Draw a sphere. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>Position of center. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>orientation. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>radius</em>&nbsp;</td><td></td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gcfcbae15cee67eceb45cd96bf01484d4"></a><!-- doxytag: member="drawstuff.h::dsDrawTriangle" ref="gcfcbae15cee67eceb45cd96bf01484d4" args="(const float pos[3], const float R[12], const float *v0, const float *v1, const float *v2, int solid)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsDrawTriangle           </td>
+          <td>(</td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>pos</em>[3], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float&nbsp;</td>
+          <td class="paramname"> <em>R</em>[12], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float *&nbsp;</td>
+          <td class="paramname"> <em>v0</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float *&nbsp;</td>
+          <td class="paramname"> <em>v1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const float *&nbsp;</td>
+          <td class="paramname"> <em>v2</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>solid</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Draw a triangle. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>Position of center </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>R</em>&nbsp;</td><td>orientation </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>v0</em>&nbsp;</td><td>first vertex </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>v1</em>&nbsp;</td><td>second </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>v2</em>&nbsp;</td><td>third vertex </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>solid</em>&nbsp;</td><td>set to 0 for wireframe </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g02f3f096703d49f5a9e497aec0b85f75"></a><!-- doxytag: member="drawstuff.h::dsElapsedTime" ref="g02f3f096703d49f5a9e497aec0b85f75" args="()" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API double dsElapsedTime           </td>
+          <td>(</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the elapsed time (on wall-clock). 
+<p>
+It returns the nr of seconds since the last call to this function. 
+</div>
+</div><p>
+<a class="anchor" name="g7a2a69ac611d5dc6ffc8e43b0a743472"></a><!-- doxytag: member="drawstuff.h::dsError" ref="g7a2a69ac611d5dc6ffc8e43b0a743472" args="(char *msg,...)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsError           </td>
+          <td>(</td>
+          <td class="paramtype">char *&nbsp;</td>
+          <td class="paramname"> <em>msg</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&nbsp;</td>
+          <td class="paramname"> <em>...</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+exit with error message. 
+<p>
+This function displays an error message then exit. <dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>msg</em>&nbsp;</td><td>format strin, like printf, without the newline character. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gaa22f45ad00e0010a1440985ac51b18b"></a><!-- doxytag: member="drawstuff.h::dsGetViewpoint" ref="gaa22f45ad00e0010a1440985ac51b18b" args="(float xyz[3], float hpr[3])" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsGetViewpoint           </td>
+          <td>(</td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>xyz</em>[3], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>hpr</em>[3]</td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the viewpoint. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>xyz</em>&nbsp;</td><td>position </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>hpr</em>&nbsp;</td><td>heading,pitch,roll. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gbca5fa4076aa9e45caa049f33e8cf168"></a><!-- doxytag: member="drawstuff.h::dsPrint" ref="gbca5fa4076aa9e45caa049f33e8cf168" args="(char *msg,...)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsPrint           </td>
+          <td>(</td>
+          <td class="paramtype">char *&nbsp;</td>
+          <td class="paramname"> <em>msg</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&nbsp;</td>
+          <td class="paramname"> <em>...</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+print log message 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>msg</em>&nbsp;</td><td>format string, like printf, without the <br>
+. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3221a0d1360621eaad7c54597671c092"></a><!-- doxytag: member="drawstuff.h::dsSetColor" ref="g3221a0d1360621eaad7c54597671c092" args="(float red, float green, float blue)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsSetColor           </td>
+          <td>(</td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>red</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>green</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>blue</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the color with which geometry is drawn. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>red</em>&nbsp;</td><td>Red component from 0 to 1 </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>green</em>&nbsp;</td><td>Green component from 0 to 1 </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>blue</em>&nbsp;</td><td>Blue component from 0 to 1 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g440940cfaef61775e37c33b055b832af"></a><!-- doxytag: member="drawstuff.h::dsSetColorAlpha" ref="g440940cfaef61775e37c33b055b832af" args="(float red, float green, float blue, float alpha)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsSetColorAlpha           </td>
+          <td>(</td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>red</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>green</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>blue</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>alpha</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the color and transparency with which geometry is drawn. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>alpha</em>&nbsp;</td><td>Note that alpha transparency is a misnomer: it is alpha opacity. 1.0 means fully opaque, and 0.0 means fully transparent. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g211aa83d5c5d102cdda303cc7aeb2fd5"></a><!-- doxytag: member="drawstuff.h::dsSetSphereQuality" ref="g211aa83d5c5d102cdda303cc7aeb2fd5" args="(int n)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsSetSphereQuality           </td>
+          <td>(</td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>n</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the quality with which curved objects are rendered. 
+<p>
+Higher numbers are higher quality, but slower to draw. This must be set before the first objects are drawn to be effective. Default sphere quality is 1, default capsule quality is 3. 
+</div>
+</div><p>
+<a class="anchor" name="g8a3d6f8fecc8c7d5a206bed35f17ba7a"></a><!-- doxytag: member="drawstuff.h::dsSetTexture" ref="g8a3d6f8fecc8c7d5a206bed35f17ba7a" args="(int texture_number)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsSetTexture           </td>
+          <td>(</td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>texture_number</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Toggle the rendering of textures. 
+<p>
+It changes the way objects are drawn. these changes will apply to all further dsDrawXXX() functions. <dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>the</em>&nbsp;</td><td>texture number must be a DS_xxx texture constant. The current texture is colored according to the current color. At the start of each frame, the texture is reset to none and the color is reset to white. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8e4ea933c31d207ec57949fbb3a75815"></a><!-- doxytag: member="drawstuff.h::dsSetViewpoint" ref="g8e4ea933c31d207ec57949fbb3a75815" args="(float xyz[3], float hpr[3])" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsSetViewpoint           </td>
+          <td>(</td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>xyz</em>[3], </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">float&nbsp;</td>
+          <td class="paramname"> <em>hpr</em>[3]</td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the viewpoint. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>xyz</em>&nbsp;</td><td>camera position. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>hpr</em>&nbsp;</td><td>contains heading, pitch and roll numbers in degrees. heading=0 points along the x axis, pitch=0 is looking towards the horizon, and roll 0 is "unrotated". </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g28560ea1b64c1d83095bcdfce9caf9dc"></a><!-- doxytag: member="drawstuff.h::dsSimulationLoop" ref="g28560ea1b64c1d83095bcdfce9caf9dc" args="(int argc, char **argv, int window_width, int window_height, struct dsFunctions *fn)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsSimulationLoop           </td>
+          <td>(</td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>argc</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">char **&nbsp;</td>
+          <td class="paramname"> <em>argv</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>window_width</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>window_height</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">struct <a class="el" href="structds_functions.html">dsFunctions</a> *&nbsp;</td>
+          <td class="paramname"> <em>fn</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Does the complete simulation. 
+<p>
+This function starts running the simulation, and only exits when the simulation is done. Function pointers should be provided for the callbacks. <dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>argv</em>&nbsp;</td><td>supports flags like '-notex' '-noshadow' '-pause' </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>fn</em>&nbsp;</td><td>Callback functions. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g6c13a5a310b9e00c45150058e669ebad"></a><!-- doxytag: member="drawstuff.h::dsStop" ref="g6c13a5a310b9e00c45150058e669ebad" args="()" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">DS_API void dsStop           </td>
+          <td>(</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Stop the simulation loop. 
+<p>
+Calling this from within <a class="el" href="group__drawstuff.html#g28560ea1b64c1d83095bcdfce9caf9dc" title="Does the complete simulation.">dsSimulationLoop()</a> will cause it to exit and return to the caller. it is the same as if the user used the exit command. using this outside the loop will have no effect. 
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__joints.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__joints.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__joints.html	(revision 216)
@@ -0,0 +1,2127 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Joints</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Joints</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g2d23509f8d6c6066b361af4cf14166f7">dJointCreateBall</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the ball type.  <a href="#g2d23509f8d6c6066b361af4cf14166f7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g2f18d431d48c905abc9d72ce011c00bd">dJointCreateHinge</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the hinge type.  <a href="#g2f18d431d48c905abc9d72ce011c00bd"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#geccc4c67b2d409016685a6a9163be539">dJointCreateSlider</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the slider type.  <a href="#geccc4c67b2d409016685a6a9163be539"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gfa5e1543239ba44ecbdc178ebc7c3cc4">dJointCreateContact</a> (dWorldID, dJointGroupID, const dContact *)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the contact type.  <a href="#gfa5e1543239ba44ecbdc178ebc7c3cc4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g6a6e32d35bdda9352d1be8d4df973f8f">dJointCreateHinge2</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the hinge2 type.  <a href="#g6a6e32d35bdda9352d1be8d4df973f8f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g1cb2e7668242313b5d24acb5d43e5c62">dJointCreateUniversal</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the universal type.  <a href="#g1cb2e7668242313b5d24acb5d43e5c62"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gdc867f10ba9931d191244fa879e43cb2">dJointCreatePR</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the PR (Prismatic and Rotoide) type.  <a href="#gdc867f10ba9931d191244fa879e43cb2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ge568995d03077e1acb13882a627dcf32">dJointCreateFixed</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the fixed type.  <a href="#ge568995d03077e1acb13882a627dcf32"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gf23195ce77e12031393e591abd0e28e6">dJointCreateAMotor</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the A-motor type.  <a href="#gf23195ce77e12031393e591abd0e28e6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g21c8c99615269c5d9d3c57c674f6fd56">dJointCreateLMotor</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the L-motor type.  <a href="#g21c8c99615269c5d9d3c57c674f6fd56"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g7e68f39530acad9c0e7a38c8a3799b38">dJointCreatePlane2D</a> (dWorldID, dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new joint of the plane-2d type.  <a href="#g7e68f39530acad9c0e7a38c8a3799b38"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a">dJointDestroy</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Destroy a joint.  <a href="#g2187ccbcf51c951f680eb6c9a210801a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dJointGroupID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gaaec687b184a1214133a41503e7c628f">dJointGroupCreate</a> (int max_size)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a joint group.  <a href="#gaaec687b184a1214133a41503e7c628f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g49e664ee9a8bd7bfe5e6932bf936bb8f">dJointGroupDestroy</a> (dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Destroy a joint group.  <a href="#g49e664ee9a8bd7bfe5e6932bf936bb8f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g6e055bac8a0a3261bda3b6d07499c4ea">dJointGroupEmpty</a> (dJointGroupID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Empty a joint group.  <a href="#g6e055bac8a0a3261bda3b6d07499c4ea"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g8f1c9b1302c799a1b87bc29b76d0dcec">dJointAttach</a> (dJointID, dBodyID body1, dBodyID body2)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Attach the joint to some new bodies.  <a href="#g8f1c9b1302c799a1b87bc29b76d0dcec"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g5ca72d8bd498ef1ba920b0b473e79d02"></a><!-- doxytag: member="joints::dJointSetData" ref="g5ca72d8bd498ef1ba920b0b473e79d02" args="(dJointID, void *data)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g5ca72d8bd498ef1ba920b0b473e79d02">dJointSetData</a> (dJointID, void *data)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the user-data pointer. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g607702a11bae2d2613295f67088b0e82"></a><!-- doxytag: member="joints::dJointGetData" ref="g607702a11bae2d2613295f67088b0e82" args="(dJointID)" -->
+ODE_API void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g607702a11bae2d2613295f67088b0e82">dJointGetData</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the user-data pointer. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g6f12f69d9b1a457428a28c2f77148174">dJointGetType</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the type of the joint.  <a href="#g6f12f69d9b1a457428a28c2f77148174"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dBodyID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gff13cbb464f1bfdc225fc9202c2c54c3">dJointGetBody</a> (dJointID, int index)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Return the bodies that this joint connects.  <a href="#gff13cbb464f1bfdc225fc9202c2c54c3"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g87ddb9beb95e9383a4280cb8a4186f01">dJointSetFeedback</a> (dJointID, dJointFeedback *)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Sets the datastructure that is to receive the feedback.  <a href="#g87ddb9beb95e9383a4280cb8a4186f01"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gda1deef60d7afbb6b9375ddbf97e09a1"></a><!-- doxytag: member="joints::dJointGetFeedback" ref="gda1deef60d7afbb6b9375ddbf97e09a1" args="(dJointID)" -->
+ODE_API dJointFeedback *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gda1deef60d7afbb6b9375ddbf97e09a1">dJointGetFeedback</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Gets the datastructure that is to receive the feedback. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g058c33a3da1ff935a1125034f779dc4a">dJointSetBallAnchor</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the joint anchor point.  <a href="#g058c33a3da1ff935a1125034f779dc4a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g51eb42782182a714be26bbd68f7a6d9a"></a><!-- doxytag: member="joints::dJointSetBallAnchor2" ref="g51eb42782182a714be26bbd68f7a6d9a" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g51eb42782182a714be26bbd68f7a6d9a">dJointSetBallAnchor2</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the joint anchor point. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ge58f5e11c0829aa8615622a74dd11d85"></a><!-- doxytag: member="joints::dJointSetBallParam" ref="ge58f5e11c0829aa8615622a74dd11d85" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ge58f5e11c0829aa8615622a74dd11d85">dJointSetBallParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Param setting for Ball joints. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gc5727a125de0abbe2abd61af7a55da26"></a><!-- doxytag: member="joints::dJointSetHingeAnchor" ref="gc5727a125de0abbe2abd61af7a55da26" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gc5727a125de0abbe2abd61af7a55da26">dJointSetHingeAnchor</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set hinge anchor parameter. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga434229f033472ec7aa031a01c6cabed"></a><!-- doxytag: member="joints::dJointSetHingeAxis" ref="ga434229f033472ec7aa031a01c6cabed" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga434229f033472ec7aa031a01c6cabed">dJointSetHingeAxis</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set hinge axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g6f9d34a01181e65639eb1f67da7a3e4c"></a><!-- doxytag: member="joints::dJointSetHingeParam" ref="g6f9d34a01181e65639eb1f67da7a3e4c" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g6f9d34a01181e65639eb1f67da7a3e4c">dJointSetHingeParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga1725abe170f80b0731321ed38785019">dJointAddHingeTorque</a> (dJointID joint, dReal torque)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Applies the torque about the hinge axis.  <a href="#ga1725abe170f80b0731321ed38785019"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gb2f662b1190507551f49ffa29d276b61"></a><!-- doxytag: member="joints::dJointSetSliderAxis" ref="gb2f662b1190507551f49ffa29d276b61" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gb2f662b1190507551f49ffa29d276b61">dJointSetSliderAxis</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set the joint axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g2a055496df2812ad69d30e2653317f6a"></a><!-- doxytag: member="joints::dJointSetSliderAxisDelta" ref="g2a055496df2812ad69d30e2653317f6a" args="(dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><b>dJointSetSliderAxisDelta</b> (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g648964f4ca4122309e71a9cc6c24c985"></a><!-- doxytag: member="joints::dJointSetSliderParam" ref="g648964f4ca4122309e71a9cc6c24c985" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g648964f4ca4122309e71a9cc6c24c985">dJointSetSliderParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g8b0e018cc3df6ea5ddb42320913455e7">dJointAddSliderForce</a> (dJointID joint, dReal force)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Applies the given force in the slider's direction.  <a href="#g8b0e018cc3df6ea5ddb42320913455e7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gf839c13fa85aff0287a87986ff447d29"></a><!-- doxytag: member="joints::dJointSetHinge2Anchor" ref="gf839c13fa85aff0287a87986ff447d29" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gf839c13fa85aff0287a87986ff447d29">dJointSetHinge2Anchor</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set anchor <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gcdf78fbb0f5b0a09b4d3ac2059b07002"></a><!-- doxytag: member="joints::dJointSetHinge2Axis1" ref="gcdf78fbb0f5b0a09b4d3ac2059b07002" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gcdf78fbb0f5b0a09b4d3ac2059b07002">dJointSetHinge2Axis1</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gdfef9f6365c87dacb95b4850a9e9f0ee"></a><!-- doxytag: member="joints::dJointSetHinge2Axis2" ref="gdfef9f6365c87dacb95b4850a9e9f0ee" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gdfef9f6365c87dacb95b4850a9e9f0ee">dJointSetHinge2Axis2</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g9a2d8d03776ccb22869667337457a7a9"></a><!-- doxytag: member="joints::dJointSetHinge2Param" ref="g9a2d8d03776ccb22869667337457a7a9" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g9a2d8d03776ccb22869667337457a7a9">dJointSetHinge2Param</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga5ba1541d092f28c93b1bdc3bfb1b69f">dJointAddHinge2Torques</a> (dJointID joint, dReal torque1, dReal torque2)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Applies torque1 about the hinge2's axis 1, torque2 about the hinge2's axis 2.  <a href="#ga5ba1541d092f28c93b1bdc3bfb1b69f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gaf4657aed67f3cd7cce775215995c05d"></a><!-- doxytag: member="joints::dJointSetUniversalAnchor" ref="gaf4657aed67f3cd7cce775215995c05d" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gaf4657aed67f3cd7cce775215995c05d">dJointSetUniversalAnchor</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set anchor <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ge0a831da9447ff65d76a0808502038e8"></a><!-- doxytag: member="joints::dJointSetUniversalAxis1" ref="ge0a831da9447ff65d76a0808502038e8" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ge0a831da9447ff65d76a0808502038e8">dJointSetUniversalAxis1</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gf3668eed7dc5aaf8fee19d7f87347343"></a><!-- doxytag: member="joints::dJointSetUniversalAxis2" ref="gf3668eed7dc5aaf8fee19d7f87347343" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gf3668eed7dc5aaf8fee19d7f87347343">dJointSetUniversalAxis2</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g3c58284c43e997a028b06dc250064e32"></a><!-- doxytag: member="joints::dJointSetUniversalParam" ref="g3c58284c43e997a028b06dc250064e32" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g3c58284c43e997a028b06dc250064e32">dJointSetUniversalParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g36607569e2ee26f39d3d42cba2397898">dJointAddUniversalTorques</a> (dJointID joint, dReal torque1, dReal torque2)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Applies torque1 about the universal's axis 1, torque2 about the universal's axis 2.  <a href="#g36607569e2ee26f39d3d42cba2397898"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ge46251e2cea2d31521b1fb9b151f640f"></a><!-- doxytag: member="joints::dJointSetPRAnchor" ref="ge46251e2cea2d31521b1fb9b151f640f" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ge46251e2cea2d31521b1fb9b151f640f">dJointSetPRAnchor</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set anchor <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga2ae3ab1fa58ec22bd443476f786fa81"></a><!-- doxytag: member="joints::dJointSetPRAxis1" ref="ga2ae3ab1fa58ec22bd443476f786fa81" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga2ae3ab1fa58ec22bd443476f786fa81">dJointSetPRAxis1</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set the axis for the prismatic articulation <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gc8c61c6dd7b28a58a4c0eaf2e91ecbd5"></a><!-- doxytag: member="joints::dJointSetPRAxis2" ref="gc8c61c6dd7b28a58a4c0eaf2e91ecbd5" args="(dJointID, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gc8c61c6dd7b28a58a4c0eaf2e91ecbd5">dJointSetPRAxis2</a> (dJointID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set the axis for the rotoide articulation <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gc08a28659605f17307d563f45db0824b">dJointSetPRParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter  <a href="#gc08a28659605f17307d563f45db0824b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ge675b0e0e332ddcd907ac9d1461b1961">dJointAddPRTorque</a> (dJointID j, dReal torque)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Applies the torque about the rotoide axis of the PR joint.  <a href="#ge675b0e0e332ddcd907ac9d1461b1961"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g8051a8232b4232f7b0d0fd57a3932072"></a><!-- doxytag: member="joints::dJointSetFixed" ref="g8051a8232b4232f7b0d0fd57a3932072" args="(dJointID)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g8051a8232b4232f7b0d0fd57a3932072">dJointSetFixed</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Call this on the fixed joint after it has been attached to remember the current desired relative offset and desired relative rotation between the bodies. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g1406f976045a1b7edffbb46bf626d04f">dJointSetAMotorNumAxes</a> (dJointID, int num)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set the nr of axes  <a href="#g1406f976045a1b7edffbb46bf626d04f"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gbef7d92227b62e04b60eb9df02359603"></a><!-- doxytag: member="joints::dJointSetAMotorAxis" ref="gbef7d92227b62e04b60eb9df02359603" args="(dJointID, int anum, int rel, dReal x, dReal y, dReal z)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gbef7d92227b62e04b60eb9df02359603">dJointSetAMotorAxis</a> (dJointID, int anum, int rel, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g17b2089e6512e22d71340befb40100d2">dJointSetAMotorAngle</a> (dJointID, int anum, dReal angle)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Tell the AMotor what the current angle is along axis anum.  <a href="#g17b2089e6512e22d71340befb40100d2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gac3f00196ee0cdb772e00dc259ef639a"></a><!-- doxytag: member="joints::dJointSetAMotorParam" ref="gac3f00196ee0cdb772e00dc259ef639a" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gac3f00196ee0cdb772e00dc259ef639a">dJointSetAMotorParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gb0a3a8527810717c62a2c68dc4dfa822"></a><!-- doxytag: member="joints::dJointSetAMotorMode" ref="gb0a3a8527810717c62a2c68dc4dfa822" args="(dJointID, int mode)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gb0a3a8527810717c62a2c68dc4dfa822">dJointSetAMotorMode</a> (dJointID, int mode)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set mode <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g69d13d54516716020d2adb841699b77b">dJointAddAMotorTorques</a> (dJointID, dReal torque1, dReal torque2, dReal torque3)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Applies torque0 about the AMotor's axis 0, torque1 about the AMotor's axis 1, and torque2 about the AMotor's axis 2.  <a href="#g69d13d54516716020d2adb841699b77b"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gcbfb4014567d69010aba3024d9b7bccd">dJointSetLMotorNumAxes</a> (dJointID, int num)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the number of axes that will be controlled by the LMotor.  <a href="#gcbfb4014567d69010aba3024d9b7bccd"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g080b7739f5b2b37a798742cee0ef38a4">dJointSetLMotorAxis</a> (dJointID, int anum, int rel, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the AMotor axes.  <a href="#g080b7739f5b2b37a798742cee0ef38a4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g791bfa6e65d0c3dce99ca0bcd3beb8d6"></a><!-- doxytag: member="joints::dJointSetLMotorParam" ref="g791bfa6e65d0c3dce99ca0bcd3beb8d6" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g791bfa6e65d0c3dce99ca0bcd3beb8d6">dJointSetLMotorParam</a> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">set joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1ec6e9ac6f92994cea1c9f9a2b50d69a"></a><!-- doxytag: member="joints::dJointSetPlane2DXParam" ref="g1ec6e9ac6f92994cea1c9f9a2b50d69a" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><b>dJointSetPlane2DXParam</b> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gf47dece2a7b73762937bd7671d23c945"></a><!-- doxytag: member="joints::dJointSetPlane2DYParam" ref="gf47dece2a7b73762937bd7671d23c945" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><b>dJointSetPlane2DYParam</b> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g2425ac42f0fe42e8b4a0d76b057070d1"></a><!-- doxytag: member="joints::dJointSetPlane2DAngleParam" ref="g2425ac42f0fe42e8b4a0d76b057070d1" args="(dJointID, int parameter, dReal value)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><b>dJointSetPlane2DAngleParam</b> (dJointID, int parameter, dReal value)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g20a27c479a75443552942059542f26ad"></a><!-- doxytag: member="joints::dJointGetBallParam" ref="g20a27c479a75443552942059542f26ad" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g20a27c479a75443552942059542f26ad">dJointGetBallParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g1d1c4f9b10c550f6fec550f9cc80c7ab">dJointGetHingeAnchor</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the hinge anchor point, in world coordinates.  <a href="#g1d1c4f9b10c550f6fec550f9cc80c7ab"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gfdc1d9c7bd8824ec3e79cc5aa67ddfa1">dJointGetHingeAnchor2</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the joint anchor point, in world coordinates.  <a href="#gfdc1d9c7bd8824ec3e79cc5aa67ddfa1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g17b812897bc5faab33584cc5e3e4d3a4"></a><!-- doxytag: member="joints::dJointGetHingeAxis" ref="g17b812897bc5faab33584cc5e3e4d3a4" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g17b812897bc5faab33584cc5e3e4d3a4">dJointGetHingeAxis</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get axis <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g43416613e72d1b16a32331a0ba3c7d70"></a><!-- doxytag: member="joints::dJointGetHingeParam" ref="g43416613e72d1b16a32331a0ba3c7d70" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g43416613e72d1b16a32331a0ba3c7d70">dJointGetHingeParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g7ca6bdfe2b919b6bc2a27ba6f0e069f0">dJointGetHingeAngle</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the hinge angle.  <a href="#g7ca6bdfe2b919b6bc2a27ba6f0e069f0"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g0d92377b748eb468dc38252df12afc76"></a><!-- doxytag: member="joints::dJointGetHingeAngleRate" ref="g0d92377b748eb468dc38252df12afc76" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g0d92377b748eb468dc38252df12afc76">dJointGetHingeAngleRate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the hinge angle time derivative. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g7f35449914cbc4a86b845dcd85a617c0">dJointGetSliderPosition</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the slider linear position (i.e. the slider's extension).  <a href="#g7f35449914cbc4a86b845dcd85a617c0"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g93378c9c2d0cd50c79cfb78ca881f8ec"></a><!-- doxytag: member="joints::dJointGetSliderPositionRate" ref="g93378c9c2d0cd50c79cfb78ca881f8ec" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g93378c9c2d0cd50c79cfb78ca881f8ec">dJointGetSliderPositionRate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the slider linear position's time derivative. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g17e31e7a877446213c39d1431269788e"></a><!-- doxytag: member="joints::dJointGetSliderAxis" ref="g17e31e7a877446213c39d1431269788e" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g17e31e7a877446213c39d1431269788e">dJointGetSliderAxis</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the slider axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gc76d8bb4bf8587af70ef5932025048fe"></a><!-- doxytag: member="joints::dJointGetSliderParam" ref="gc76d8bb4bf8587af70ef5932025048fe" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gc76d8bb4bf8587af70ef5932025048fe">dJointGetSliderParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g879999d011f82c73acf94029132cc198">dJointGetHinge2Anchor</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the joint anchor point, in world coordinates.  <a href="#g879999d011f82c73acf94029132cc198"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga67cde755a0c9b699859ead5b5c81d26"></a><!-- doxytag: member="joints::dJointGetHinge2Anchor2" ref="ga67cde755a0c9b699859ead5b5c81d26" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga67cde755a0c9b699859ead5b5c81d26">dJointGetHinge2Anchor2</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the joint anchor point, in world coordinates. This returns the point on body 2. If the joint is perfectly satisfied, this will return the same value as dJointGetHinge2Anchor. If not, this value will be slightly different. This can be used, for example, to see how far the joint has come apart. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g5d3e60c78ed85e8086dd60b13c3054f5"></a><!-- doxytag: member="joints::dJointGetHinge2Axis1" ref="g5d3e60c78ed85e8086dd60b13c3054f5" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g5d3e60c78ed85e8086dd60b13c3054f5">dJointGetHinge2Axis1</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get joint axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g9459009e9370ea1a1e4de10f60053c87"></a><!-- doxytag: member="joints::dJointGetHinge2Axis2" ref="g9459009e9370ea1a1e4de10f60053c87" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g9459009e9370ea1a1e4de10f60053c87">dJointGetHinge2Axis2</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get joint axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g9fe8b60ba59aa9451e5758491e34045a"></a><!-- doxytag: member="joints::dJointGetHinge2Param" ref="g9fe8b60ba59aa9451e5758491e34045a" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g9fe8b60ba59aa9451e5758491e34045a">dJointGetHinge2Param</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g430ed7cafe907e88929b28fdb17533c0"></a><!-- doxytag: member="joints::dJointGetHinge2Angle1" ref="g430ed7cafe907e88929b28fdb17533c0" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g430ed7cafe907e88929b28fdb17533c0">dJointGetHinge2Angle1</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g61881501e905ec1072aba05464fe44fb"></a><!-- doxytag: member="joints::dJointGetHinge2Angle1Rate" ref="g61881501e905ec1072aba05464fe44fb" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g61881501e905ec1072aba05464fe44fb">dJointGetHinge2Angle1Rate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get time derivative of angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g028c47d8ff409f6856492d9eb0367c8a"></a><!-- doxytag: member="joints::dJointGetHinge2Angle2Rate" ref="g028c47d8ff409f6856492d9eb0367c8a" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g028c47d8ff409f6856492d9eb0367c8a">dJointGetHinge2Angle2Rate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get time derivative of angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga768432c561cb76ba2490913f42d1aaf">dJointGetUniversalAnchor</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the joint anchor point, in world coordinates.  <a href="#ga768432c561cb76ba2490913f42d1aaf"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g00d5018903a90d75c324c4f870b0e7ea">dJointGetUniversalAnchor2</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the joint anchor point, in world coordinates.  <a href="#g00d5018903a90d75c324c4f870b0e7ea"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="geaa8e546d93c304755a86ad3fa6d2abe"></a><!-- doxytag: member="joints::dJointGetUniversalAxis1" ref="geaa8e546d93c304755a86ad3fa6d2abe" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#geaa8e546d93c304755a86ad3fa6d2abe">dJointGetUniversalAxis1</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g13c01cbc9c5e918740bac0540f6473b3"></a><!-- doxytag: member="joints::dJointGetUniversalAxis2" ref="g13c01cbc9c5e918740bac0540f6473b3" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g13c01cbc9c5e918740bac0540f6473b3">dJointGetUniversalAxis2</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gf96e70e676058b7eb385f5810fec641a"></a><!-- doxytag: member="joints::dJointGetUniversalParam" ref="gf96e70e676058b7eb385f5810fec641a" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gf96e70e676058b7eb385f5810fec641a">dJointGetUniversalParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g3c0fafbd1ccd8e450c01012ce600f6ab">dJointGetUniversalAngles</a> (dJointID, dReal *angle1, dReal *angle2)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get both angles at the same time.  <a href="#g3c0fafbd1ccd8e450c01012ce600f6ab"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g3a08e2fed2e88eb0c964a33fb8c0c61f"></a><!-- doxytag: member="joints::dJointGetUniversalAngle1" ref="g3a08e2fed2e88eb0c964a33fb8c0c61f" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g3a08e2fed2e88eb0c964a33fb8c0c61f">dJointGetUniversalAngle1</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g4026a7331d7956eef31e72e20e0c703b"></a><!-- doxytag: member="joints::dJointGetUniversalAngle2" ref="g4026a7331d7956eef31e72e20e0c703b" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g4026a7331d7956eef31e72e20e0c703b">dJointGetUniversalAngle2</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1f8ff99b6c33d3da2004a8846112427c"></a><!-- doxytag: member="joints::dJointGetUniversalAngle1Rate" ref="g1f8ff99b6c33d3da2004a8846112427c" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g1f8ff99b6c33d3da2004a8846112427c">dJointGetUniversalAngle1Rate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get time derivative of angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g94fb28ecb65cb0711b555558c22396cf"></a><!-- doxytag: member="joints::dJointGetUniversalAngle2Rate" ref="g94fb28ecb65cb0711b555558c22396cf" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g94fb28ecb65cb0711b555558c22396cf">dJointGetUniversalAngle2Rate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get time derivative of angle. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g88b176c70948c3f96e5c9173904b04fe">dJointGetPRAnchor</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the joint anchor point, in world coordinates.  <a href="#g88b176c70948c3f96e5c9173904b04fe"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gd8b95871e93525f44badcdaf8e521da7">dJointGetPRPosition</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the PR linear position (i.e. the prismatic's extension).  <a href="#gd8b95871e93525f44badcdaf8e521da7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gc3a434069c8bf31ae5140e2bff3bbb26"></a><!-- doxytag: member="joints::dJointGetPRPositionRate" ref="gc3a434069c8bf31ae5140e2bff3bbb26" args="(dJointID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gc3a434069c8bf31ae5140e2bff3bbb26">dJointGetPRPositionRate</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the PR linear position's time derivative. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g826424aac5023739bb13426df672ab32"></a><!-- doxytag: member="joints::dJointGetPRAxis1" ref="g826424aac5023739bb13426df672ab32" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g826424aac5023739bb13426df672ab32">dJointGetPRAxis1</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the prismatic axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g5f175ed66c5df1119a251fad8a51059d"></a><!-- doxytag: member="joints::dJointGetPRAxis2" ref="g5f175ed66c5df1119a251fad8a51059d" args="(dJointID, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g5f175ed66c5df1119a251fad8a51059d">dJointGetPRAxis2</a> (dJointID, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the Rotoide axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g968b868bd1598b24a3101a04320206c6"></a><!-- doxytag: member="joints::dJointGetPRParam" ref="g968b868bd1598b24a3101a04320206c6" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g968b868bd1598b24a3101a04320206c6">dJointGetPRParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g35f0392af69ece0d0c3ef7ed88b532bf">dJointGetAMotorNumAxes</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the number of angular axes that will be controlled by the AMotor.  <a href="#g35f0392af69ece0d0c3ef7ed88b532bf"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gef1af77cc19d81b24ad00025f3c9d5ec">dJointGetAMotorAxis</a> (dJointID, int anum, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the AMotor axes.  <a href="#gef1af77cc19d81b24ad00025f3c9d5ec"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g1887538374f044e22f9742650d14ae69">dJointGetAMotorAxisRel</a> (dJointID, int anum)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get axis.  <a href="#g1887538374f044e22f9742650d14ae69"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g3634444b00ac33a5f34a7af4fffda8b2">dJointGetAMotorAngle</a> (dJointID, int anum)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the current angle for axis.  <a href="#g3634444b00ac33a5f34a7af4fffda8b2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ga65abc36177390330037299b689b70c7">dJointGetAMotorAngleRate</a> (dJointID, int anum)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the current angle rate for axis anum.  <a href="#ga65abc36177390330037299b689b70c7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gfc4cd1046089baa4309d30ae7832d289"></a><!-- doxytag: member="joints::dJointGetAMotorParam" ref="gfc4cd1046089baa4309d30ae7832d289" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gfc4cd1046089baa4309d30ae7832d289">dJointGetAMotorParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gf2430c2062414bc28660bdc06a0d72d5">dJointGetAMotorMode</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the angular motor mode.  <a href="#gf2430c2062414bc28660bdc06a0d72d5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g6d7557b5e94e0ee37561cadc5bf85cb7"></a><!-- doxytag: member="joints::dJointGetLMotorNumAxes" ref="g6d7557b5e94e0ee37561cadc5bf85cb7" args="(dJointID)" -->
+ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g6d7557b5e94e0ee37561cadc5bf85cb7">dJointGetLMotorNumAxes</a> (dJointID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get nr of axes. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g4ef7e0ca633583e82d90679c8eb6d5c3"></a><!-- doxytag: member="joints::dJointGetLMotorAxis" ref="g4ef7e0ca633583e82d90679c8eb6d5c3" args="(dJointID, int anum, dVector3 result)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g4ef7e0ca633583e82d90679c8eb6d5c3">dJointGetLMotorAxis</a> (dJointID, int anum, dVector3 result)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get axis. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gcbc48fd61857e3843923166abf81a7a0"></a><!-- doxytag: member="joints::dJointGetLMotorParam" ref="gcbc48fd61857e3843923166abf81a7a0" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gcbc48fd61857e3843923166abf81a7a0">dJointGetLMotorParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ge433a5eac5f8600d8e6325666c2e12c2"></a><!-- doxytag: member="joints::dJointGetFixedParam" ref="ge433a5eac5f8600d8e6325666c2e12c2" args="(dJointID, int parameter)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#ge433a5eac5f8600d8e6325666c2e12c2">dJointGetFixedParam</a> (dJointID, int parameter)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">get joint parameter <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g4f5e75d2e10f4392d5046ef1ab119da2"></a><!-- doxytag: member="joints::dConnectingJoint" ref="g4f5e75d2e10f4392d5046ef1ab119da2" args="(dBodyID, dBodyID)" -->
+ODE_API dJointID&nbsp;</td><td class="memItemRight" valign="bottom"><b>dConnectingJoint</b> (dBodyID, dBodyID)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="gabe5f454e7679bb24d0037f1502861a5"></a><!-- doxytag: member="joints::dConnectingJointList" ref="gabe5f454e7679bb24d0037f1502861a5" args="(dBodyID, dBodyID, dJointID *)" -->
+ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><b>dConnectingJointList</b> (dBodyID, dBodyID, dJointID *)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#g68eb2f4daea03713db4d8b4daca663ae">dAreConnected</a> (dBodyID, dBodyID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Utility function.  <a href="#g68eb2f4daea03713db4d8b4daca663ae"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__joints.html#gc1eafde1fde036633136be6fd254ca5d">dAreConnectedExcluding</a> (dBodyID body1, dBodyID body2, int joint_type)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Utility function.  <a href="#gc1eafde1fde036633136be6fd254ca5d"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+In real life a joint is something like a hinge, that is used to connect two objects. In ODE a joint is very similar: It is a relationship that is enforced between two bodies so that they can only have certain positions and orientations relative to each other. This relationship is called a constraint -- the words joint and constraint are often used interchangeably.<p>
+A joint has a set of parameters that can be set. These include:<p>
+<ul>
+<li>dParamLoStop Low stop angle or position. Setting this to -dInfinity (the default value) turns off the low stop. For rotational joints, this stop must be greater than -pi to be effective. </li>
+<li>dParamHiStop High stop angle or position. Setting this to dInfinity (the default value) turns off the high stop. For rotational joints, this stop must be less than pi to be effective. If the high stop is less than the low stop then both stops will be ineffective. </li>
+<li>dParamVel Desired motor velocity (this will be an angular or linear velocity). </li>
+<li>dParamFMax The maximum force or torque that the motor will use to achieve the desired velocity. This must always be greater than or equal to zero. Setting this to zero (the default value) turns off the motor. </li>
+<li>dParamFudgeFactor The current joint stop/motor implementation has a small problem: when the joint is at one stop and the motor is set to move it away from the stop, too much force may be applied for one time step, causing a ``jumping'' motion. This fudge factor is used to scale this excess force. It should have a value between zero and one (the default value). If the jumping motion is too visible in a joint, the value can be reduced. Making this value too small can prevent the motor from being able to move the joint away from a stop. </li>
+<li>dParamBounce The bouncyness of the stops. This is a restitution parameter in the range 0..1. 0 means the stops are not bouncy at all, 1 means maximum bouncyness. </li>
+<li>dParamCFM The constraint force mixing (CFM) value used when not at a stop. </li>
+<li>dParamStopERP The error reduction parameter (ERP) used by the stops. </li>
+<li>dParamStopCFM The constraint force mixing (CFM) value used by the stops. Together with the ERP value this can be used to get spongy or soft stops. Note that this is intended for unpowered joints, it does not really work as expected when a powered joint reaches its limit. </li>
+<li>dParamSuspensionERP Suspension error reduction parameter (ERP). Currently this is only implemented on the hinge-2 joint. </li>
+<li>dParamSuspensionCFM Suspension constraint force mixing (CFM) value. Currently this is only implemented on the hinge-2 joint.</li>
+</ul>
+If a particular parameter is not implemented by a given joint, setting it will have no effect. These parameter names can be optionally followed by a digit (2 or 3) to indicate the second or third set of parameters, e.g. for the second axis in a hinge-2 joint, or the third axis in an AMotor joint. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="g68eb2f4daea03713db4d8b4daca663ae"></a><!-- doxytag: member="objects.h::dAreConnected" ref="g68eb2f4daea03713db4d8b4daca663ae" args="(dBodyID, dBodyID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dAreConnected           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Utility function. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if the two bodies are connected together by a joint, otherwise return 0. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc1eafde1fde036633136be6fd254ca5d"></a><!-- doxytag: member="objects.h::dAreConnectedExcluding" ref="gc1eafde1fde036633136be6fd254ca5d" args="(dBodyID body1, dBodyID body2, int joint_type)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dAreConnectedExcluding           </td>
+          <td>(</td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body2</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>joint_type</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Utility function. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if the two bodies are connected together by a joint that does not have type <ul>
+<li>{joint_type}, otherwise return 0. </li>
+</ul>
+</dd></dl>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>body1</em>&nbsp;</td><td>A body to check. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>body2</em>&nbsp;</td><td>A body to check. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>joint_type</em>&nbsp;</td><td>is a dJointTypeXXX constant. This is useful for deciding whether to add contact joints between two bodies: if they are already connected by non-contact joints then it may not be appropriate to add contacts, however it is okay to add more contact between- bodies that already have contacts. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g69d13d54516716020d2adb841699b77b"></a><!-- doxytag: member="objects.h::dJointAddAMotorTorques" ref="g69d13d54516716020d2adb841699b77b" args="(dJointID, dReal torque1, dReal torque2, dReal torque3)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAddAMotorTorques           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque2</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque3</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Applies torque0 about the AMotor's axis 0, torque1 about the AMotor's axis 1, and torque2 about the AMotor's axis 2. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>If the motor has fewer than three axes, the higher torques are ignored. This function is just a wrapper for <a class="el" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque()</a>. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga5ba1541d092f28c93b1bdc3bfb1b69f"></a><!-- doxytag: member="objects.h::dJointAddHinge2Torques" ref="ga5ba1541d092f28c93b1bdc3bfb1b69f" args="(dJointID joint, dReal torque1, dReal torque2)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAddHinge2Torques           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname"> <em>joint</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque2</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Applies torque1 about the hinge2's axis 1, torque2 about the hinge2's axis 2. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This function is just a wrapper for <a class="el" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque()</a>. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga1725abe170f80b0731321ed38785019"></a><!-- doxytag: member="objects.h::dJointAddHingeTorque" ref="ga1725abe170f80b0731321ed38785019" args="(dJointID joint, dReal torque)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAddHingeTorque           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname"> <em>joint</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Applies the torque about the hinge axis. 
+<p>
+That is, it applies a torque with specified magnitude in the direction of the hinge axis, to body 1, and with the same magnitude but in opposite direction to body 2. This function is just a wrapper for <a class="el" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque()</a>} 
+</div>
+</div><p>
+<a class="anchor" name="ge675b0e0e332ddcd907ac9d1461b1961"></a><!-- doxytag: member="objects.h::dJointAddPRTorque" ref="ge675b0e0e332ddcd907ac9d1461b1961" args="(dJointID j, dReal torque)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAddPRTorque           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname"> <em>j</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Applies the torque about the rotoide axis of the PR joint. 
+<p>
+That is, it applies a torque with specified magnitude in the direction of the rotoide axis, to body 1, and with the same magnitude but in opposite direction to body 2. This function is just a wrapper for <a class="el" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque()</a>} 
+</div>
+</div><p>
+<a class="anchor" name="g8b0e018cc3df6ea5ddb42320913455e7"></a><!-- doxytag: member="objects.h::dJointAddSliderForce" ref="g8b0e018cc3df6ea5ddb42320913455e7" args="(dJointID joint, dReal force)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAddSliderForce           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname"> <em>joint</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>force</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Applies the given force in the slider's direction. 
+<p>
+That is, it applies a force with specified magnitude, in the direction of slider's axis, to body1, and with the same magnitude but opposite direction to body2. This function is just a wrapper for <a class="el" href="group__bodies.html#g1e1352dc350ad42bff5818f2200ba792" title="Add force at centre of mass of body in absolute coordinates.">dBodyAddForce()</a>. 
+</div>
+</div><p>
+<a class="anchor" name="g36607569e2ee26f39d3d42cba2397898"></a><!-- doxytag: member="objects.h::dJointAddUniversalTorques" ref="g36607569e2ee26f39d3d42cba2397898" args="(dJointID joint, dReal torque1, dReal torque2)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAddUniversalTorques           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname"> <em>joint</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>torque2</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Applies torque1 about the universal's axis 1, torque2 about the universal's axis 2. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This function is just a wrapper for <a class="el" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque()</a>. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8f1c9b1302c799a1b87bc29b76d0dcec"></a><!-- doxytag: member="objects.h::dJointAttach" ref="g8f1c9b1302c799a1b87bc29b76d0dcec" args="(dJointID, dBodyID body1, dBodyID body2)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointAttach           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dBodyID&nbsp;</td>
+          <td class="paramname"> <em>body2</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Attach the joint to some new bodies. 
+<p>
+If the joint is already attached, it will be detached from the old bodies first. To attach this joint to only one body, set body1 or body2 to zero - a zero body refers to the static environment. Setting both bodies to zero puts the joint into "limbo", i.e. it will have no effect on the simulation. <dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Some joints, like hinge-2 need to be attached to two bodies to work. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf23195ce77e12031393e591abd0e28e6"></a><!-- doxytag: member="objects.h::dJointCreateAMotor" ref="gf23195ce77e12031393e591abd0e28e6" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateAMotor           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the A-motor type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2d23509f8d6c6066b361af4cf14166f7"></a><!-- doxytag: member="objects.h::dJointCreateBall" ref="g2d23509f8d6c6066b361af4cf14166f7" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateBall           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the ball type. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The joint is initially in "limbo" (i.e. it has no effect on the simulation) because it does not connect to any bodies. </dd></dl>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gfa5e1543239ba44ecbdc178ebc7c3cc4"></a><!-- doxytag: member="objects.h::dJointCreateContact" ref="gfa5e1543239ba44ecbdc178ebc7c3cc4" args="(dWorldID, dJointGroupID, const dContact *)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateContact           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const dContact *&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the contact type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ge568995d03077e1acb13882a627dcf32"></a><!-- doxytag: member="objects.h::dJointCreateFixed" ref="ge568995d03077e1acb13882a627dcf32" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateFixed           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the fixed type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2f18d431d48c905abc9d72ce011c00bd"></a><!-- doxytag: member="objects.h::dJointCreateHinge" ref="g2f18d431d48c905abc9d72ce011c00bd" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateHinge           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the hinge type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g6a6e32d35bdda9352d1be8d4df973f8f"></a><!-- doxytag: member="objects.h::dJointCreateHinge2" ref="g6a6e32d35bdda9352d1be8d4df973f8f" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateHinge2           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the hinge2 type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g21c8c99615269c5d9d3c57c674f6fd56"></a><!-- doxytag: member="objects.h::dJointCreateLMotor" ref="g21c8c99615269c5d9d3c57c674f6fd56" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateLMotor           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the L-motor type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7e68f39530acad9c0e7a38c8a3799b38"></a><!-- doxytag: member="objects.h::dJointCreatePlane2D" ref="g7e68f39530acad9c0e7a38c8a3799b38" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreatePlane2D           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the plane-2d type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gdc867f10ba9931d191244fa879e43cb2"></a><!-- doxytag: member="objects.h::dJointCreatePR" ref="gdc867f10ba9931d191244fa879e43cb2" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreatePR           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the PR (Prismatic and Rotoide) type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="geccc4c67b2d409016685a6a9163be539"></a><!-- doxytag: member="objects.h::dJointCreateSlider" ref="geccc4c67b2d409016685a6a9163be539" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateSlider           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the slider type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g1cb2e7668242313b5d24acb5d43e5c62"></a><!-- doxytag: member="objects.h::dJointCreateUniversal" ref="g1cb2e7668242313b5d24acb5d43e5c62" args="(dWorldID, dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointID dJointCreateUniversal           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new joint of the universal type. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dJointGroupID</em>&nbsp;</td><td>set to 0 to allocate the joint normally. If it is nonzero the joint is allocated in the given joint group. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2187ccbcf51c951f680eb6c9a210801a"></a><!-- doxytag: member="objects.h::dJointDestroy" ref="g2187ccbcf51c951f680eb6c9a210801a" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointDestroy           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Destroy a joint. 
+<p>
+disconnects it from its attached bodies and removing it from the world. However, if the joint is a member of a group then this function has no effect - to destroy that joint the group must be emptied or destroyed. 
+</div>
+</div><p>
+<a class="anchor" name="g3634444b00ac33a5f34a7af4fffda8b2"></a><!-- doxytag: member="objects.h::dJointGetAMotorAngle" ref="g3634444b00ac33a5f34a7af4fffda8b2" args="(dJointID, int anum)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dJointGetAMotorAngle           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>anum</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the current angle for axis. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>In dAMotorUser mode this is simply the value that was set with <a class="el" href="group__joints.html#g17b2089e6512e22d71340befb40100d2" title="Tell the AMotor what the current angle is along axis anum.">dJointSetAMotorAngle()</a>. In dAMotorEuler mode this is the corresponding euler angle. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga65abc36177390330037299b689b70c7"></a><!-- doxytag: member="objects.h::dJointGetAMotorAngleRate" ref="ga65abc36177390330037299b689b70c7" args="(dJointID, int anum)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dJointGetAMotorAngleRate           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>anum</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the current angle rate for axis anum. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>In dAMotorUser mode this is always zero, as not enough information is available. In dAMotorEuler mode this is the corresponding euler angle rate. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gef1af77cc19d81b24ad00025f3c9d5ec"></a><!-- doxytag: member="objects.h::dJointGetAMotorAxis" ref="gef1af77cc19d81b24ad00025f3c9d5ec" args="(dJointID, int anum, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetAMotorAxis           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>anum</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the AMotor axes. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>anum</em>&nbsp;</td><td>selects the axis to change (0,1 or 2). </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>rel</em>&nbsp;</td><td>Each axis can have one of three ``relative orientation'' modes. <ul>
+<li>0: The axis is anchored to the global frame. </li>
+<li>1: The axis is anchored to the first body. </li>
+<li>2: The axis is anchored to the second body. </li>
+</ul>
+</td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g1887538374f044e22f9742650d14ae69"></a><!-- doxytag: member="objects.h::dJointGetAMotorAxisRel" ref="g1887538374f044e22f9742650d14ae69" args="(dJointID, int anum)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dJointGetAMotorAxisRel           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>anum</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get axis. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The axis vector is always specified in global coordinates regardless of the setting of rel. There are two GetAMotorAxis functions, one to return the axis and one to return the relative mode.</dd></dl>
+For dAMotorEuler mode: <ul>
+<li>Only axes 0 and 2 need to be set. Axis 1 will be determined automatically at each time step. </li>
+<li>Axes 0 and 2 must be perpendicular to each other. </li>
+<li>Axis 0 must be anchored to the first body, axis 2 must be anchored to the second body. </li>
+</ul>
+
+</div>
+</div><p>
+<a class="anchor" name="gf2430c2062414bc28660bdc06a0d72d5"></a><!-- doxytag: member="objects.h::dJointGetAMotorMode" ref="gf2430c2062414bc28660bdc06a0d72d5" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dJointGetAMotorMode           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the angular motor mode. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>mode</em>&nbsp;</td><td>must be one of the following constants: <ul>
+<li>dAMotorUser The AMotor axes and joint angle settings are entirely controlled by the user. This is the default mode. </li>
+<li>dAMotorEuler Euler angles are automatically computed. The axis a1 is also automatically computed. The AMotor axes must be set correctly when in this mode, as described below. When this mode is initially set the current relative orientations of the bodies will correspond to all euler angles at zero. </li>
+</ul>
+</td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g35f0392af69ece0d0c3ef7ed88b532bf"></a><!-- doxytag: member="objects.h::dJointGetAMotorNumAxes" ref="g35f0392af69ece0d0c3ef7ed88b532bf" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dJointGetAMotorNumAxes           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the number of angular axes that will be controlled by the AMotor. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>num</em>&nbsp;</td><td>can range from 0 (which effectively deactivates the joint) to 3. This is automatically set to 3 in dAMotorEuler mode. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gff13cbb464f1bfdc225fc9202c2c54c3"></a><!-- doxytag: member="objects.h::dJointGetBody" ref="gff13cbb464f1bfdc225fc9202c2c54c3" args="(dJointID, int index)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dBodyID dJointGetBody           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>index</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Return the bodies that this joint connects. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>index</em>&nbsp;</td><td>return the first (0) or second (1) body. </td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>If one of these returned body IDs is zero, the joint connects the other body to the static environment. If both body IDs are zero, the joint is in ``limbo'' and has no effect on the simulation. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g879999d011f82c73acf94029132cc198"></a><!-- doxytag: member="objects.h::dJointGetHinge2Anchor" ref="g879999d011f82c73acf94029132cc198" args="(dJointID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetHinge2Anchor           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the joint anchor point, in world coordinates. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the point on body 1. If the joint is perfectly satisfied, this will be the same as the point on body 2. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g1d1c4f9b10c550f6fec550f9cc80c7ab"></a><!-- doxytag: member="objects.h::dJointGetHingeAnchor" ref="g1d1c4f9b10c550f6fec550f9cc80c7ab" args="(dJointID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetHingeAnchor           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the hinge anchor point, in world coordinates. 
+<p>
+This returns the point on body 1. If the joint is perfectly satisfied, this will be the same as the point on body 2. 
+</div>
+</div><p>
+<a class="anchor" name="gfdc1d9c7bd8824ec3e79cc5aa67ddfa1"></a><!-- doxytag: member="objects.h::dJointGetHingeAnchor2" ref="gfdc1d9c7bd8824ec3e79cc5aa67ddfa1" args="(dJointID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetHingeAnchor2           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the joint anchor point, in world coordinates. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The point on body 2. If the joint is perfectly satisfied, this will return the same value as <a class="el" href="group__joints.html#g1d1c4f9b10c550f6fec550f9cc80c7ab" title="Get the hinge anchor point, in world coordinates.">dJointGetHingeAnchor()</a>. If not, this value will be slightly different. This can be used, for example, to see how far the joint has come apart. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7ca6bdfe2b919b6bc2a27ba6f0e069f0"></a><!-- doxytag: member="objects.h::dJointGetHingeAngle" ref="g7ca6bdfe2b919b6bc2a27ba6f0e069f0" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dJointGetHingeAngle           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the hinge angle. 
+<p>
+The angle is measured between the two bodies, or between the body and the static environment. The angle will be between -pi..pi. When the hinge anchor or axis is set, the current position of the attached bodies is examined and that position will be the zero angle. 
+</div>
+</div><p>
+<a class="anchor" name="g88b176c70948c3f96e5c9173904b04fe"></a><!-- doxytag: member="objects.h::dJointGetPRAnchor" ref="g88b176c70948c3f96e5c9173904b04fe" args="(dJointID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetPRAnchor           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the joint anchor point, in world coordinates. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the point on body 1. If the joint is perfectly satisfied, this will be the same as the point on body 2. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd8b95871e93525f44badcdaf8e521da7"></a><!-- doxytag: member="objects.h::dJointGetPRPosition" ref="gd8b95871e93525f44badcdaf8e521da7" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dJointGetPRPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the PR linear position (i.e. the prismatic's extension). 
+<p>
+When the axis is set, the current position of the attached bodies is examined and that position will be the zero position.<p>
+The position is the "oriented" length between the position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)] 
+</div>
+</div><p>
+<a class="anchor" name="g7f35449914cbc4a86b845dcd85a617c0"></a><!-- doxytag: member="objects.h::dJointGetSliderPosition" ref="g7f35449914cbc4a86b845dcd85a617c0" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dJointGetSliderPosition           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the slider linear position (i.e. the slider's extension). 
+<p>
+When the axis is set, the current position of the attached bodies is examined and that position will be the zero position. 
+</div>
+</div><p>
+<a class="anchor" name="g6f12f69d9b1a457428a28c2f77148174"></a><!-- doxytag: member="objects.h::dJointGetType" ref="g6f12f69d9b1a457428a28c2f77148174" args="(dJointID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dJointGetType           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the type of the joint. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the type, being one of these: <ul>
+<li>JointTypeBall </li>
+<li>JointTypeHinge </li>
+<li>JointTypeSlider </li>
+<li>JointTypeContact </li>
+<li>JointTypeUniversal </li>
+<li>JointTypeHinge2 </li>
+<li>JointTypeFixed </li>
+<li>JointTypeAMotor </li>
+<li>JointTypeLMotor </li>
+</ul>
+</dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga768432c561cb76ba2490913f42d1aaf"></a><!-- doxytag: member="objects.h::dJointGetUniversalAnchor" ref="ga768432c561cb76ba2490913f42d1aaf" args="(dJointID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetUniversalAnchor           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the joint anchor point, in world coordinates. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the point on body 1. If the joint is perfectly satisfied, this will be the same as the point on body 2. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g00d5018903a90d75c324c4f870b0e7ea"></a><!-- doxytag: member="objects.h::dJointGetUniversalAnchor2" ref="g00d5018903a90d75c324c4f870b0e7ea" args="(dJointID, dVector3 result)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetUniversalAnchor2           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>result</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the joint anchor point, in world coordinates. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>This returns the point on body 2. </dd></dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>You can think of the ball and socket part of a universal joint as trying to keep the result of dJointGetBallAnchor() and dJointGetBallAnchor2() the same. If the joint is perfectly satisfied, this function will return the same value as <a class="el" href="group__joints.html#ga768432c561cb76ba2490913f42d1aaf" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor()</a> to within roundoff errors. <a class="el" href="group__joints.html#g00d5018903a90d75c324c4f870b0e7ea" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor2()</a> can be used, along with <a class="el" href="group__joints.html#ga768432c561cb76ba2490913f42d1aaf" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor()</a>, to see how far the joint has come apart. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3c0fafbd1ccd8e450c01012ce600f6ab"></a><!-- doxytag: member="objects.h::dJointGetUniversalAngles" ref="g3c0fafbd1ccd8e450c01012ce600f6ab" args="(dJointID, dReal *angle1, dReal *angle2)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGetUniversalAngles           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal *&nbsp;</td>
+          <td class="paramname"> <em>angle1</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal *&nbsp;</td>
+          <td class="paramname"> <em>angle2</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get both angles at the same time. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>joint</em>&nbsp;</td><td>The universal joint for which we want to calculate the angles </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>angle1</em>&nbsp;</td><td>The angle between the body1 and the axis 1 </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>angle2</em>&nbsp;</td><td>The angle between the body2 and the axis 2</td></tr>
+  </table>
+</dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>This function combine getUniversalAngle1 and getUniversalAngle2 together and try to avoid redundant calculation </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gaaec687b184a1214133a41503e7c628f"></a><!-- doxytag: member="objects.h::dJointGroupCreate" ref="gaaec687b184a1214133a41503e7c628f" args="(int max_size)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dJointGroupID dJointGroupCreate           </td>
+          <td>(</td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>max_size</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a joint group. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>max_size</em>&nbsp;</td><td>deprecated. Set to 0. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g49e664ee9a8bd7bfe5e6932bf936bb8f"></a><!-- doxytag: member="objects.h::dJointGroupDestroy" ref="g49e664ee9a8bd7bfe5e6932bf936bb8f" args="(dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGroupDestroy           </td>
+          <td>(</td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Destroy a joint group. 
+<p>
+All joints in the joint group will be destroyed. 
+</div>
+</div><p>
+<a class="anchor" name="g6e055bac8a0a3261bda3b6d07499c4ea"></a><!-- doxytag: member="objects.h::dJointGroupEmpty" ref="g6e055bac8a0a3261bda3b6d07499c4ea" args="(dJointGroupID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointGroupEmpty           </td>
+          <td>(</td>
+          <td class="paramtype">dJointGroupID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Empty a joint group. 
+<p>
+All joints in the joint group will be destroyed, but the joint group itself will not be destroyed. 
+</div>
+</div><p>
+<a class="anchor" name="g17b2089e6512e22d71340befb40100d2"></a><!-- doxytag: member="objects.h::dJointSetAMotorAngle" ref="g17b2089e6512e22d71340befb40100d2" args="(dJointID, int anum, dReal angle)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetAMotorAngle           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>anum</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>angle</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Tell the AMotor what the current angle is along axis anum. 
+<p>
+This function should only be called in dAMotorUser mode, because in this mode the AMotor has no other way of knowing the joint angles. The angle information is needed if stops have been set along the axis, but it is not needed for axis motors. 
+</div>
+</div><p>
+<a class="anchor" name="g1406f976045a1b7edffbb46bf626d04f"></a><!-- doxytag: member="objects.h::dJointSetAMotorNumAxes" ref="g1406f976045a1b7edffbb46bf626d04f" args="(dJointID, int num)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetAMotorNumAxes           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>num</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+set the nr of axes 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>num</em>&nbsp;</td><td>0..3 </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g058c33a3da1ff935a1125034f779dc4a"></a><!-- doxytag: member="objects.h::dJointSetBallAnchor" ref="g058c33a3da1ff935a1125034f779dc4a" args="(dJointID, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetBallAnchor           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the joint anchor point. 
+<p>
+The joint will try to keep this point on each body together. The input is specified in world coordinates. 
+</div>
+</div><p>
+<a class="anchor" name="g87ddb9beb95e9383a4280cb8a4186f01"></a><!-- doxytag: member="objects.h::dJointSetFeedback" ref="g87ddb9beb95e9383a4280cb8a4186f01" args="(dJointID, dJointFeedback *)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetFeedback           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dJointFeedback *&nbsp;</td>
+          <td class="paramname"></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the datastructure that is to receive the feedback. 
+<p>
+The feedback can be used by the user, so that it is known how much force an individual joint exerts. 
+</div>
+</div><p>
+<a class="anchor" name="g080b7739f5b2b37a798742cee0ef38a4"></a><!-- doxytag: member="objects.h::dJointSetLMotorAxis" ref="g080b7739f5b2b37a798742cee0ef38a4" args="(dJointID, int anum, int rel, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetLMotorAxis           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>anum</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>rel</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the AMotor axes. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>anum</em>&nbsp;</td><td>selects the axis to change (0,1 or 2). </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>rel</em>&nbsp;</td><td>Each axis can have one of three ``relative orientation'' modes <ul>
+<li>0: The axis is anchored to the global frame. </li>
+<li>1: The axis is anchored to the first body. </li>
+<li>2: The axis is anchored to the second body. </li>
+</ul>
+</td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>The axis vector is always specified in global coordinates regardless of the setting of rel. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gcbfb4014567d69010aba3024d9b7bccd"></a><!-- doxytag: member="objects.h::dJointSetLMotorNumAxes" ref="gcbfb4014567d69010aba3024d9b7bccd" args="(dJointID, int num)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetLMotorNumAxes           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>num</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the number of axes that will be controlled by the LMotor. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>num</em>&nbsp;</td><td>can range from 0 (which effectively deactivates the joint) to 3. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc08a28659605f17307d563f45db0824b"></a><!-- doxytag: member="objects.h::dJointSetPRParam" ref="gc08a28659605f17307d563f45db0824b" args="(dJointID, int parameter, dReal value)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dJointSetPRParam           </td>
+          <td>(</td>
+          <td class="paramtype">dJointID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>parameter</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>value</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+set joint parameter 
+<p>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>parameterX where X equal 2 refer to parameter for the rotoide articulation </dd></dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/group__world.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/group__world.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/group__world.html	(revision 216)
@@ -0,0 +1,697 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: World</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>World</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dWorldID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g929067266d630fb745f752042d685fc7">dWorldCreate</a> (void)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Create a new, empty world and return its ID number.  <a href="#g929067266d630fb745f752042d685fc7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g5a2e5b1d2d6a1376dca239b488e629f9">dWorldDestroy</a> (dWorldID world)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Destroy a world and everything in it.  <a href="#g5a2e5b1d2d6a1376dca239b488e629f9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#ga1b220b922215b335572c699cf8f8cad">dWorldSetGravity</a> (dWorldID, dReal x, dReal y, dReal z)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the world's global gravity vector.  <a href="#ga1b220b922215b335572c699cf8f8cad"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ge1a29b6a91cc1910a982c916ae4dee4a"></a><!-- doxytag: member="world::dWorldGetGravity" ref="ge1a29b6a91cc1910a982c916ae4dee4a" args="(dWorldID, dVector3 gravity)" -->
+ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#ge1a29b6a91cc1910a982c916ae4dee4a">dWorldGetGravity</a> (dWorldID, dVector3 gravity)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the gravity vector for a given world. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#gacd0778bdaa939d22f093fc2d5d5f868">dWorldSetERP</a> (dWorldID, dReal erp)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the global ERP value, that controls how much error correction is performed in each time step.  <a href="#gacd0778bdaa939d22f093fc2d5d5f868"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g033cd87a0b22889a94d4d84149bda5a0">dWorldGetERP</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the error reduction parameter.  <a href="#g033cd87a0b22889a94d4d84149bda5a0"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g8b7913fe46d0afc468418c655da79233">dWorldSetCFM</a> (dWorldID, dReal cfm)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the global CFM (constraint force mixing) value.  <a href="#g8b7913fe46d0afc468418c655da79233"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#gc7a431f2b3fc6f887fe91ad676828ba3">dWorldGetCFM</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the constraint force mixing value.  <a href="#gc7a431f2b3fc6f887fe91ad676828ba3"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g8f547ebeb3deed27e0f7b8143d475f50">dWorldStep</a> (dWorldID, dReal stepsize)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Step the world.  <a href="#g8f547ebeb3deed27e0f7b8143d475f50"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#ga9c564b4dd7d8fa4c6f4b32dd95fc33a">dWorldImpulseToForce</a> (dWorldID, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Converts an impulse to a force.  <a href="#ga9c564b4dd7d8fa4c6f4b32dd95fc33a"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#gc24fadc1d42b65ca3563e40bc1f0fec1">dWorldQuickStep</a> (dWorldID w, dReal stepsize)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Step the world.  <a href="#gc24fadc1d42b65ca3563e40bc1f0fec1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g9d852689d87d28a3d4947eda59c5ba7e">dWorldSetQuickStepNumIterations</a> (dWorldID, int num)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the number of iterations that the QuickStep method performs per step.  <a href="#g9d852689d87d28a3d4947eda59c5ba7e"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#ga51acfac06347fd27ff926d37672ce3c">dWorldGetQuickStepNumIterations</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the number of iterations that the QuickStep method performs per step.  <a href="#ga51acfac06347fd27ff926d37672ce3c"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#gf741ee61e3f9981ae102729f23aad535">dWorldSetQuickStepW</a> (dWorldID, dReal over_relaxation)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the SOR over-relaxation parameter.  <a href="#gf741ee61e3f9981ae102729f23aad535"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#ga7fef06f7a8293f21778939dfea36951">dWorldGetQuickStepW</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the SOR over-relaxation parameter.  <a href="#ga7fef06f7a8293f21778939dfea36951"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g2cec4be3f40d49c5950ceac1a28440d8">dWorldSetContactMaxCorrectingVel</a> (dWorldID, dReal vel)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the maximum correcting velocity that contacts are allowed to generate.  <a href="#g2cec4be3f40d49c5950ceac1a28440d8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g7673e6d0db3ddb319642caea7d14959d"></a><!-- doxytag: member="world::dWorldGetContactMaxCorrectingVel" ref="g7673e6d0db3ddb319642caea7d14959d" args="(dWorldID)" -->
+ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g7673e6d0db3ddb319642caea7d14959d">dWorldGetContactMaxCorrectingVel</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the maximum correcting velocity that contacts are allowed to generated. <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g8f6f964bc15b6cf0937d3214f6e3a1f1">dWorldSetContactSurfaceLayer</a> (dWorldID, dReal depth)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set the depth of the surface layer around all geometry objects.  <a href="#g8f6f964bc15b6cf0937d3214f6e3a1f1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#g97e1c98f55d9b56d00e7838900ad5e58">dWorldGetContactSurfaceLayer</a> (dWorldID)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the depth of the surface layer around all geometry objects.  <a href="#g97e1c98f55d9b56d00e7838900ad5e58"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">ODE_API void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__world.html#gefa68c714bb3c8f70503f101ea062c03">dWorldStepFast1</a> (dWorldID, dReal stepsize, int maxiterations)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Step the world using the StepFast1 algorithm.  <a href="#gefa68c714bb3c8f70503f101ea062c03"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+The world object is a container for rigid bodies and joints. Objects in different worlds can not interact, for example rigid bodies from two different worlds can not collide.<p>
+All the objects in a world exist at the same point in time, thus one reason to use separate worlds is to simulate systems at different rates. Most applications will only need one world. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="g929067266d630fb745f752042d685fc7"></a><!-- doxytag: member="objects.h::dWorldCreate" ref="g929067266d630fb745f752042d685fc7" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dWorldID dWorldCreate           </td>
+          <td>(</td>
+          <td class="paramtype">void&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Create a new, empty world and return its ID number. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>an identifier </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g5a2e5b1d2d6a1376dca239b488e629f9"></a><!-- doxytag: member="objects.h::dWorldDestroy" ref="g5a2e5b1d2d6a1376dca239b488e629f9" args="(dWorldID world)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldDestroy           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname"> <em>world</em>          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Destroy a world and everything in it. 
+<p>
+This includes all bodies, and all joints that are not part of a joint group. Joints that are part of a joint group will be deactivated, and can be destroyed by calling, for example, <a class="el" href="group__joints.html#g6e055bac8a0a3261bda3b6d07499c4ea" title="Empty a joint group.">dJointGroupEmpty()</a>.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>world</em>&nbsp;</td><td>the identifier for the world the be destroyed. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc7a431f2b3fc6f887fe91ad676828ba3"></a><!-- doxytag: member="objects.h::dWorldGetCFM" ref="gc7a431f2b3fc6f887fe91ad676828ba3" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetCFM           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the constraint force mixing value. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>CFM value </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g97e1c98f55d9b56d00e7838900ad5e58"></a><!-- doxytag: member="objects.h::dWorldGetContactSurfaceLayer" ref="g97e1c98f55d9b56d00e7838900ad5e58" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetContactSurfaceLayer           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the depth of the surface layer around all geometry objects. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the depth </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g033cd87a0b22889a94d4d84149bda5a0"></a><!-- doxytag: member="objects.h::dWorldGetERP" ref="g033cd87a0b22889a94d4d84149bda5a0" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetERP           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the error reduction parameter. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>ERP value </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga51acfac06347fd27ff926d37672ce3c"></a><!-- doxytag: member="objects.h::dWorldGetQuickStepNumIterations" ref="ga51acfac06347fd27ff926d37672ce3c" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API int dWorldGetQuickStepNumIterations           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the number of iterations that the QuickStep method performs per step. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>nr of iterations </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga7fef06f7a8293f21778939dfea36951"></a><!-- doxytag: member="objects.h::dWorldGetQuickStepW" ref="ga7fef06f7a8293f21778939dfea36951" args="(dWorldID)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API dReal dWorldGetQuickStepW           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">          </td>
+          <td>&nbsp;)&nbsp;</td>
+          <td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get the SOR over-relaxation parameter. 
+<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>the over-relaxation setting </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga9c564b4dd7d8fa4c6f4b32dd95fc33a"></a><!-- doxytag: member="objects.h::dWorldImpulseToForce" ref="ga9c564b4dd7d8fa4c6f4b32dd95fc33a" args="(dWorldID, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldImpulseToForce           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>stepsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>ix</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>iy</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>iz</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dVector3&nbsp;</td>
+          <td class="paramname"> <em>force</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Converts an impulse to a force. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>If you want to apply a linear or angular impulse to a rigid body, instead of a force or a torque, then you can use this function to convert the desired impulse into a force/torque vector before calling the BodyAdd... function. The current algorithm simply scales the impulse by 1/stepsize, where stepsize is the step size for the next step that will be taken. This function is given a dWorldID because, in the future, the force computation may depend on integrator parameters that are set as properties of the world. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gc24fadc1d42b65ca3563e40bc1f0fec1"></a><!-- doxytag: member="objects.h::dWorldQuickStep" ref="gc24fadc1d42b65ca3563e40bc1f0fec1" args="(dWorldID w, dReal stepsize)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldQuickStep           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname"> <em>w</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>stepsize</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Step the world. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>This uses an iterative method that takes time on the order of m*N and memory on the order of m, where m is the total number of constraint rows N is the number of iterations. For large systems this is a lot faster than <a class="el" href="group__world.html#g8f547ebeb3deed27e0f7b8143d475f50" title="Step the world.">dWorldStep()</a>, but it is less accurate. <p>
+QuickStep is great for stacks of objects especially when the auto-disable feature is used as well. However, it has poor accuracy for near-singular systems. Near-singular systems can occur when using high-friction contacts, motors, or certain articulated structures. For example, a robot with multiple legs sitting on the ground may be near-singular. <p>
+There are ways to help overcome QuickStep's inaccuracy problems: <ul>
+<li>Increase CFM. </li>
+<li>Reduce the number of contacts in your system (e.g. use the minimum number of contacts for the feet of a robot or creature). </li>
+<li>Don't use excessive friction in the contacts. </li>
+<li>Use contact slip if appropriate </li>
+<li>Avoid kinematic loops (however, kinematic loops are inevitable in legged creatures). </li>
+<li>Don't use excessive motor strength.  force-based motors instead of velocity-based motors.</li>
+</ul>
+Increasing the number of QuickStep iterations may help a little bit, but it is not going to help much if your system is really near singular. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8b7913fe46d0afc468418c655da79233"></a><!-- doxytag: member="objects.h::dWorldSetCFM" ref="g8b7913fe46d0afc468418c655da79233" args="(dWorldID, dReal cfm)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetCFM           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>cfm</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the global CFM (constraint force mixing) value. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>cfm</em>&nbsp;</td><td>Typical values are in the range {10^{-9}} -- 1. The default is 10^-5 if single precision is being used, or 10^-10 if double precision is being used. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2cec4be3f40d49c5950ceac1a28440d8"></a><!-- doxytag: member="objects.h::dWorldSetContactMaxCorrectingVel" ref="g2cec4be3f40d49c5950ceac1a28440d8" args="(dWorldID, dReal vel)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetContactMaxCorrectingVel           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>vel</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the maximum correcting velocity that contacts are allowed to generate. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>vel</em>&nbsp;</td><td>The default value is infinity (i.e. no limit). </td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Reducing this value can help prevent "popping" of deeply embedded objects. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8f6f964bc15b6cf0937d3214f6e3a1f1"></a><!-- doxytag: member="objects.h::dWorldSetContactSurfaceLayer" ref="g8f6f964bc15b6cf0937d3214f6e3a1f1" args="(dWorldID, dReal depth)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetContactSurfaceLayer           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>depth</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the depth of the surface layer around all geometry objects. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Contacts are allowed to sink into the surface layer up to the given depth before coming to rest. </dd></dl>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>depth</em>&nbsp;</td><td>The default value is zero. </td></tr>
+  </table>
+</dl>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>Increasing this to some small value (e.g. 0.001) can help prevent jittering problems due to contacts being repeatedly made and broken. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gacd0778bdaa939d22f093fc2d5d5f868"></a><!-- doxytag: member="objects.h::dWorldSetERP" ref="gacd0778bdaa939d22f093fc2d5d5f868" args="(dWorldID, dReal erp)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetERP           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>erp</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the global ERP value, that controls how much error correction is performed in each time step. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>dWorldID</em>&nbsp;</td><td>the identifier of the world. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>erp</em>&nbsp;</td><td>Typical values are in the range 0.1--0.8. The default is 0.2. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga1b220b922215b335572c699cf8f8cad"></a><!-- doxytag: member="objects.h::dWorldSetGravity" ref="ga1b220b922215b335572c699cf8f8cad" args="(dWorldID, dReal x, dReal y, dReal z)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetGravity           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>x</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>y</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>z</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the world's global gravity vector. 
+<p>
+The units are m/s^2, so Earth's gravity vector would be (0,0,-9.81), assuming that +z is up. The default is no gravity, i.e. (0,0,0). 
+</div>
+</div><p>
+<a class="anchor" name="g9d852689d87d28a3d4947eda59c5ba7e"></a><!-- doxytag: member="objects.h::dWorldSetQuickStepNumIterations" ref="g9d852689d87d28a3d4947eda59c5ba7e" args="(dWorldID, int num)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetQuickStepNumIterations           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>num</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the number of iterations that the QuickStep method performs per step. 
+<p>
+<dl class="remark" compact><dt><b>Remarks:</b></dt><dd>More iterations will give a more accurate solution, but will take longer to compute. </dd></dl>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>num</em>&nbsp;</td><td>The default is 20 iterations. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf741ee61e3f9981ae102729f23aad535"></a><!-- doxytag: member="objects.h::dWorldSetQuickStepW" ref="gf741ee61e3f9981ae102729f23aad535" args="(dWorldID, dReal over_relaxation)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldSetQuickStepW           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>over_relaxation</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the SOR over-relaxation parameter. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>over_relaxation</em>&nbsp;</td><td>value to use by SOR </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8f547ebeb3deed27e0f7b8143d475f50"></a><!-- doxytag: member="objects.h::dWorldStep" ref="g8f547ebeb3deed27e0f7b8143d475f50" args="(dWorldID, dReal stepsize)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldStep           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>stepsize</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Step the world. 
+<p>
+This uses a "big matrix" method that takes time on the order of m^3 and memory on the order of m^2, where m is the total number of constraint rows. For large systems this will use a lot of memory and can be very slow, but this is currently the most accurate method.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>stepsize</em>&nbsp;</td><td>The number of seconds that the simulation has to advance. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gefa68c714bb3c8f70503f101ea062c03"></a><!-- doxytag: member="objects.h::dWorldStepFast1" ref="gefa68c714bb3c8f70503f101ea062c03" args="(dWorldID, dReal stepsize, int maxiterations)" -->
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">ODE_API void dWorldStepFast1           </td>
+          <td>(</td>
+          <td class="paramtype">dWorldID&nbsp;</td>
+          <td class="paramname">, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">dReal&nbsp;</td>
+          <td class="paramname"> <em>stepsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&nbsp;</td>
+          <td class="paramname"> <em>maxiterations</em></td><td>&nbsp;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td><td width="100%"></td>
+        </tr>
+      </table>
+</div>
+<div class="memdoc">
+
+<p>
+Step the world using the StepFast1 algorithm. 
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+  <table border="0" cellspacing="2" cellpadding="0">
+    <tr><td valign="top"></td><td valign="top"><em>stepsize</em>&nbsp;</td><td>the nr of seconds to advance the simulation. </td></tr>
+    <tr><td valign="top"></td><td valign="top"><em>maxiterations</em>&nbsp;</td><td>The number of iterations to perform. </td></tr>
+  </table>
+</dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/index.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/index.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/index.html	(revision 216)
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Open Dynamics Engine API Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li class="current"><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Open Dynamics Engine API Reference</h1>
+<p>
+<center><em>This document is &copy; Russell Smith and the ODE Project</em></center><p>
+The Open Dynamics Engine (ODE) is a free, industrial quality library for simulating articulated rigid body dynamics. ODE is being developed by <a href="http://www.q12.org/">Russell Smith</a> with help from several <a href="http://ode.org/community.html">contributors</a>.<p>
+This document describes the library API. For a more general introduction to ODE, please see the <a href="http://opende.sourceforge.net/wiki/index.php/Manual">Online Handbook</a>.<p>
+<h2>Important: this document is not yet complete!</h2>
+<p>
+We are still working on getting the full API documentated. In the meantime, please refer to the <a href="http://opende.sourceforge.net/wiki/index.php/Manual">Online Handbook</a> <hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/mass_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/mass_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/mass_8h-source.html	(revision 216)
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: mass.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>mass.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_MASS_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_MASS_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00030"></a>00030 <span class="preprocessor">#endif</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span>
+<a name="l00032"></a>00032 <span class="keyword">struct </span>dMass;
+<a name="l00033"></a>00033 <span class="keyword">typedef</span> <span class="keyword">struct </span>dMass dMass;
+<a name="l00034"></a>00034 
+<a name="l00043"></a>00043 ODE_API <span class="keywordtype">int</span> dMassCheck(<span class="keyword">const</span> dMass *m);
+<a name="l00044"></a>00044 
+<a name="l00045"></a>00045 ODE_API <span class="keywordtype">void</span> dMassSetZero (dMass *);
+<a name="l00046"></a>00046 
+<a name="l00047"></a>00047 ODE_API <span class="keywordtype">void</span> dMassSetParameters (dMass *, dReal themass,
+<a name="l00048"></a>00048           dReal cgx, dReal cgy, dReal cgz,
+<a name="l00049"></a>00049           dReal I11, dReal I22, dReal I33,
+<a name="l00050"></a>00050           dReal I12, dReal I13, dReal I23);
+<a name="l00051"></a>00051 
+<a name="l00052"></a>00052 ODE_API <span class="keywordtype">void</span> dMassSetSphere (dMass *, dReal density, dReal radius);
+<a name="l00053"></a>00053 ODE_API <span class="keywordtype">void</span> dMassSetSphereTotal (dMass *, dReal total_mass, dReal radius);
+<a name="l00054"></a>00054 
+<a name="l00055"></a>00055 ODE_API <span class="keywordtype">void</span> dMassSetCapsule (dMass *, dReal density, <span class="keywordtype">int</span> direction,
+<a name="l00056"></a>00056          dReal radius, dReal length);
+<a name="l00057"></a>00057 ODE_API <span class="keywordtype">void</span> dMassSetCapsuleTotal (dMass *, dReal total_mass, <span class="keywordtype">int</span> direction,
+<a name="l00058"></a>00058          dReal radius, dReal length);
+<a name="l00059"></a>00059 
+<a name="l00060"></a>00060 ODE_API <span class="keywordtype">void</span> dMassSetCylinder (dMass *, dReal density, <span class="keywordtype">int</span> direction,
+<a name="l00061"></a>00061              dReal radius, dReal length);
+<a name="l00062"></a>00062 ODE_API <span class="keywordtype">void</span> dMassSetCylinderTotal (dMass *, dReal total_mass, <span class="keywordtype">int</span> direction,
+<a name="l00063"></a>00063              dReal radius, dReal length);
+<a name="l00064"></a>00064 
+<a name="l00065"></a>00065 ODE_API <span class="keywordtype">void</span> dMassSetBox (dMass *, dReal density,
+<a name="l00066"></a>00066         dReal lx, dReal ly, dReal lz);
+<a name="l00067"></a>00067 ODE_API <span class="keywordtype">void</span> dMassSetBoxTotal (dMass *, dReal total_mass,
+<a name="l00068"></a>00068              dReal lx, dReal ly, dReal lz);
+<a name="l00069"></a>00069 
+<a name="l00070"></a>00070 ODE_API <span class="keywordtype">void</span> dMassSetTrimesh (dMass *, dReal density, dGeomID g);
+<a name="l00071"></a>00071 
+<a name="l00072"></a>00072 ODE_API <span class="keywordtype">void</span> dMassSetTrimeshTotal (dMass *m, dReal total_mass, dGeomID g);
+<a name="l00073"></a>00073 
+<a name="l00074"></a>00074 ODE_API <span class="keywordtype">void</span> dMassAdjust (dMass *, dReal newmass);
+<a name="l00075"></a>00075 
+<a name="l00076"></a>00076 ODE_API <span class="keywordtype">void</span> dMassTranslate (dMass *, dReal x, dReal y, dReal z);
+<a name="l00077"></a>00077 
+<a name="l00078"></a>00078 ODE_API <span class="keywordtype">void</span> dMassRotate (dMass *, <span class="keyword">const</span> dMatrix3 R);
+<a name="l00079"></a>00079 
+<a name="l00080"></a>00080 ODE_API <span class="keywordtype">void</span> dMassAdd (dMass *a, <span class="keyword">const</span> dMass *b);
+<a name="l00081"></a>00081 
+<a name="l00082"></a>00082 <span class="comment">// Backwards compatible API</span>
+<a name="l00083"></a>00083 <span class="preprocessor">#define dMassSetCappedCylinder dMassSetCapsule</span>
+<a name="l00084"></a>00084 <span class="preprocessor"></span><span class="preprocessor">#define dMassSetCappedCylinderTotal dMassSetCapsuleTotal</span>
+<a name="l00085"></a>00085 <span class="preprocessor"></span>
+<a name="l00086"></a>00086 
+<a name="l00087"></a>00087 <span class="keyword">struct </span>dMass {
+<a name="l00088"></a>00088   dReal mass;
+<a name="l00089"></a>00089   dVector4 c;
+<a name="l00090"></a>00090   dMatrix3 I;
+<a name="l00091"></a>00091 
+<a name="l00092"></a>00092 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00093"></a>00093 <span class="preprocessor"></span>  dMass()
+<a name="l00094"></a>00094     { dMassSetZero (<span class="keyword">this</span>); }
+<a name="l00095"></a>00095   <span class="keywordtype">void</span> setZero()
+<a name="l00096"></a>00096     { dMassSetZero (<span class="keyword">this</span>); }
+<a name="l00097"></a>00097   <span class="keywordtype">void</span> setParameters (dReal themass, dReal cgx, dReal cgy, dReal cgz,
+<a name="l00098"></a>00098             dReal I11, dReal I22, dReal I33,
+<a name="l00099"></a>00099             dReal I12, dReal I13, dReal I23)
+<a name="l00100"></a>00100     { dMassSetParameters (<span class="keyword">this</span>,themass,cgx,cgy,cgz,I11,I22,I33,I12,I13,I23); }
+<a name="l00101"></a>00101   <span class="keywordtype">void</span> setSphere (dReal density, dReal radius)
+<a name="l00102"></a>00102     { dMassSetSphere (<span class="keyword">this</span>,density,radius); }
+<a name="l00103"></a>00103   <span class="keywordtype">void</span> setCapsule (dReal density, <span class="keywordtype">int</span> direction, dReal a, dReal b)
+<a name="l00104"></a>00104     { dMassSetCappedCylinder (<span class="keyword">this</span>,density,direction,a,b); }
+<a name="l00105"></a>00105   <span class="keywordtype">void</span> setCappedCylinder (dReal density, <span class="keywordtype">int</span> direction, dReal a, dReal b)
+<a name="l00106"></a>00106     { setCapsule(density, direction, a, b); }
+<a name="l00107"></a>00107   <span class="keywordtype">void</span> setBox (dReal density, dReal lx, dReal ly, dReal lz)
+<a name="l00108"></a>00108     { dMassSetBox (<span class="keyword">this</span>,density,lx,ly,lz); }
+<a name="l00109"></a>00109   <span class="keywordtype">void</span> adjust (dReal newmass)
+<a name="l00110"></a>00110     { dMassAdjust (<span class="keyword">this</span>,newmass); }
+<a name="l00111"></a>00111   <span class="keywordtype">void</span> translate (dReal x, dReal y, dReal z)
+<a name="l00112"></a>00112     { dMassTranslate (<span class="keyword">this</span>,x,y,z); }
+<a name="l00113"></a>00113   <span class="keywordtype">void</span> rotate (<span class="keyword">const</span> dMatrix3 R)
+<a name="l00114"></a>00114     { dMassRotate (<span class="keyword">this</span>,R); }
+<a name="l00115"></a>00115   <span class="keywordtype">void</span> <span class="keyword">add</span> (<span class="keyword">const</span> dMass *b)
+<a name="l00116"></a>00116     { dMassAdd (<span class="keyword">this</span>,b); }
+<a name="l00117"></a>00117 <span class="preprocessor">#endif</span>
+<a name="l00118"></a>00118 <span class="preprocessor"></span>};
+<a name="l00119"></a>00119 
+<a name="l00120"></a>00120 
+<a name="l00121"></a>00121 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00122"></a>00122 <span class="preprocessor"></span>}
+<a name="l00123"></a>00123 <span class="preprocessor">#endif</span>
+<a name="l00124"></a>00124 <span class="preprocessor"></span>
+<a name="l00125"></a>00125 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/matrix_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/matrix_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/matrix_8h-source.html	(revision 216)
@@ -0,0 +1,214 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: matrix.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>matrix.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/* optimized and unoptimized vector and matrix functions */</span>
+<a name="l00024"></a>00024 
+<a name="l00025"></a>00025 <span class="preprocessor">#ifndef _ODE_MATRIX_H_</span>
+<a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_MATRIX_H_</span>
+<a name="l00027"></a>00027 <span class="preprocessor"></span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 
+<a name="l00031"></a>00031 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00032"></a>00032 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00033"></a>00033 <span class="preprocessor">#endif</span>
+<a name="l00034"></a>00034 <span class="preprocessor"></span>
+<a name="l00035"></a>00035 
+<a name="l00036"></a>00036 <span class="comment">/* set a vector/matrix of size n to all zeros, or to a specific value. */</span>
+<a name="l00037"></a>00037 
+<a name="l00038"></a>00038 ODE_API <span class="keywordtype">void</span> dSetZero (dReal *a, <span class="keywordtype">int</span> n);
+<a name="l00039"></a>00039 ODE_API <span class="keywordtype">void</span> dSetValue (dReal *a, <span class="keywordtype">int</span> n, dReal value);
+<a name="l00040"></a>00040 
+<a name="l00041"></a>00041 
+<a name="l00042"></a>00042 <span class="comment">/* get the dot product of two n*1 vectors. if n &lt;= 0 then</span>
+<a name="l00043"></a>00043 <span class="comment"> * zero will be returned (in which case a and b need not be valid).</span>
+<a name="l00044"></a>00044 <span class="comment"> */</span>
+<a name="l00045"></a>00045 
+<a name="l00046"></a>00046 ODE_API dReal dDot (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b, <span class="keywordtype">int</span> n);
+<a name="l00047"></a>00047 
+<a name="l00048"></a>00048 
+<a name="l00049"></a>00049 <span class="comment">/* get the dot products of (a0,b), (a1,b), etc and return them in outsum.</span>
+<a name="l00050"></a>00050 <span class="comment"> * all vectors are n*1. if n &lt;= 0 then zeroes will be returned (in which case</span>
+<a name="l00051"></a>00051 <span class="comment"> * the input vectors need not be valid). this function is somewhat faster</span>
+<a name="l00052"></a>00052 <span class="comment"> * than calling dDot() for all of the combinations separately.</span>
+<a name="l00053"></a>00053 <span class="comment"> */</span>
+<a name="l00054"></a>00054 
+<a name="l00055"></a>00055 <span class="comment">/* NOT INCLUDED in the library for now.</span>
+<a name="l00056"></a>00056 <span class="comment">void dMultidot2 (const dReal *a0, const dReal *a1,</span>
+<a name="l00057"></a>00057 <span class="comment">       const dReal *b, dReal *outsum, int n);</span>
+<a name="l00058"></a>00058 <span class="comment">*/</span>
+<a name="l00059"></a>00059 
+<a name="l00060"></a>00060 
+<a name="l00061"></a>00061 <span class="comment">/* matrix multiplication. all matrices are stored in standard row format.</span>
+<a name="l00062"></a>00062 <span class="comment"> * the digit refers to the argument that is transposed:</span>
+<a name="l00063"></a>00063 <span class="comment"> *   0:   A = B  * C   (sizes: A:p*r B:p*q C:q*r)</span>
+<a name="l00064"></a>00064 <span class="comment"> *   1:   A = B' * C   (sizes: A:p*r B:q*p C:q*r)</span>
+<a name="l00065"></a>00065 <span class="comment"> *   2:   A = B  * C'  (sizes: A:p*r B:p*q C:r*q)</span>
+<a name="l00066"></a>00066 <span class="comment"> * case 1,2 are equivalent to saying that the operation is A=B*C but</span>
+<a name="l00067"></a>00067 <span class="comment"> * B or C are stored in standard column format.</span>
+<a name="l00068"></a>00068 <span class="comment"> */</span>
+<a name="l00069"></a>00069 
+<a name="l00070"></a>00070 ODE_API <span class="keywordtype">void</span> dMultiply0 (dReal *A, <span class="keyword">const</span> dReal *B, <span class="keyword">const</span> dReal *C, <span class="keywordtype">int</span> p,<span class="keywordtype">int</span> q,<span class="keywordtype">int</span> r);
+<a name="l00071"></a>00071 ODE_API <span class="keywordtype">void</span> dMultiply1 (dReal *A, <span class="keyword">const</span> dReal *B, <span class="keyword">const</span> dReal *C, <span class="keywordtype">int</span> p,<span class="keywordtype">int</span> q,<span class="keywordtype">int</span> r);
+<a name="l00072"></a>00072 ODE_API <span class="keywordtype">void</span> dMultiply2 (dReal *A, <span class="keyword">const</span> dReal *B, <span class="keyword">const</span> dReal *C, <span class="keywordtype">int</span> p,<span class="keywordtype">int</span> q,<span class="keywordtype">int</span> r);
+<a name="l00073"></a>00073 
+<a name="l00074"></a>00074 
+<a name="l00075"></a>00075 <span class="comment">/* do an in-place cholesky decomposition on the lower triangle of the n*n</span>
+<a name="l00076"></a>00076 <span class="comment"> * symmetric matrix A (which is stored by rows). the resulting lower triangle</span>
+<a name="l00077"></a>00077 <span class="comment"> * will be such that L*L'=A. return 1 on success and 0 on failure (on failure</span>
+<a name="l00078"></a>00078 <span class="comment"> * the matrix is not positive definite).</span>
+<a name="l00079"></a>00079 <span class="comment"> */</span>
+<a name="l00080"></a>00080 
+<a name="l00081"></a>00081 ODE_API <span class="keywordtype">int</span> dFactorCholesky (dReal *A, <span class="keywordtype">int</span> n);
+<a name="l00082"></a>00082 
+<a name="l00083"></a>00083 
+<a name="l00084"></a>00084 <span class="comment">/* solve for x: L*L'*x = b, and put the result back into x.</span>
+<a name="l00085"></a>00085 <span class="comment"> * L is size n*n, b is size n*1. only the lower triangle of L is considered.</span>
+<a name="l00086"></a>00086 <span class="comment"> */</span>
+<a name="l00087"></a>00087 
+<a name="l00088"></a>00088 ODE_API <span class="keywordtype">void</span> dSolveCholesky (<span class="keyword">const</span> dReal *L, dReal *b, <span class="keywordtype">int</span> n);
+<a name="l00089"></a>00089 
+<a name="l00090"></a>00090 
+<a name="l00091"></a>00091 <span class="comment">/* compute the inverse of the n*n positive definite matrix A and put it in</span>
+<a name="l00092"></a>00092 <span class="comment"> * Ainv. this is not especially fast. this returns 1 on success (A was</span>
+<a name="l00093"></a>00093 <span class="comment"> * positive definite) or 0 on failure (not PD).</span>
+<a name="l00094"></a>00094 <span class="comment"> */</span>
+<a name="l00095"></a>00095 
+<a name="l00096"></a>00096 ODE_API <span class="keywordtype">int</span> dInvertPDMatrix (<span class="keyword">const</span> dReal *A, dReal *Ainv, <span class="keywordtype">int</span> n);
+<a name="l00097"></a>00097 
+<a name="l00098"></a>00098 
+<a name="l00099"></a>00099 <span class="comment">/* check whether an n*n matrix A is positive definite, return 1/0 (yes/no).</span>
+<a name="l00100"></a>00100 <span class="comment"> * positive definite means that x'*A*x &gt; 0 for any x. this performs a</span>
+<a name="l00101"></a>00101 <span class="comment"> * cholesky decomposition of A. if the decomposition fails then the matrix</span>
+<a name="l00102"></a>00102 <span class="comment"> * is not positive definite. A is stored by rows. A is not altered.</span>
+<a name="l00103"></a>00103 <span class="comment"> */</span>
+<a name="l00104"></a>00104 
+<a name="l00105"></a>00105 ODE_API <span class="keywordtype">int</span> dIsPositiveDefinite (<span class="keyword">const</span> dReal *A, <span class="keywordtype">int</span> n);
+<a name="l00106"></a>00106 
+<a name="l00107"></a>00107 
+<a name="l00108"></a>00108 <span class="comment">/* factorize a matrix A into L*D*L', where L is lower triangular with ones on</span>
+<a name="l00109"></a>00109 <span class="comment"> * the diagonal, and D is diagonal.</span>
+<a name="l00110"></a>00110 <span class="comment"> * A is an n*n matrix stored by rows, with a leading dimension of n rounded</span>
+<a name="l00111"></a>00111 <span class="comment"> * up to 4. L is written into the strict lower triangle of A (the ones are not</span>
+<a name="l00112"></a>00112 <span class="comment"> * written) and the reciprocal of the diagonal elements of D are written into</span>
+<a name="l00113"></a>00113 <span class="comment"> * d.</span>
+<a name="l00114"></a>00114 <span class="comment"> */</span>
+<a name="l00115"></a>00115 ODE_API <span class="keywordtype">void</span> dFactorLDLT (dReal *A, dReal *d, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> nskip);
+<a name="l00116"></a>00116 
+<a name="l00117"></a>00117 
+<a name="l00118"></a>00118 <span class="comment">/* solve L*x=b, where L is n*n lower triangular with ones on the diagonal,</span>
+<a name="l00119"></a>00119 <span class="comment"> * and x,b are n*1. b is overwritten with x.</span>
+<a name="l00120"></a>00120 <span class="comment"> * the leading dimension of L is `nskip'.</span>
+<a name="l00121"></a>00121 <span class="comment"> */</span>
+<a name="l00122"></a>00122 ODE_API <span class="keywordtype">void</span> dSolveL1 (<span class="keyword">const</span> dReal *L, dReal *b, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> nskip);
+<a name="l00123"></a>00123 
+<a name="l00124"></a>00124 
+<a name="l00125"></a>00125 <span class="comment">/* solve L'*x=b, where L is n*n lower triangular with ones on the diagonal,</span>
+<a name="l00126"></a>00126 <span class="comment"> * and x,b are n*1. b is overwritten with x.</span>
+<a name="l00127"></a>00127 <span class="comment"> * the leading dimension of L is `nskip'.</span>
+<a name="l00128"></a>00128 <span class="comment"> */</span>
+<a name="l00129"></a>00129 ODE_API <span class="keywordtype">void</span> dSolveL1T (<span class="keyword">const</span> dReal *L, dReal *b, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> nskip);
+<a name="l00130"></a>00130 
+<a name="l00131"></a>00131 
+<a name="l00132"></a>00132 <span class="comment">/* in matlab syntax: a(1:n) = a(1:n) .* d(1:n) */</span>
+<a name="l00133"></a>00133 
+<a name="l00134"></a>00134 ODE_API <span class="keywordtype">void</span> dVectorScale (dReal *a, <span class="keyword">const</span> dReal *d, <span class="keywordtype">int</span> n);
+<a name="l00135"></a>00135 
+<a name="l00136"></a>00136 
+<a name="l00137"></a>00137 <span class="comment">/* given `L', a n*n lower triangular matrix with ones on the diagonal,</span>
+<a name="l00138"></a>00138 <span class="comment"> * and `d', a n*1 vector of the reciprocal diagonal elements of an n*n matrix</span>
+<a name="l00139"></a>00139 <span class="comment"> * D, solve L*D*L'*x=b where x,b are n*1. x overwrites b.</span>
+<a name="l00140"></a>00140 <span class="comment"> * the leading dimension of L is `nskip'.</span>
+<a name="l00141"></a>00141 <span class="comment"> */</span>
+<a name="l00142"></a>00142 
+<a name="l00143"></a>00143 ODE_API <span class="keywordtype">void</span> dSolveLDLT (<span class="keyword">const</span> dReal *L, <span class="keyword">const</span> dReal *d, dReal *b, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> nskip);
+<a name="l00144"></a>00144 
+<a name="l00145"></a>00145 
+<a name="l00146"></a>00146 <span class="comment">/* given an L*D*L' factorization of an n*n matrix A, return the updated</span>
+<a name="l00147"></a>00147 <span class="comment"> * factorization L2*D2*L2' of A plus the following "top left" matrix:</span>
+<a name="l00148"></a>00148 <span class="comment"> *</span>
+<a name="l00149"></a>00149 <span class="comment"> *    [ b a' ]     &lt;-- b is a[0]</span>
+<a name="l00150"></a>00150 <span class="comment"> *    [ a 0  ]     &lt;-- a is a[1..n-1]</span>
+<a name="l00151"></a>00151 <span class="comment"> *</span>
+<a name="l00152"></a>00152 <span class="comment"> *   - L has size n*n, its leading dimension is nskip. L is lower triangular</span>
+<a name="l00153"></a>00153 <span class="comment"> *     with ones on the diagonal. only the lower triangle of L is referenced.</span>
+<a name="l00154"></a>00154 <span class="comment"> *   - d has size n. d contains the reciprocal diagonal elements of D.</span>
+<a name="l00155"></a>00155 <span class="comment"> *   - a has size n.</span>
+<a name="l00156"></a>00156 <span class="comment"> * the result is written into L, except that the left column of L and d[0]</span>
+<a name="l00157"></a>00157 <span class="comment"> * are not actually modified. see ldltaddTL.m for further comments. </span>
+<a name="l00158"></a>00158 <span class="comment"> */</span>
+<a name="l00159"></a>00159 ODE_API <span class="keywordtype">void</span> dLDLTAddTL (dReal *L, dReal *d, <span class="keyword">const</span> dReal *a, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> nskip);
+<a name="l00160"></a>00160 
+<a name="l00161"></a>00161 
+<a name="l00162"></a>00162 <span class="comment">/* given an L*D*L' factorization of a permuted matrix A, produce a new</span>
+<a name="l00163"></a>00163 <span class="comment"> * factorization for row and column `r' removed.</span>
+<a name="l00164"></a>00164 <span class="comment"> *   - A has size n1*n1, its leading dimension in nskip. A is symmetric and</span>
+<a name="l00165"></a>00165 <span class="comment"> *     positive definite. only the lower triangle of A is referenced.</span>
+<a name="l00166"></a>00166 <span class="comment"> *     A itself may actually be an array of row pointers.</span>
+<a name="l00167"></a>00167 <span class="comment"> *   - L has size n2*n2, its leading dimension in nskip. L is lower triangular</span>
+<a name="l00168"></a>00168 <span class="comment"> *     with ones on the diagonal. only the lower triangle of L is referenced.</span>
+<a name="l00169"></a>00169 <span class="comment"> *   - d has size n2. d contains the reciprocal diagonal elements of D.</span>
+<a name="l00170"></a>00170 <span class="comment"> *   - p is a permutation vector. it contains n2 indexes into A. each index</span>
+<a name="l00171"></a>00171 <span class="comment"> *     must be in the range 0..n1-1.</span>
+<a name="l00172"></a>00172 <span class="comment"> *   - r is the row/column of L to remove.</span>
+<a name="l00173"></a>00173 <span class="comment"> * the new L will be written within the old L, i.e. will have the same leading</span>
+<a name="l00174"></a>00174 <span class="comment"> * dimension. the last row and column of L, and the last element of d, are</span>
+<a name="l00175"></a>00175 <span class="comment"> * undefined on exit.</span>
+<a name="l00176"></a>00176 <span class="comment"> *</span>
+<a name="l00177"></a>00177 <span class="comment"> * a fast O(n^2) algorithm is used. see ldltremove.m for further comments.</span>
+<a name="l00178"></a>00178 <span class="comment"> */</span>
+<a name="l00179"></a>00179 ODE_API <span class="keywordtype">void</span> dLDLTRemove (dReal **A, <span class="keyword">const</span> <span class="keywordtype">int</span> *p, dReal *L, dReal *d,
+<a name="l00180"></a>00180         <span class="keywordtype">int</span> n1, <span class="keywordtype">int</span> n2, <span class="keywordtype">int</span> r, <span class="keywordtype">int</span> nskip);
+<a name="l00181"></a>00181 
+<a name="l00182"></a>00182 
+<a name="l00183"></a>00183 <span class="comment">/* given an n*n matrix A (with leading dimension nskip), remove the r'th row</span>
+<a name="l00184"></a>00184 <span class="comment"> * and column by moving elements. the new matrix will have the same leading</span>
+<a name="l00185"></a>00185 <span class="comment"> * dimension. the last row and column of A are untouched on exit.</span>
+<a name="l00186"></a>00186 <span class="comment"> */</span>
+<a name="l00187"></a>00187 ODE_API <span class="keywordtype">void</span> dRemoveRowCol (dReal *A, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> nskip, <span class="keywordtype">int</span> r);
+<a name="l00188"></a>00188 
+<a name="l00189"></a>00189 
+<a name="l00190"></a>00190 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00191"></a>00191 <span class="preprocessor"></span>}
+<a name="l00192"></a>00192 <span class="preprocessor">#endif</span>
+<a name="l00193"></a>00193 <span class="preprocessor"></span>
+<a name="l00194"></a>00194 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/memory_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/memory_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/memory_8h-source.html	(revision 216)
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: memory.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>memory.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/* this comes from the `reuse' library. copy any changes back to the source */</span>
+<a name="l00024"></a>00024 
+<a name="l00025"></a>00025 <span class="preprocessor">#ifndef _ODE_MEMORY_H_</span>
+<a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_MEMORY_H_</span>
+<a name="l00027"></a>00027 <span class="preprocessor"></span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include "ode/config.h"</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00032"></a>00032 <span class="preprocessor">#endif</span>
+<a name="l00033"></a>00033 <span class="preprocessor"></span>
+<a name="l00034"></a>00034 <span class="comment">/* function types to allocate and free memory */</span>
+<a name="l00035"></a>00035 <span class="keyword">typedef</span> <span class="keywordtype">void</span> * dAllocFunction (<span class="keywordtype">size_t</span> size);
+<a name="l00036"></a>00036 <span class="keyword">typedef</span> <span class="keywordtype">void</span> * dReallocFunction (<span class="keywordtype">void</span> *ptr, <span class="keywordtype">size_t</span> oldsize, <span class="keywordtype">size_t</span> newsize);
+<a name="l00037"></a>00037 <span class="keyword">typedef</span> <span class="keywordtype">void</span> dFreeFunction (<span class="keywordtype">void</span> *ptr, <span class="keywordtype">size_t</span> size);
+<a name="l00038"></a>00038 
+<a name="l00039"></a>00039 <span class="comment">/* set new memory management functions. if fn is 0, the default handlers are</span>
+<a name="l00040"></a>00040 <span class="comment"> * used. */</span>
+<a name="l00041"></a>00041 ODE_API <span class="keywordtype">void</span> dSetAllocHandler (dAllocFunction *fn);
+<a name="l00042"></a>00042 ODE_API <span class="keywordtype">void</span> dSetReallocHandler (dReallocFunction *fn);
+<a name="l00043"></a>00043 ODE_API <span class="keywordtype">void</span> dSetFreeHandler (dFreeFunction *fn);
+<a name="l00044"></a>00044 
+<a name="l00045"></a>00045 <span class="comment">/* get current memory management functions */</span>
+<a name="l00046"></a>00046 ODE_API dAllocFunction *dGetAllocHandler (<span class="keywordtype">void</span>);
+<a name="l00047"></a>00047 ODE_API dReallocFunction *dGetReallocHandler (<span class="keywordtype">void</span>);
+<a name="l00048"></a>00048 ODE_API dFreeFunction *dGetFreeHandler (<span class="keywordtype">void</span>);
+<a name="l00049"></a>00049 
+<a name="l00050"></a>00050 <span class="comment">/* allocate and free memory. */</span>
+<a name="l00051"></a>00051 ODE_API <span class="keywordtype">void</span> * dAlloc (<span class="keywordtype">size_t</span> size);
+<a name="l00052"></a>00052 ODE_API <span class="keywordtype">void</span> * dRealloc (<span class="keywordtype">void</span> *ptr, <span class="keywordtype">size_t</span> oldsize, <span class="keywordtype">size_t</span> newsize);
+<a name="l00053"></a>00053 ODE_API <span class="keywordtype">void</span> dFree (<span class="keywordtype">void</span> *ptr, <span class="keywordtype">size_t</span> size);
+<a name="l00054"></a>00054 
+<a name="l00055"></a>00055 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00056"></a>00056 <span class="preprocessor"></span>}
+<a name="l00057"></a>00057 <span class="preprocessor">#endif</span>
+<a name="l00058"></a>00058 <span class="preprocessor"></span>
+<a name="l00059"></a>00059 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/misc_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/misc_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/misc_8h-source.html	(revision 216)
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: misc.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>misc.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/* miscellaneous math functions. these are mostly useful for testing */</span>
+<a name="l00024"></a>00024 
+<a name="l00025"></a>00025 <span class="preprocessor">#ifndef _ODE_MISC_H_</span>
+<a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_MISC_H_</span>
+<a name="l00027"></a>00027 <span class="preprocessor"></span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 
+<a name="l00031"></a>00031 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00032"></a>00032 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00033"></a>00033 <span class="preprocessor">#endif</span>
+<a name="l00034"></a>00034 <span class="preprocessor"></span>
+<a name="l00035"></a>00035 
+<a name="l00036"></a>00036 <span class="comment">/* return 1 if the random number generator is working. */</span>
+<a name="l00037"></a>00037 ODE_API <span class="keywordtype">int</span> dTestRand(<span class="keywordtype">void</span>);
+<a name="l00038"></a>00038 
+<a name="l00039"></a>00039 <span class="comment">/* return next 32 bit random number. this uses a not-very-random linear</span>
+<a name="l00040"></a>00040 <span class="comment"> * congruential method.</span>
+<a name="l00041"></a>00041 <span class="comment"> */</span>
+<a name="l00042"></a>00042 ODE_API <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> dRand(<span class="keywordtype">void</span>);
+<a name="l00043"></a>00043 
+<a name="l00044"></a>00044 <span class="comment">/* get and set the current random number seed. */</span>
+<a name="l00045"></a>00045 ODE_API <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>  dRandGetSeed(<span class="keywordtype">void</span>);
+<a name="l00046"></a>00046 ODE_API <span class="keywordtype">void</span> dRandSetSeed (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> s);
+<a name="l00047"></a>00047 
+<a name="l00048"></a>00048 <span class="comment">/* return a random integer between 0..n-1. the distribution will get worse</span>
+<a name="l00049"></a>00049 <span class="comment"> * as n approaches 2^32.</span>
+<a name="l00050"></a>00050 <span class="comment"> */</span>
+<a name="l00051"></a>00051 ODE_API <span class="keywordtype">int</span> dRandInt (<span class="keywordtype">int</span> n);
+<a name="l00052"></a>00052 
+<a name="l00053"></a>00053 <span class="comment">/* return a random real number between 0..1 */</span>
+<a name="l00054"></a>00054 ODE_API dReal dRandReal(<span class="keywordtype">void</span>);
+<a name="l00055"></a>00055 
+<a name="l00056"></a>00056 <span class="comment">/* print out a matrix */</span>
+<a name="l00057"></a>00057 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00058"></a>00058 <span class="preprocessor"></span>ODE_API <span class="keywordtype">void</span> dPrintMatrix (<span class="keyword">const</span> dReal *A, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> m, <span class="keywordtype">char</span> *fmt = <span class="stringliteral">"%10.4f "</span>,
+<a name="l00059"></a>00059          FILE *f=stdout);
+<a name="l00060"></a>00060 <span class="preprocessor">#else</span>
+<a name="l00061"></a>00061 <span class="preprocessor"></span>ODE_API <span class="keywordtype">void</span> dPrintMatrix (<span class="keyword">const</span> dReal *A, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> m, <span class="keywordtype">char</span> *fmt, FILE *f);
+<a name="l00062"></a>00062 <span class="preprocessor">#endif</span>
+<a name="l00063"></a>00063 <span class="preprocessor"></span>
+<a name="l00064"></a>00064 <span class="comment">/* make a random vector with entries between +/- range. A has n elements. */</span>
+<a name="l00065"></a>00065 ODE_API <span class="keywordtype">void</span> dMakeRandomVector (dReal *A, <span class="keywordtype">int</span> n, dReal range);
+<a name="l00066"></a>00066 
+<a name="l00067"></a>00067 <span class="comment">/* make a random matrix with entries between +/- range. A has size n*m. */</span>
+<a name="l00068"></a>00068 ODE_API <span class="keywordtype">void</span> dMakeRandomMatrix (dReal *A, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> m, dReal range);
+<a name="l00069"></a>00069 
+<a name="l00070"></a>00070 <span class="comment">/* clear the upper triangle of a square matrix */</span>
+<a name="l00071"></a>00071 ODE_API <span class="keywordtype">void</span> dClearUpperTriangle (dReal *A, <span class="keywordtype">int</span> n);
+<a name="l00072"></a>00072 
+<a name="l00073"></a>00073 <span class="comment">/* return the maximum element difference between the two n*m matrices */</span>
+<a name="l00074"></a>00074 ODE_API dReal dMaxDifference (<span class="keyword">const</span> dReal *A, <span class="keyword">const</span> dReal *B, <span class="keywordtype">int</span> n, <span class="keywordtype">int</span> m);
+<a name="l00075"></a>00075 
+<a name="l00076"></a>00076 <span class="comment">/* return the maximum element difference between the lower triangle of two</span>
+<a name="l00077"></a>00077 <span class="comment"> * n*n matrices */</span>
+<a name="l00078"></a>00078 ODE_API dReal dMaxDifferenceLowerTriangle (<span class="keyword">const</span> dReal *A, <span class="keyword">const</span> dReal *B, <span class="keywordtype">int</span> n);
+<a name="l00079"></a>00079 
+<a name="l00080"></a>00080 
+<a name="l00081"></a>00081 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00082"></a>00082 <span class="preprocessor"></span>}
+<a name="l00083"></a>00083 <span class="preprocessor">#endif</span>
+<a name="l00084"></a>00084 <span class="preprocessor"></span>
+<a name="l00085"></a>00085 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/modules.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/modules.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/modules.html	(revision 216)
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: Module Index</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li class="current"><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>Open Dynamics Engine Modules</h1>Here is a list of all modules:<ul>
+<li><a class="el" href="group__collide.html">Collision Detection</a>
+<ul>
+<li><a class="el" href="group__collide__sphere.html">Sphere Class</a>
+<li><a class="el" href="group__collide__box.html">Box Class</a>
+</ul>
+<li><a class="el" href="group__world.html">World</a>
+<li><a class="el" href="group__disable.html">Automatic Enabling and Disabling</a>
+<li><a class="el" href="group__bodies.html">Rigid Bodies</a>
+<li><a class="el" href="group__joints.html">Joints</a>
+<li><a class="el" href="group__drawstuff.html">DrawStuff</a>
+</ul>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/objects_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/objects_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/objects_8h-source.html	(revision 216)
@@ -0,0 +1,563 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: objects.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>objects.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_OBJECTS_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_OBJECTS_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 <span class="preprocessor">#include &lt;ode/mass.h&gt;</span>
+<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;ode/contact.h&gt;</span>
+<a name="l00029"></a>00029 
+<a name="l00030"></a>00030 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00032"></a>00032 <span class="preprocessor">#endif</span>
+<a name="l00033"></a>00033 <span class="preprocessor"></span>
+<a name="l00052"></a>00052 ODE_API dWorldID <a class="code" href="group__world.html#g929067266d630fb745f752042d685fc7" title="Create a new, empty world and return its ID number.">dWorldCreate</a>(<span class="keywordtype">void</span>);
+<a name="l00053"></a>00053 
+<a name="l00054"></a>00054 
+<a name="l00064"></a>00064 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#g5a2e5b1d2d6a1376dca239b488e629f9" title="Destroy a world and everything in it.">dWorldDestroy</a> (dWorldID world);
+<a name="l00065"></a>00065 
+<a name="l00066"></a>00066 
+<a name="l00075"></a>00075 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#ga1b220b922215b335572c699cf8f8cad" title="Set the world&amp;#39;s global gravity vector.">dWorldSetGravity</a> (dWorldID, dReal x, dReal y, dReal z);
+<a name="l00076"></a>00076 
+<a name="l00077"></a>00077 
+<a name="l00082"></a>00082 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#ge1a29b6a91cc1910a982c916ae4dee4a" title="Get the gravity vector for a given world.">dWorldGetGravity</a> (dWorldID, dVector3 gravity);
+<a name="l00083"></a>00083 
+<a name="l00084"></a>00084 
+<a name="l00092"></a>00092 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#gacd0778bdaa939d22f093fc2d5d5f868" title="Set the global ERP value, that controls how much error correction is performed in...">dWorldSetERP</a> (dWorldID, dReal erp);
+<a name="l00093"></a>00093 
+<a name="l00099"></a>00099 ODE_API dReal <a class="code" href="group__world.html#g033cd87a0b22889a94d4d84149bda5a0" title="Get the error reduction parameter.">dWorldGetERP</a> (dWorldID);
+<a name="l00100"></a>00100 
+<a name="l00101"></a>00101 
+<a name="l00109"></a>00109 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#g8b7913fe46d0afc468418c655da79233" title="Set the global CFM (constraint force mixing) value.">dWorldSetCFM</a> (dWorldID, dReal cfm);
+<a name="l00110"></a>00110 
+<a name="l00116"></a>00116 ODE_API dReal <a class="code" href="group__world.html#gc7a431f2b3fc6f887fe91ad676828ba3" title="Get the constraint force mixing value.">dWorldGetCFM</a> (dWorldID);
+<a name="l00117"></a>00117 
+<a name="l00118"></a>00118 
+<a name="l00129"></a>00129 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#g8f547ebeb3deed27e0f7b8143d475f50" title="Step the world.">dWorldStep</a> (dWorldID, dReal stepsize);
+<a name="l00130"></a>00130 
+<a name="l00131"></a>00131 
+<a name="l00146"></a>00146 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#ga9c564b4dd7d8fa4c6f4b32dd95fc33a" title="Converts an impulse to a force.">dWorldImpulseToForce</a>
+<a name="l00147"></a>00147 (
+<a name="l00148"></a>00148   dWorldID, dReal stepsize,
+<a name="l00149"></a>00149   dReal ix, dReal iy, dReal iz, dVector3 force
+<a name="l00150"></a>00150 );
+<a name="l00151"></a>00151 
+<a name="l00152"></a>00152 
+<a name="l00184"></a>00184 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#gc24fadc1d42b65ca3563e40bc1f0fec1" title="Step the world.">dWorldQuickStep</a> (dWorldID w, dReal stepsize);
+<a name="l00185"></a>00185 
+<a name="l00186"></a>00186 
+<a name="l00196"></a>00196 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#g9d852689d87d28a3d4947eda59c5ba7e" title="Set the number of iterations that the QuickStep method performs per step.">dWorldSetQuickStepNumIterations</a> (dWorldID, <span class="keywordtype">int</span> num);
+<a name="l00197"></a>00197 
+<a name="l00198"></a>00198 
+<a name="l00205"></a>00205 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__world.html#ga51acfac06347fd27ff926d37672ce3c" title="Get the number of iterations that the QuickStep method performs per step.">dWorldGetQuickStepNumIterations</a> (dWorldID);
+<a name="l00206"></a>00206 
+<a name="l00212"></a>00212 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#gf741ee61e3f9981ae102729f23aad535" title="Set the SOR over-relaxation parameter.">dWorldSetQuickStepW</a> (dWorldID, dReal over_relaxation);
+<a name="l00213"></a>00213 
+<a name="l00219"></a>00219 ODE_API dReal <a class="code" href="group__world.html#ga7fef06f7a8293f21778939dfea36951" title="Get the SOR over-relaxation parameter.">dWorldGetQuickStepW</a> (dWorldID);
+<a name="l00220"></a>00220 
+<a name="l00221"></a>00221 <span class="comment">/* World contact parameter functions */</span>
+<a name="l00222"></a>00222 
+<a name="l00231"></a>00231 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#g2cec4be3f40d49c5950ceac1a28440d8" title="Set the maximum correcting velocity that contacts are allowed to generate.">dWorldSetContactMaxCorrectingVel</a> (dWorldID, dReal vel);
+<a name="l00232"></a>00232 
+<a name="l00238"></a>00238 ODE_API dReal <a class="code" href="group__world.html#g7673e6d0db3ddb319642caea7d14959d" title="Get the maximum correcting velocity that contacts are allowed to generated.">dWorldGetContactMaxCorrectingVel</a> (dWorldID);
+<a name="l00239"></a>00239 
+<a name="l00251"></a>00251 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#g8f6f964bc15b6cf0937d3214f6e3a1f1" title="Set the depth of the surface layer around all geometry objects.">dWorldSetContactSurfaceLayer</a> (dWorldID, dReal depth);
+<a name="l00252"></a>00252 
+<a name="l00258"></a>00258 ODE_API dReal <a class="code" href="group__world.html#g97e1c98f55d9b56d00e7838900ad5e58" title="Get the depth of the surface layer around all geometry objects.">dWorldGetContactSurfaceLayer</a> (dWorldID);
+<a name="l00259"></a>00259 
+<a name="l00260"></a>00260 <span class="comment">/* StepFast1 functions */</span>
+<a name="l00261"></a>00261 
+<a name="l00268"></a>00268 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__world.html#gefa68c714bb3c8f70503f101ea062c03" title="Step the world using the StepFast1 algorithm.">dWorldStepFast1</a>(dWorldID, dReal stepsize, <span class="keywordtype">int</span> maxiterations);
+<a name="l00269"></a>00269 
+<a name="l00270"></a>00270 
+<a name="l00306"></a>00306 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#g280c6deffe6b4b8ba39d60bf25355347" title="Set the AutoEnableDepth parameter used by the StepFast1 algorithm.">dWorldSetAutoEnableDepthSF1</a>(dWorldID, <span class="keywordtype">int</span> autoEnableDepth);
+<a name="l00307"></a>00307 
+<a name="l00312"></a>00312 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__disable.html#g5438f43d9c71d8090a44171f685de196" title="Get the AutoEnableDepth parameter used by the StepFast1 algorithm.">dWorldGetAutoEnableDepthSF1</a>(dWorldID);
+<a name="l00313"></a>00313 
+<a name="l00319"></a>00319 ODE_API dReal <a class="code" href="group__disable.html#g48802a9736cc8cc9c1a14cbc3125d9b2" title="Get auto disable linear threshold for newly created bodies.">dWorldGetAutoDisableLinearThreshold</a> (dWorldID);
+<a name="l00320"></a>00320 
+<a name="l00326"></a>00326 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__disable.html#ga1070c6f127352fb0a87ab1d42677b8e" title="Set auto disable linear threshold for newly created bodies.">dWorldSetAutoDisableLinearThreshold</a> (dWorldID, dReal linear_threshold);
+<a name="l00327"></a>00327 
+<a name="l00333"></a>00333 ODE_API dReal <a class="code" href="group__disable.html#g9d32b31b5d343c324897434a97387abc" title="Get auto disable angular threshold for newly created bodies.">dWorldGetAutoDisableAngularThreshold</a> (dWorldID);
+<a name="l00334"></a>00334 
+<a name="l00340"></a>00340 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#g61cae2bd156129a918c3a1e69ac1b6dd" title="Set auto disable angular threshold for newly created bodies.">dWorldSetAutoDisableAngularThreshold</a> (dWorldID, dReal angular_threshold);
+<a name="l00341"></a>00341 
+<a name="l00347"></a>00347 ODE_API dReal <a class="code" href="group__disable.html#g947e2d43df920a26fb52b5273ea9856b" title="Get auto disable linear average threshold for newly created bodies.">dWorldGetAutoDisableLinearAverageThreshold</a> (dWorldID);
+<a name="l00348"></a>00348 
+<a name="l00354"></a>00354 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__disable.html#g3e5ef82227b955c545efc40d60ef1b21" title="Set auto disable linear average threshold for newly created bodies.">dWorldSetAutoDisableLinearAverageThreshold</a> (dWorldID, dReal linear_average_threshold);
+<a name="l00355"></a>00355 
+<a name="l00361"></a>00361 ODE_API dReal <a class="code" href="group__disable.html#gb9bd57f1bef49a8d9d6985462c078b02" title="Get auto disable angular average threshold for newly created bodies.">dWorldGetAutoDisableAngularAverageThreshold</a> (dWorldID);
+<a name="l00362"></a>00362 
+<a name="l00368"></a>00368 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#gca94337cc27914fe4bc00ebce83f231a" title="Set auto disable angular average threshold for newly created bodies.">dWorldSetAutoDisableAngularAverageThreshold</a> (dWorldID, dReal angular_average_threshold);
+<a name="l00369"></a>00369 
+<a name="l00375"></a>00375 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__disable.html#g4343cfd23eb87f3ee629a9d13833c2ac" title="Get auto disable sample count for newly created bodies.">dWorldGetAutoDisableAverageSamplesCount</a> (dWorldID);
+<a name="l00376"></a>00376 
+<a name="l00383"></a>00383 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#g2babd1af3df87518e5bac9dfcb392593" title="Set auto disable average sample count for newly created bodies.">dWorldSetAutoDisableAverageSamplesCount</a> (dWorldID, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> average_samples_count );
+<a name="l00384"></a>00384 
+<a name="l00390"></a>00390 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__disable.html#gb0a26f648b9e40d8d4639bf187d5ac94" title="Get auto disable steps for newly created bodies.">dWorldGetAutoDisableSteps</a> (dWorldID);
+<a name="l00391"></a>00391 
+<a name="l00397"></a>00397 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#gdb9f69119d1aa259a0e32a8ff94e2535" title="Set auto disable steps for newly created bodies.">dWorldSetAutoDisableSteps</a> (dWorldID, <span class="keywordtype">int</span> steps);
+<a name="l00398"></a>00398 
+<a name="l00404"></a>00404 ODE_API dReal <a class="code" href="group__disable.html#gbc004c37efff5f962fa2ac271b3be8e1" title="Get auto disable time for newly created bodies.">dWorldGetAutoDisableTime</a> (dWorldID);
+<a name="l00405"></a>00405 
+<a name="l00411"></a>00411 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#g06828866a19cab7aeb129ca9ec76863b" title="Set auto disable time for newly created bodies.">dWorldSetAutoDisableTime</a> (dWorldID, dReal time);
+<a name="l00412"></a>00412 
+<a name="l00418"></a>00418 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__disable.html#g7617d19f08c7b1d22cf17ccf22bbdc00" title="Get auto disable flag for newly created bodies.">dWorldGetAutoDisableFlag</a> (dWorldID);
+<a name="l00419"></a>00419 
+<a name="l00425"></a>00425 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__disable.html#g58959b92ae4706e612bca673e85bfc50" title="Set auto disable flag for newly created bodies.">dWorldSetAutoDisableFlag</a> (dWorldID, <span class="keywordtype">int</span> do_auto_disable);
+<a name="l00426"></a>00426 
+<a name="l00427"></a>00427 
+<a name="l00428"></a>00428 
+<a name="l00468"></a>00468 ODE_API dReal <a class="code" href="group__bodies.html#g57c1e1b1bd50fdcafc5140c1ed89c7d7" title="Get auto disable linear average threshold.">dBodyGetAutoDisableLinearThreshold</a> (dBodyID);
+<a name="l00469"></a>00469 
+<a name="l00475"></a>00475 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__bodies.html#gb8f6e736830cfea86c35e7a0cdfa3112" title="Set auto disable linear average threshold.">dBodySetAutoDisableLinearThreshold</a> (dBodyID, dReal linear_average_threshold);
+<a name="l00476"></a>00476 
+<a name="l00482"></a>00482 ODE_API dReal <a class="code" href="group__bodies.html#g5b988719423e9bc3af1be2146872e2d6" title="Get auto disable angular average threshold.">dBodyGetAutoDisableAngularThreshold</a> (dBodyID);
+<a name="l00483"></a>00483 
+<a name="l00489"></a>00489 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__bodies.html#g206ccf22f027a62aaf5e45a16ddc4040" title="Set auto disable angular average threshold.">dBodySetAutoDisableAngularThreshold</a> (dBodyID, dReal angular_average_threshold);
+<a name="l00490"></a>00490 
+<a name="l00496"></a>00496 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#gf398254a02ab5bedcdf7e4fb2918a902" title="Get auto disable average size (samples count).">dBodyGetAutoDisableAverageSamplesCount</a> (dBodyID);
+<a name="l00497"></a>00497 
+<a name="l00503"></a>00503 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g4bce13aaa5ffb7d4b3452191974c3be6" title="Set auto disable average buffer size (average steps).">dBodySetAutoDisableAverageSamplesCount</a> (dBodyID, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> average_samples_count);
+<a name="l00504"></a>00504 
+<a name="l00505"></a>00505 
+<a name="l00511"></a>00511 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#g797ad84c737a2ae4ef3f8a37dfa02183" title="Get auto steps a body must be thought of as idle to disable.">dBodyGetAutoDisableSteps</a> (dBodyID);
+<a name="l00512"></a>00512 
+<a name="l00518"></a>00518 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g03cc329bdc8e19e59c4bfe62cf736578" title="Set auto disable steps.">dBodySetAutoDisableSteps</a> (dBodyID, <span class="keywordtype">int</span> steps);
+<a name="l00519"></a>00519 
+<a name="l00525"></a>00525 ODE_API dReal <a class="code" href="group__bodies.html#ga2f4d01a8fb5c4d7e77efd5f0e4dd72b" title="Get auto disable time.">dBodyGetAutoDisableTime</a> (dBodyID);
+<a name="l00526"></a>00526 
+<a name="l00532"></a>00532 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__bodies.html#g0ae2f08bb38359934151f9420cdef341" title="Set auto disable time.">dBodySetAutoDisableTime</a> (dBodyID, dReal time);
+<a name="l00533"></a>00533 
+<a name="l00539"></a>00539 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#gfe44b3ae620abb1091472089cb07f64e" title="Get auto disable flag.">dBodyGetAutoDisableFlag</a> (dBodyID);
+<a name="l00540"></a>00540 
+<a name="l00546"></a>00546 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#ge352fdcd8851224f07da53f35691ceb7" title="Set auto disable flag.">dBodySetAutoDisableFlag</a> (dBodyID, <span class="keywordtype">int</span> do_auto_disable);
+<a name="l00547"></a>00547 
+<a name="l00554"></a>00554 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__bodies.html#g00969db4aebc2e8629cd9c45f3b7385e" title="Set auto disable defaults.">dBodySetAutoDisableDefaults</a> (dBodyID);
+<a name="l00555"></a>00555 
+<a name="l00556"></a>00556 
+<a name="l00563"></a>00563 ODE_API dWorldID <a class="code" href="group__bodies.html#gb044b0a466f2ec2af3fd29ae399e822e" title="Retrives the world attached to te given body.">dBodyGetWorld</a> (dBodyID);
+<a name="l00564"></a>00564 
+<a name="l00571"></a>00571 ODE_API dBodyID <a class="code" href="group__bodies.html#g578137bbaf82d4b8896d2baee3a032a6" title="Create a body in given world.">dBodyCreate</a> (dWorldID);
+<a name="l00572"></a>00572 
+<a name="l00581"></a>00581 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gc1a0ee96898f14017a29b2afa0eafe13" title="Destroy a body.">dBodyDestroy</a> (dBodyID);
+<a name="l00582"></a>00582 
+<a name="l00588"></a>00588 ODE_API <span class="keywordtype">void</span>  <a class="code" href="group__bodies.html#gf9cbe9e1ed1bd4559bb5603b8d0f92f2" title="Set the body&amp;#39;s user-data pointer.">dBodySetData</a> (dBodyID, <span class="keywordtype">void</span> *data);
+<a name="l00589"></a>00589 
+<a name="l00595"></a>00595 ODE_API <span class="keywordtype">void</span> *<a class="code" href="group__bodies.html#g68d3d80c7476776dd4512d577bf70325" title="Get the body&amp;#39;s user-data pointer.">dBodyGetData</a> (dBodyID);
+<a name="l00596"></a>00596 
+<a name="l00605"></a>00605 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gb84612b793366f18ff5b5cbdbed092da" title="Set position of a body.">dBodySetPosition</a>   (dBodyID, dReal x, dReal y, dReal z);
+<a name="l00606"></a>00606 
+<a name="l00615"></a>00615 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gb5f04968ec37ef46d2aaffad6c344468" title="Set the orientation of a body.">dBodySetRotation</a>   (dBodyID, <span class="keyword">const</span> dMatrix3 R);
+<a name="l00616"></a>00616 
+<a name="l00625"></a>00625 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#ga5f51dd3605c402320e9eae4231d7ad4" title="Set the orientation of a body.">dBodySetQuaternion</a> (dBodyID, <span class="keyword">const</span> dQuaternion q);
+<a name="l00626"></a>00626 
+<a name="l00631"></a>00631 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gafe72e03c1df0f2150e2d7b8677e1460" title="Set the linear velocity of a body.">dBodySetLinearVel</a>  (dBodyID, dReal x, dReal y, dReal z);
+<a name="l00632"></a>00632 
+<a name="l00637"></a>00637 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g7b4f90c1986333395375c086c4f3ec41" title="Set the angular velocity of a body.">dBodySetAngularVel</a> (dBodyID, dReal x, dReal y, dReal z);
+<a name="l00638"></a>00638 
+<a name="l00648"></a>00648 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#g2bddae29591b9f14c5175411b783d570" title="Get the position of a body.">dBodyGetPosition</a>   (dBodyID);
+<a name="l00649"></a>00649 
+<a name="l00650"></a>00650 
+<a name="l00658"></a>00658 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gf69c1ebd1c8d7d165fe740c9f1146217" title="Copy the position of a body into a vector.">dBodyCopyPosition</a> (dBodyID body, dVector3 pos);
+<a name="l00659"></a>00659 
+<a name="l00660"></a>00660 
+<a name="l00666"></a>00666 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#g2374da7ff88a2bac607e2fbce529ad27" title="Get the rotation of a body.">dBodyGetRotation</a>   (dBodyID);
+<a name="l00667"></a>00667 
+<a name="l00668"></a>00668 
+<a name="l00676"></a>00676 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#ga992006681bc720c6c6ef644768226e5" title="Copy the rotation of a body.">dBodyCopyRotation</a> (dBodyID, dMatrix3 R);
+<a name="l00677"></a>00677 
+<a name="l00678"></a>00678 
+<a name="l00684"></a>00684 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#g36b7e19622ed47fe6b9dcfbac20237e7" title="Get the rotation of a body.">dBodyGetQuaternion</a> (dBodyID);
+<a name="l00685"></a>00685 
+<a name="l00686"></a>00686 
+<a name="l00694"></a>00694 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gd906c3ad061b7f70d1c60d6957aa2d0f" title="Copy the orientation of a body into a quaternion.">dBodyCopyQuaternion</a>(dBodyID body, dQuaternion quat);
+<a name="l00695"></a>00695 
+<a name="l00696"></a>00696 
+<a name="l00701"></a>00701 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#g2a0a986c12d53efd5a3753dd4b509cac" title="Get the linear velocity of a body.">dBodyGetLinearVel</a>  (dBodyID);
+<a name="l00702"></a>00702 
+<a name="l00707"></a>00707 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#g54dc73be9562cdece52d0a7d8decd1d0" title="Get the angular velocity of a body.">dBodyGetAngularVel</a> (dBodyID);
+<a name="l00708"></a>00708 
+<a name="l00713"></a>00713 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gf3609b58548e34471ef8ad4727b33e52" title="Set the mass of a body.">dBodySetMass</a> (dBodyID, <span class="keyword">const</span> dMass *mass);
+<a name="l00714"></a>00714 
+<a name="l00719"></a>00719 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g7aa7944f6e36a96d3e578f3369ac4171" title="Get the mass of a body.">dBodyGetMass</a> (dBodyID, dMass *mass);
+<a name="l00720"></a>00720 
+<a name="l00725"></a>00725 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g1e1352dc350ad42bff5818f2200ba792" title="Add force at centre of mass of body in absolute coordinates.">dBodyAddForce</a>            (dBodyID, dReal fx, dReal fy, dReal fz);
+<a name="l00726"></a>00726 
+<a name="l00731"></a>00731 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque</a>           (dBodyID, dReal fx, dReal fy, dReal fz);
+<a name="l00732"></a>00732 
+<a name="l00737"></a>00737 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g0a91e5416c5af7729177c465346837ad" title="Add force at centre of mass of body in coordinates relative to body.">dBodyAddRelForce</a>         (dBodyID, dReal fx, dReal fy, dReal fz);
+<a name="l00738"></a>00738 
+<a name="l00743"></a>00743 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g172a59e64f6dfa4a59bcd45b694585de" title="Add torque at centre of mass of body in coordinates relative to body.">dBodyAddRelTorque</a>        (dBodyID, dReal fx, dReal fy, dReal fz);
+<a name="l00744"></a>00744 
+<a name="l00749"></a>00749 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gfa134c6b7b455680b890b677c5789c2b" title="Add force at specified point in body in global coordinates.">dBodyAddForceAtPos</a>       (dBodyID, dReal fx, dReal fy, dReal fz,
+<a name="l00750"></a>00750                          dReal px, dReal py, dReal pz);
+<a name="l00755"></a>00755 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g77606cdb23029337a7ed43dee5a59ee1" title="Add force at specified point in body in local coordinates.">dBodyAddForceAtRelPos</a>    (dBodyID, dReal fx, dReal fy, dReal fz,
+<a name="l00756"></a>00756                          dReal px, dReal py, dReal pz);
+<a name="l00761"></a>00761 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#ga024b08f8dfb85705b86e18b99a0ef8e" title="Add force at specified point in body in global coordinates.">dBodyAddRelForceAtPos</a>    (dBodyID, dReal fx, dReal fy, dReal fz,
+<a name="l00762"></a>00762                          dReal px, dReal py, dReal pz);
+<a name="l00767"></a>00767 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g7e5d20b6bb36f74d0dedb08f5eefddcb" title="Add force at specified point in body in local coordinates.">dBodyAddRelForceAtRelPos</a> (dBodyID, dReal fx, dReal fy, dReal fz,
+<a name="l00768"></a>00768                          dReal px, dReal py, dReal pz);
+<a name="l00769"></a>00769 
+<a name="l00779"></a>00779 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#g3b458397a79f09b1957cb6e5a85e9eba" title="Return the current accumulated force vector.">dBodyGetForce</a>   (dBodyID);
+<a name="l00780"></a>00780 
+<a name="l00790"></a>00790 ODE_API <span class="keyword">const</span> dReal * <a class="code" href="group__bodies.html#gfe88a5bc363fc812c8f154e3d5f8ea5d" title="Return the current accumulated torque vector.">dBodyGetTorque</a>  (dBodyID);
+<a name="l00791"></a>00791 
+<a name="l00800"></a>00800 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gbd56079db36d4562db0e18aebea4f95f" title="Set the body force accumulation vector.">dBodySetForce</a>  (dBodyID b, dReal x, dReal y, dReal z);
+<a name="l00801"></a>00801 
+<a name="l00810"></a>00810 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gfcd3e44223a878ba52428ad3a124fa94" title="Set the body torque accumulation vector.">dBodySetTorque</a> (dBodyID b, dReal x, dReal y, dReal z);
+<a name="l00811"></a>00811 
+<a name="l00817"></a>00817 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gfcf00cd9c4c754c82189fb9d1eb9f102" title="Get world position of a relative point on body.">dBodyGetRelPointPos</a>
+<a name="l00818"></a>00818 (
+<a name="l00819"></a>00819   dBodyID, dReal px, dReal py, dReal pz,
+<a name="l00820"></a>00820   dVector3 result
+<a name="l00821"></a>00821 );
+<a name="l00822"></a>00822 
+<a name="l00828"></a>00828 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g7fd4f4c7e70c59380da11277b2e97510" title="Get velocity vector in global coords of a relative point on body.">dBodyGetRelPointVel</a>
+<a name="l00829"></a>00829 (
+<a name="l00830"></a>00830   dBodyID, dReal px, dReal py, dReal pz,
+<a name="l00831"></a>00831   dVector3 result
+<a name="l00832"></a>00832 );
+<a name="l00833"></a>00833 
+<a name="l00840"></a>00840 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g89dd6a4a3c6f3cd98c8377e8d4dec015" title="Get velocity vector in global coords of a globally specified point on a body.">dBodyGetPointVel</a>
+<a name="l00841"></a>00841 (
+<a name="l00842"></a>00842   dBodyID, dReal px, dReal py, dReal pz,
+<a name="l00843"></a>00843   dVector3 result
+<a name="l00844"></a>00844 );
+<a name="l00845"></a>00845 
+<a name="l00854"></a>00854 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g0334d9d523cbfeec742ac4a814834199" title="takes a point in global coordinates and returns the point&amp;#39;s position in body-relative...">dBodyGetPosRelPoint</a>
+<a name="l00855"></a>00855 (
+<a name="l00856"></a>00856   dBodyID, dReal px, dReal py, dReal pz,
+<a name="l00857"></a>00857   dVector3 result
+<a name="l00858"></a>00858 );
+<a name="l00859"></a>00859 
+<a name="l00865"></a>00865 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g0a2cd6f7499bcfeb8275cbb981465bbf" title="Convert from local to world coordinates.">dBodyVectorToWorld</a>
+<a name="l00866"></a>00866 (
+<a name="l00867"></a>00867   dBodyID, dReal px, dReal py, dReal pz,
+<a name="l00868"></a>00868   dVector3 result
+<a name="l00869"></a>00869 );
+<a name="l00870"></a>00870 
+<a name="l00876"></a>00876 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g1e3ac3ef038e806d4942ea8b399ab575" title="Convert from world to local coordinates.">dBodyVectorFromWorld</a>
+<a name="l00877"></a>00877 (
+<a name="l00878"></a>00878   dBodyID, dReal px, dReal py, dReal pz,
+<a name="l00879"></a>00879   dVector3 result
+<a name="l00880"></a>00880 );
+<a name="l00881"></a>00881 
+<a name="l00899"></a>00899 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gc474ca36d734fb67b8bd504b672527fa" title="controls the way a body&amp;#39;s orientation is updated at each timestep.">dBodySetFiniteRotationMode</a> (dBodyID, <span class="keywordtype">int</span> mode);
+<a name="l00900"></a>00900 
+<a name="l00917"></a>00917 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#ga9546c1ea6119fcbf80c71a96f56d052" title="sets the finite rotation axis for a body.">dBodySetFiniteRotationAxis</a> (dBodyID, dReal x, dReal y, dReal z);
+<a name="l00918"></a>00918 
+<a name="l00924"></a>00924 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#g3fb10ac984d64c92e4f138e50b704f9e" title="Get the way a body&amp;#39;s orientation is updated each timestep.">dBodyGetFiniteRotationMode</a> (dBodyID);
+<a name="l00925"></a>00925 
+<a name="l00931"></a>00931 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gfc8853ff678be731881665ff7abf61ad" title="Get the finite rotation axis.">dBodyGetFiniteRotationAxis</a> (dBodyID, dVector3 result);
+<a name="l00932"></a>00932 
+<a name="l00938"></a>00938 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#g79fd517a57ac9c3594cb71850f649af7" title="Get the number of joints that are attached to this body.">dBodyGetNumJoints</a> (dBodyID b);
+<a name="l00939"></a>00939 
+<a name="l00946"></a>00946 ODE_API dJointID <a class="code" href="group__bodies.html#g095e41c5b5632b22aa9bd1a4bd051f8d" title="Return a joint attached to this body, given by index.">dBodyGetJoint</a> (dBodyID, <span class="keywordtype">int</span> index);
+<a name="l00947"></a>00947 
+<a name="l00953"></a>00953 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#gd0776c40f667b235f8642e10755543f8" title="Manually enable a body.">dBodyEnable</a> (dBodyID);
+<a name="l00954"></a>00954 
+<a name="l00962"></a>00962 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#ga78092d7cadae36373441aa9be7e6157" title="Manually disable a body.">dBodyDisable</a> (dBodyID);
+<a name="l00963"></a>00963 
+<a name="l00969"></a>00969 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#g7e7803132dfcfceee04a6ab0ca1e0bf8" title="Check wether a body is enabled.">dBodyIsEnabled</a> (dBodyID);
+<a name="l00970"></a>00970 
+<a name="l00978"></a>00978 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__bodies.html#g5465d605e7fbe82d63a0d4e1000da731" title="Set whether the body is influenced by the world&amp;#39;s gravity or not.">dBodySetGravityMode</a> (dBodyID b, <span class="keywordtype">int</span> mode);
+<a name="l00979"></a>00979 
+<a name="l00985"></a>00985 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__bodies.html#g0df2f4fed454c567f10fc8bbb8c70455" title="Get whether the body is influenced by the world&amp;#39;s gravity or not.">dBodyGetGravityMode</a> (dBodyID b);
+<a name="l00986"></a>00986 
+<a name="l00987"></a>00987 
+<a name="l00988"></a>00988 
+<a name="l01064"></a>01064 ODE_API dJointID <a class="code" href="group__joints.html#g2d23509f8d6c6066b361af4cf14166f7" title="Create a new joint of the ball type.">dJointCreateBall</a> (dWorldID, dJointGroupID);
+<a name="l01065"></a>01065 
+<a name="l01072"></a>01072 ODE_API dJointID <a class="code" href="group__joints.html#g2f18d431d48c905abc9d72ce011c00bd" title="Create a new joint of the hinge type.">dJointCreateHinge</a> (dWorldID, dJointGroupID);
+<a name="l01073"></a>01073 
+<a name="l01080"></a>01080 ODE_API dJointID <a class="code" href="group__joints.html#geccc4c67b2d409016685a6a9163be539" title="Create a new joint of the slider type.">dJointCreateSlider</a> (dWorldID, dJointGroupID);
+<a name="l01081"></a>01081 
+<a name="l01088"></a>01088 ODE_API dJointID <a class="code" href="group__joints.html#gfa5e1543239ba44ecbdc178ebc7c3cc4" title="Create a new joint of the contact type.">dJointCreateContact</a> (dWorldID, dJointGroupID, <span class="keyword">const</span> dContact *);
+<a name="l01089"></a>01089 
+<a name="l01096"></a>01096 ODE_API dJointID <a class="code" href="group__joints.html#g6a6e32d35bdda9352d1be8d4df973f8f" title="Create a new joint of the hinge2 type.">dJointCreateHinge2</a> (dWorldID, dJointGroupID);
+<a name="l01097"></a>01097 
+<a name="l01104"></a>01104 ODE_API dJointID <a class="code" href="group__joints.html#g1cb2e7668242313b5d24acb5d43e5c62" title="Create a new joint of the universal type.">dJointCreateUniversal</a> (dWorldID, dJointGroupID);
+<a name="l01105"></a>01105 
+<a name="l01112"></a>01112 ODE_API dJointID <a class="code" href="group__joints.html#gdc867f10ba9931d191244fa879e43cb2" title="Create a new joint of the PR (Prismatic and Rotoide) type.">dJointCreatePR</a> (dWorldID, dJointGroupID);
+<a name="l01113"></a>01113 
+<a name="l01120"></a>01120 ODE_API dJointID <a class="code" href="group__joints.html#ge568995d03077e1acb13882a627dcf32" title="Create a new joint of the fixed type.">dJointCreateFixed</a> (dWorldID, dJointGroupID);
+<a name="l01121"></a>01121 
+<a name="l01122"></a>01122 ODE_API dJointID dJointCreateNull (dWorldID, dJointGroupID);
+<a name="l01123"></a>01123 
+<a name="l01130"></a>01130 ODE_API dJointID <a class="code" href="group__joints.html#gf23195ce77e12031393e591abd0e28e6" title="Create a new joint of the A-motor type.">dJointCreateAMotor</a> (dWorldID, dJointGroupID);
+<a name="l01131"></a>01131 
+<a name="l01138"></a>01138 ODE_API dJointID <a class="code" href="group__joints.html#g21c8c99615269c5d9d3c57c674f6fd56" title="Create a new joint of the L-motor type.">dJointCreateLMotor</a> (dWorldID, dJointGroupID);
+<a name="l01139"></a>01139 
+<a name="l01146"></a>01146 ODE_API dJointID <a class="code" href="group__joints.html#g7e68f39530acad9c0e7a38c8a3799b38" title="Create a new joint of the plane-2d type.">dJointCreatePlane2D</a> (dWorldID, dJointGroupID);
+<a name="l01147"></a>01147 
+<a name="l01156"></a>01156 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (dJointID);
+<a name="l01157"></a>01157 
+<a name="l01158"></a>01158 
+<a name="l01164"></a>01164 ODE_API dJointGroupID <a class="code" href="group__joints.html#gaaec687b184a1214133a41503e7c628f" title="Create a joint group.">dJointGroupCreate</a> (<span class="keywordtype">int</span> max_size);
+<a name="l01165"></a>01165 
+<a name="l01172"></a>01172 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g49e664ee9a8bd7bfe5e6932bf936bb8f" title="Destroy a joint group.">dJointGroupDestroy</a> (dJointGroupID);
+<a name="l01173"></a>01173 
+<a name="l01181"></a>01181 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g6e055bac8a0a3261bda3b6d07499c4ea" title="Empty a joint group.">dJointGroupEmpty</a> (dJointGroupID);
+<a name="l01182"></a>01182 
+<a name="l01196"></a>01196 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g8f1c9b1302c799a1b87bc29b76d0dcec" title="Attach the joint to some new bodies.">dJointAttach</a> (dJointID, dBodyID body1, dBodyID body2);
+<a name="l01197"></a>01197 
+<a name="l01202"></a>01202 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g5ca72d8bd498ef1ba920b0b473e79d02" title="Set the user-data pointer.">dJointSetData</a> (dJointID, <span class="keywordtype">void</span> *data);
+<a name="l01203"></a>01203 
+<a name="l01208"></a>01208 ODE_API <span class="keywordtype">void</span> *<a class="code" href="group__joints.html#g607702a11bae2d2613295f67088b0e82" title="Get the user-data pointer.">dJointGetData</a> (dJointID);
+<a name="l01209"></a>01209 
+<a name="l01224"></a>01224 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#g6f12f69d9b1a457428a28c2f77148174" title="Get the type of the joint.">dJointGetType</a> (dJointID);
+<a name="l01225"></a>01225 
+<a name="l01236"></a>01236 ODE_API dBodyID <a class="code" href="group__joints.html#gff13cbb464f1bfdc225fc9202c2c54c3" title="Return the bodies that this joint connects.">dJointGetBody</a> (dJointID, <span class="keywordtype">int</span> index);
+<a name="l01237"></a>01237 
+<a name="l01245"></a>01245 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g87ddb9beb95e9383a4280cb8a4186f01" title="Sets the datastructure that is to receive the feedback.">dJointSetFeedback</a> (dJointID, dJointFeedback *);
+<a name="l01246"></a>01246 
+<a name="l01251"></a>01251 ODE_API dJointFeedback *<a class="code" href="group__joints.html#gda1deef60d7afbb6b9375ddbf97e09a1" title="Gets the datastructure that is to receive the feedback.">dJointGetFeedback</a> (dJointID);
+<a name="l01252"></a>01252 
+<a name="l01260"></a>01260 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g058c33a3da1ff935a1125034f779dc4a" title="Set the joint anchor point.">dJointSetBallAnchor</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01261"></a>01261 
+<a name="l01266"></a>01266 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g51eb42782182a714be26bbd68f7a6d9a" title="Set the joint anchor point.">dJointSetBallAnchor2</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01267"></a>01267 
+<a name="l01272"></a>01272 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ge58f5e11c0829aa8615622a74dd11d85" title="Param setting for Ball joints.">dJointSetBallParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01273"></a>01273 
+<a name="l01278"></a>01278 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gc5727a125de0abbe2abd61af7a55da26" title="Set hinge anchor parameter.">dJointSetHingeAnchor</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01279"></a>01279 
+<a name="l01280"></a>01280 ODE_API <span class="keywordtype">void</span> dJointSetHingeAnchorDelta (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
+<a name="l01281"></a>01281 
+<a name="l01286"></a>01286 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ga434229f033472ec7aa031a01c6cabed" title="Set hinge axis.">dJointSetHingeAxis</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01287"></a>01287 
+<a name="l01292"></a>01292 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g6f9d34a01181e65639eb1f67da7a3e4c" title="set joint parameter">dJointSetHingeParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01293"></a>01293 
+<a name="l01302"></a>01302 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ga1725abe170f80b0731321ed38785019" title="Applies the torque about the hinge axis.">dJointAddHingeTorque</a>(dJointID joint, dReal torque);
+<a name="l01303"></a>01303 
+<a name="l01308"></a>01308 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gb2f662b1190507551f49ffa29d276b61" title="set the joint axis">dJointSetSliderAxis</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01309"></a>01309 
+<a name="l01313"></a>01313 ODE_API <span class="keywordtype">void</span> dJointSetSliderAxisDelta (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
+<a name="l01314"></a>01314 
+<a name="l01319"></a>01319 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g648964f4ca4122309e71a9cc6c24c985" title="set joint parameter">dJointSetSliderParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01320"></a>01320 
+<a name="l01329"></a>01329 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g8b0e018cc3df6ea5ddb42320913455e7" title="Applies the given force in the slider&amp;#39;s direction.">dJointAddSliderForce</a>(dJointID joint, dReal force);
+<a name="l01330"></a>01330 
+<a name="l01335"></a>01335 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gf839c13fa85aff0287a87986ff447d29" title="set anchor">dJointSetHinge2Anchor</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01336"></a>01336 
+<a name="l01341"></a>01341 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gcdf78fbb0f5b0a09b4d3ac2059b07002" title="set axis">dJointSetHinge2Axis1</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01342"></a>01342 
+<a name="l01347"></a>01347 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gdfef9f6365c87dacb95b4850a9e9f0ee" title="set axis">dJointSetHinge2Axis2</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01348"></a>01348 
+<a name="l01353"></a>01353 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g9a2d8d03776ccb22869667337457a7a9" title="set joint parameter">dJointSetHinge2Param</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01354"></a>01354 
+<a name="l01361"></a>01361 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ga5ba1541d092f28c93b1bdc3bfb1b69f" title="Applies torque1 about the hinge2&amp;#39;s axis 1, torque2 about the hinge2&amp;#39;s axis...">dJointAddHinge2Torques</a>(dJointID joint, dReal torque1, dReal torque2);
+<a name="l01362"></a>01362 
+<a name="l01367"></a>01367 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gaf4657aed67f3cd7cce775215995c05d" title="set anchor">dJointSetUniversalAnchor</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01368"></a>01368 
+<a name="l01373"></a>01373 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ge0a831da9447ff65d76a0808502038e8" title="set axis">dJointSetUniversalAxis1</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01374"></a>01374 
+<a name="l01379"></a>01379 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gf3668eed7dc5aaf8fee19d7f87347343" title="set axis">dJointSetUniversalAxis2</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01380"></a>01380 
+<a name="l01385"></a>01385 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g3c58284c43e997a028b06dc250064e32" title="set joint parameter">dJointSetUniversalParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01386"></a>01386 
+<a name="l01393"></a>01393 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g36607569e2ee26f39d3d42cba2397898" title="Applies torque1 about the universal&amp;#39;s axis 1, torque2 about the universal&amp;#39;s...">dJointAddUniversalTorques</a>(dJointID joint, dReal torque1, dReal torque2);
+<a name="l01394"></a>01394 
+<a name="l01395"></a>01395 
+<a name="l01400"></a>01400 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ge46251e2cea2d31521b1fb9b151f640f" title="set anchor">dJointSetPRAnchor</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01401"></a>01401 
+<a name="l01406"></a>01406 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ga2ae3ab1fa58ec22bd443476f786fa81" title="set the axis for the prismatic articulation">dJointSetPRAxis1</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01407"></a>01407 
+<a name="l01412"></a>01412 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gc8c61c6dd7b28a58a4c0eaf2e91ecbd5" title="set the axis for the rotoide articulation">dJointSetPRAxis2</a> (dJointID, dReal x, dReal y, dReal z);
+<a name="l01413"></a>01413 
+<a name="l01420"></a>01420 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gc08a28659605f17307d563f45db0824b" title="set joint parameter">dJointSetPRParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01421"></a>01421 
+<a name="l01430"></a>01430 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ge675b0e0e332ddcd907ac9d1461b1961" title="Applies the torque about the rotoide axis of the PR joint.">dJointAddPRTorque</a> (dJointID j, dReal torque);
+<a name="l01431"></a>01431 
+<a name="l01432"></a>01432 
+<a name="l01439"></a>01439 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g8051a8232b4232f7b0d0fd57a3932072" title="Call this on the fixed joint after it has been attached to remember the current desired...">dJointSetFixed</a> (dJointID);
+<a name="l01440"></a>01440 
+<a name="l01441"></a>01441 <span class="comment">/*</span>
+<a name="l01442"></a>01442 <span class="comment"> * @brief Sets joint parameter</span>
+<a name="l01443"></a>01443 <span class="comment"> *</span>
+<a name="l01444"></a>01444 <span class="comment"> * @ingroup joints</span>
+<a name="l01445"></a>01445 <span class="comment"> */</span>
+<a name="l01446"></a>01446 ODE_API <span class="keywordtype">void</span> dJointSetFixedParam (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01447"></a>01447 
+<a name="l01453"></a>01453 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g1406f976045a1b7edffbb46bf626d04f" title="set the nr of axes">dJointSetAMotorNumAxes</a> (dJointID, <span class="keywordtype">int</span> num);
+<a name="l01454"></a>01454 
+<a name="l01459"></a>01459 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gbef7d92227b62e04b60eb9df02359603" title="set axis">dJointSetAMotorAxis</a> (dJointID, <span class="keywordtype">int</span> anum, <span class="keywordtype">int</span> rel,
+<a name="l01460"></a>01460            dReal x, dReal y, dReal z);
+<a name="l01461"></a>01461 
+<a name="l01471"></a>01471 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g17b2089e6512e22d71340befb40100d2" title="Tell the AMotor what the current angle is along axis anum.">dJointSetAMotorAngle</a> (dJointID, <span class="keywordtype">int</span> anum, dReal angle);
+<a name="l01472"></a>01472 
+<a name="l01477"></a>01477 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gac3f00196ee0cdb772e00dc259ef639a" title="set joint parameter">dJointSetAMotorParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01478"></a>01478 
+<a name="l01483"></a>01483 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gb0a3a8527810717c62a2c68dc4dfa822" title="set mode">dJointSetAMotorMode</a> (dJointID, <span class="keywordtype">int</span> mode);
+<a name="l01484"></a>01484 
+<a name="l01493"></a>01493 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g69d13d54516716020d2adb841699b77b" title="Applies torque0 about the AMotor&amp;#39;s axis 0, torque1 about the AMotor&amp;#39;s axis...">dJointAddAMotorTorques</a> (dJointID, dReal torque1, dReal torque2, dReal torque3);
+<a name="l01494"></a>01494 
+<a name="l01500"></a>01500 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gcbfb4014567d69010aba3024d9b7bccd" title="Set the number of axes that will be controlled by the LMotor.">dJointSetLMotorNumAxes</a> (dJointID, <span class="keywordtype">int</span> num);
+<a name="l01501"></a>01501 
+<a name="l01513"></a>01513 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g080b7739f5b2b37a798742cee0ef38a4" title="Set the AMotor axes.">dJointSetLMotorAxis</a> (dJointID, <span class="keywordtype">int</span> anum, <span class="keywordtype">int</span> rel, dReal x, dReal y, dReal z);
+<a name="l01514"></a>01514 
+<a name="l01519"></a>01519 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g791bfa6e65d0c3dce99ca0bcd3beb8d6" title="set joint parameter">dJointSetLMotorParam</a> (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01520"></a>01520 
+<a name="l01524"></a>01524 ODE_API <span class="keywordtype">void</span> dJointSetPlane2DXParam (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01525"></a>01525 
+<a name="l01530"></a>01530 ODE_API <span class="keywordtype">void</span> dJointSetPlane2DYParam (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01531"></a>01531 
+<a name="l01535"></a>01535 ODE_API <span class="keywordtype">void</span> dJointSetPlane2DAngleParam (dJointID, <span class="keywordtype">int</span> parameter, dReal value);
+<a name="l01536"></a>01536 
+<a name="l01543"></a>01543 ODE_API <span class="keywordtype">void</span> dJointGetBallAnchor (dJointID, dVector3 result);
+<a name="l01544"></a>01544 
+<a name="l01555"></a>01555 ODE_API <span class="keywordtype">void</span> dJointGetBallAnchor2 (dJointID, dVector3 result);
+<a name="l01556"></a>01556 
+<a name="l01561"></a>01561 ODE_API dReal <a class="code" href="group__joints.html#g20a27c479a75443552942059542f26ad" title="get joint parameter">dJointGetBallParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01562"></a>01562 
+<a name="l01570"></a>01570 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g1d1c4f9b10c550f6fec550f9cc80c7ab" title="Get the hinge anchor point, in world coordinates.">dJointGetHingeAnchor</a> (dJointID, dVector3 result);
+<a name="l01571"></a>01571 
+<a name="l01580"></a>01580 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gfdc1d9c7bd8824ec3e79cc5aa67ddfa1" title="Get the joint anchor point, in world coordinates.">dJointGetHingeAnchor2</a> (dJointID, dVector3 result);
+<a name="l01581"></a>01581 
+<a name="l01586"></a>01586 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g17b812897bc5faab33584cc5e3e4d3a4" title="get axis">dJointGetHingeAxis</a> (dJointID, dVector3 result);
+<a name="l01587"></a>01587 
+<a name="l01592"></a>01592 ODE_API dReal <a class="code" href="group__joints.html#g43416613e72d1b16a32331a0ba3c7d70" title="get joint parameter">dJointGetHingeParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01593"></a>01593 
+<a name="l01604"></a>01604 ODE_API dReal <a class="code" href="group__joints.html#g7ca6bdfe2b919b6bc2a27ba6f0e069f0" title="Get the hinge angle.">dJointGetHingeAngle</a> (dJointID);
+<a name="l01605"></a>01605 
+<a name="l01610"></a>01610 ODE_API dReal <a class="code" href="group__joints.html#g0d92377b748eb468dc38252df12afc76" title="Get the hinge angle time derivative.">dJointGetHingeAngleRate</a> (dJointID);
+<a name="l01611"></a>01611 
+<a name="l01619"></a>01619 ODE_API dReal <a class="code" href="group__joints.html#g7f35449914cbc4a86b845dcd85a617c0" title="Get the slider linear position (i.e. the slider&amp;#39;s extension).">dJointGetSliderPosition</a> (dJointID);
+<a name="l01620"></a>01620 
+<a name="l01625"></a>01625 ODE_API dReal <a class="code" href="group__joints.html#g93378c9c2d0cd50c79cfb78ca881f8ec" title="Get the slider linear position&amp;#39;s time derivative.">dJointGetSliderPositionRate</a> (dJointID);
+<a name="l01626"></a>01626 
+<a name="l01631"></a>01631 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g17e31e7a877446213c39d1431269788e" title="Get the slider axis.">dJointGetSliderAxis</a> (dJointID, dVector3 result);
+<a name="l01632"></a>01632 
+<a name="l01637"></a>01637 ODE_API dReal <a class="code" href="group__joints.html#gc76d8bb4bf8587af70ef5932025048fe" title="get joint parameter">dJointGetSliderParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01638"></a>01638 
+<a name="l01645"></a>01645 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g879999d011f82c73acf94029132cc198" title="Get the joint anchor point, in world coordinates.">dJointGetHinge2Anchor</a> (dJointID, dVector3 result);
+<a name="l01646"></a>01646 
+<a name="l01655"></a>01655 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ga67cde755a0c9b699859ead5b5c81d26" title="Get the joint anchor point, in world coordinates. This returns the point on body...">dJointGetHinge2Anchor2</a> (dJointID, dVector3 result);
+<a name="l01656"></a>01656 
+<a name="l01661"></a>01661 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g5d3e60c78ed85e8086dd60b13c3054f5" title="Get joint axis.">dJointGetHinge2Axis1</a> (dJointID, dVector3 result);
+<a name="l01662"></a>01662 
+<a name="l01667"></a>01667 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g9459009e9370ea1a1e4de10f60053c87" title="Get joint axis.">dJointGetHinge2Axis2</a> (dJointID, dVector3 result);
+<a name="l01668"></a>01668 
+<a name="l01673"></a>01673 ODE_API dReal <a class="code" href="group__joints.html#g9fe8b60ba59aa9451e5758491e34045a" title="get joint parameter">dJointGetHinge2Param</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01674"></a>01674 
+<a name="l01679"></a>01679 ODE_API dReal <a class="code" href="group__joints.html#g430ed7cafe907e88929b28fdb17533c0" title="Get angle.">dJointGetHinge2Angle1</a> (dJointID);
+<a name="l01680"></a>01680 
+<a name="l01685"></a>01685 ODE_API dReal <a class="code" href="group__joints.html#g61881501e905ec1072aba05464fe44fb" title="Get time derivative of angle.">dJointGetHinge2Angle1Rate</a> (dJointID);
+<a name="l01686"></a>01686 
+<a name="l01691"></a>01691 ODE_API dReal <a class="code" href="group__joints.html#g028c47d8ff409f6856492d9eb0367c8a" title="Get time derivative of angle.">dJointGetHinge2Angle2Rate</a> (dJointID);
+<a name="l01692"></a>01692 
+<a name="l01699"></a>01699 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#ga768432c561cb76ba2490913f42d1aaf" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor</a> (dJointID, dVector3 result);
+<a name="l01700"></a>01700 
+<a name="l01714"></a>01714 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g00d5018903a90d75c324c4f870b0e7ea" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor2</a> (dJointID, dVector3 result);
+<a name="l01715"></a>01715 
+<a name="l01720"></a>01720 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#geaa8e546d93c304755a86ad3fa6d2abe" title="Get axis.">dJointGetUniversalAxis1</a> (dJointID, dVector3 result);
+<a name="l01721"></a>01721 
+<a name="l01726"></a>01726 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g13c01cbc9c5e918740bac0540f6473b3" title="Get axis.">dJointGetUniversalAxis2</a> (dJointID, dVector3 result);
+<a name="l01727"></a>01727 
+<a name="l01728"></a>01728 
+<a name="l01733"></a>01733 ODE_API dReal <a class="code" href="group__joints.html#gf96e70e676058b7eb385f5810fec641a" title="get joint parameter">dJointGetUniversalParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01734"></a>01734 
+<a name="l01746"></a>01746 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g3c0fafbd1ccd8e450c01012ce600f6ab" title="Get both angles at the same time.">dJointGetUniversalAngles</a> (dJointID, dReal *angle1, dReal *angle2);
+<a name="l01747"></a>01747 
+<a name="l01752"></a>01752 ODE_API dReal <a class="code" href="group__joints.html#g3a08e2fed2e88eb0c964a33fb8c0c61f" title="Get angle.">dJointGetUniversalAngle1</a> (dJointID);
+<a name="l01753"></a>01753 
+<a name="l01758"></a>01758 ODE_API dReal <a class="code" href="group__joints.html#g4026a7331d7956eef31e72e20e0c703b" title="Get angle.">dJointGetUniversalAngle2</a> (dJointID);
+<a name="l01759"></a>01759 
+<a name="l01764"></a>01764 ODE_API dReal <a class="code" href="group__joints.html#g1f8ff99b6c33d3da2004a8846112427c" title="Get time derivative of angle.">dJointGetUniversalAngle1Rate</a> (dJointID);
+<a name="l01765"></a>01765 
+<a name="l01770"></a>01770 ODE_API dReal <a class="code" href="group__joints.html#g94fb28ecb65cb0711b555558c22396cf" title="Get time derivative of angle.">dJointGetUniversalAngle2Rate</a> (dJointID);
+<a name="l01771"></a>01771 
+<a name="l01772"></a>01772 
+<a name="l01773"></a>01773 
+<a name="l01780"></a>01780 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g88b176c70948c3f96e5c9173904b04fe" title="Get the joint anchor point, in world coordinates.">dJointGetPRAnchor</a> (dJointID, dVector3 result);
+<a name="l01781"></a>01781 
+<a name="l01793"></a>01793 ODE_API dReal <a class="code" href="group__joints.html#gd8b95871e93525f44badcdaf8e521da7" title="Get the PR linear position (i.e. the prismatic&amp;#39;s extension).">dJointGetPRPosition</a> (dJointID);
+<a name="l01794"></a>01794 
+<a name="l01800"></a>01800 ODE_API dReal <a class="code" href="group__joints.html#gc3a434069c8bf31ae5140e2bff3bbb26" title="Get the PR linear position&amp;#39;s time derivative.">dJointGetPRPositionRate</a> (dJointID);
+<a name="l01801"></a>01801 
+<a name="l01802"></a>01802 
+<a name="l01807"></a>01807 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g826424aac5023739bb13426df672ab32" title="Get the prismatic axis.">dJointGetPRAxis1</a> (dJointID, dVector3 result);
+<a name="l01808"></a>01808 
+<a name="l01813"></a>01813 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g5f175ed66c5df1119a251fad8a51059d" title="Get the Rotoide axis.">dJointGetPRAxis2</a> (dJointID, dVector3 result);
+<a name="l01814"></a>01814 
+<a name="l01819"></a>01819 ODE_API dReal <a class="code" href="group__joints.html#g968b868bd1598b24a3101a04320206c6" title="get joint parameter">dJointGetPRParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01820"></a>01820 
+<a name="l01821"></a>01821 
+<a name="l01822"></a>01822 
+<a name="l01831"></a>01831 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#g35f0392af69ece0d0c3ef7ed88b532bf" title="Get the number of angular axes that will be controlled by the AMotor.">dJointGetAMotorNumAxes</a> (dJointID);
+<a name="l01832"></a>01832 
+<a name="l01842"></a>01842 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#gef1af77cc19d81b24ad00025f3c9d5ec" title="Get the AMotor axes.">dJointGetAMotorAxis</a> (dJointID, <span class="keywordtype">int</span> anum, dVector3 result);
+<a name="l01843"></a>01843 
+<a name="l01860"></a>01860 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#g1887538374f044e22f9742650d14ae69" title="Get axis.">dJointGetAMotorAxisRel</a> (dJointID, <span class="keywordtype">int</span> anum);
+<a name="l01861"></a>01861 
+<a name="l01870"></a>01870 ODE_API dReal <a class="code" href="group__joints.html#g3634444b00ac33a5f34a7af4fffda8b2" title="Get the current angle for axis.">dJointGetAMotorAngle</a> (dJointID, <span class="keywordtype">int</span> anum);
+<a name="l01871"></a>01871 
+<a name="l01880"></a>01880 ODE_API dReal <a class="code" href="group__joints.html#ga65abc36177390330037299b689b70c7" title="Get the current angle rate for axis anum.">dJointGetAMotorAngleRate</a> (dJointID, <span class="keywordtype">int</span> anum);
+<a name="l01881"></a>01881 
+<a name="l01886"></a>01886 ODE_API dReal <a class="code" href="group__joints.html#gfc4cd1046089baa4309d30ae7832d289" title="get joint parameter">dJointGetAMotorParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01887"></a>01887 
+<a name="l01901"></a>01901 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#gf2430c2062414bc28660bdc06a0d72d5" title="Get the angular motor mode.">dJointGetAMotorMode</a> (dJointID);
+<a name="l01902"></a>01902 
+<a name="l01907"></a>01907 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#g6d7557b5e94e0ee37561cadc5bf85cb7" title="Get nr of axes.">dJointGetLMotorNumAxes</a> (dJointID);
+<a name="l01908"></a>01908 
+<a name="l01913"></a>01913 ODE_API <span class="keywordtype">void</span> <a class="code" href="group__joints.html#g4ef7e0ca633583e82d90679c8eb6d5c3" title="Get axis.">dJointGetLMotorAxis</a> (dJointID, <span class="keywordtype">int</span> anum, dVector3 result);
+<a name="l01914"></a>01914 
+<a name="l01919"></a>01919 ODE_API dReal <a class="code" href="group__joints.html#gcbc48fd61857e3843923166abf81a7a0" title="get joint parameter">dJointGetLMotorParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01920"></a>01920 
+<a name="l01925"></a>01925 ODE_API dReal <a class="code" href="group__joints.html#ge433a5eac5f8600d8e6325666c2e12c2" title="get joint parameter">dJointGetFixedParam</a> (dJointID, <span class="keywordtype">int</span> parameter);
+<a name="l01926"></a>01926 
+<a name="l01927"></a>01927 
+<a name="l01931"></a>01931 ODE_API dJointID dConnectingJoint (dBodyID, dBodyID);
+<a name="l01932"></a>01932 
+<a name="l01936"></a>01936 ODE_API <span class="keywordtype">int</span> dConnectingJointList (dBodyID, dBodyID, dJointID*);
+<a name="l01937"></a>01937 
+<a name="l01944"></a>01944 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#g68eb2f4daea03713db4d8b4daca663ae" title="Utility function.">dAreConnected</a> (dBodyID, dBodyID);
+<a name="l01945"></a>01945 
+<a name="l01959"></a>01959 ODE_API <span class="keywordtype">int</span> <a class="code" href="group__joints.html#gc1eafde1fde036633136be6fd254ca5d" title="Utility function.">dAreConnectedExcluding</a> (dBodyID body1, dBodyID body2, <span class="keywordtype">int</span> joint_type);
+<a name="l01960"></a>01960 
+<a name="l01961"></a>01961 
+<a name="l01962"></a>01962 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l01963"></a>01963 <span class="preprocessor"></span>}
+<a name="l01964"></a>01964 <span class="preprocessor">#endif</span>
+<a name="l01965"></a>01965 <span class="preprocessor"></span>
+<a name="l01966"></a>01966 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/ode_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/ode_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/ode_8h-source.html	(revision 216)
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: ode.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>ode.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_ODE_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_ODE_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="comment">/* include *everything* here */</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 <span class="preprocessor">#include &lt;ode/config.h&gt;</span>
+<a name="l00029"></a>00029 <span class="preprocessor">#include &lt;ode/compatibility.h&gt;</span>
+<a name="l00030"></a>00030 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00031"></a>00031 <span class="preprocessor">#include &lt;ode/contact.h&gt;</span>
+<a name="l00032"></a>00032 <span class="preprocessor">#include &lt;ode/error.h&gt;</span>
+<a name="l00033"></a>00033 <span class="preprocessor">#include &lt;ode/memory.h&gt;</span>
+<a name="l00034"></a>00034 <span class="preprocessor">#include &lt;ode/odemath.h&gt;</span>
+<a name="l00035"></a>00035 <span class="preprocessor">#include &lt;ode/matrix.h&gt;</span>
+<a name="l00036"></a>00036 <span class="preprocessor">#include &lt;ode/timer.h&gt;</span>
+<a name="l00037"></a>00037 <span class="preprocessor">#include &lt;ode/rotation.h&gt;</span>
+<a name="l00038"></a>00038 <span class="preprocessor">#include &lt;ode/mass.h&gt;</span>
+<a name="l00039"></a>00039 <span class="preprocessor">#include &lt;ode/misc.h&gt;</span>
+<a name="l00040"></a>00040 <span class="preprocessor">#include &lt;ode/objects.h&gt;</span>
+<a name="l00041"></a>00041 <span class="preprocessor">#include &lt;ode/odecpp.h&gt;</span>
+<a name="l00042"></a>00042 <span class="preprocessor">#include &lt;ode/collision_space.h&gt;</span>
+<a name="l00043"></a>00043 <span class="preprocessor">#include &lt;ode/collision.h&gt;</span>
+<a name="l00044"></a>00044 <span class="preprocessor">#include &lt;ode/odecpp_collision.h&gt;</span>
+<a name="l00045"></a>00045 <span class="preprocessor">#include &lt;ode/export-dif.h&gt;</span>
+<a name="l00046"></a>00046 
+<a name="l00047"></a>00047 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/odecpp_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/odecpp_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/odecpp_8h-source.html	(revision 216)
@@ -0,0 +1,732 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: odecpp.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>odecpp.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                          *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.    *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org    *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                          *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or   *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:             *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *  Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *  your option) any later version. The text of the GNU Lesser  *</span>
+<a name="l00011"></a>00011 <span class="comment"> *  General Public License is included with this library in the    *</span>
+<a name="l00012"></a>00012 <span class="comment"> *  file LICENSE.TXT.                   *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in  *</span>
+<a name="l00014"></a>00014 <span class="comment"> *  the file LICENSE-BSD.TXT.              *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                          *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,    *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of  *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.         *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                          *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/* C++ interface for non-collision stuff */</span>
+<a name="l00024"></a>00024 
+<a name="l00025"></a>00025 
+<a name="l00026"></a>00026 <span class="preprocessor">#ifndef _ODE_ODECPP_H_</span>
+<a name="l00027"></a>00027 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_ODECPP_H_</span>
+<a name="l00028"></a>00028 <span class="preprocessor"></span><span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span>
+<a name="l00030"></a>00030 <span class="preprocessor">#include &lt;ode/error.h&gt;</span>
+<a name="l00031"></a>00031 
+<a name="l00032"></a>00032 
+<a name="l00033"></a>00033 <span class="keyword">class </span>dWorld {
+<a name="l00034"></a>00034   dWorldID _id;
+<a name="l00035"></a>00035 
+<a name="l00036"></a>00036   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00037"></a>00037   dWorld (<span class="keyword">const</span> dWorld &amp;);
+<a name="l00038"></a>00038   <span class="keywordtype">void</span> operator= (<span class="keyword">const</span> dWorld &amp;);
+<a name="l00039"></a>00039 
+<a name="l00040"></a>00040 <span class="keyword">public</span>:
+<a name="l00041"></a>00041   dWorld()
+<a name="l00042"></a>00042     { _id = <a class="code" href="group__world.html#g929067266d630fb745f752042d685fc7" title="Create a new, empty world and return its ID number.">dWorldCreate</a>(); }
+<a name="l00043"></a>00043   ~dWorld()
+<a name="l00044"></a>00044     { <a class="code" href="group__world.html#g5a2e5b1d2d6a1376dca239b488e629f9" title="Destroy a world and everything in it.">dWorldDestroy</a> (_id); }
+<a name="l00045"></a>00045 
+<a name="l00046"></a>00046   dWorldID id()<span class="keyword"> const</span>
+<a name="l00047"></a>00047 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00048"></a>00048   operator dWorldID()<span class="keyword"> const</span>
+<a name="l00049"></a>00049 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00050"></a>00050 
+<a name="l00051"></a>00051   <span class="keywordtype">void</span> setGravity (dReal x, dReal y, dReal z)
+<a name="l00052"></a>00052     { <a class="code" href="group__world.html#ga1b220b922215b335572c699cf8f8cad" title="Set the world&amp;#39;s global gravity vector.">dWorldSetGravity</a> (_id,x,y,z); }
+<a name="l00053"></a>00053   <span class="keywordtype">void</span> getGravity (dVector3 g)<span class="keyword"> const</span>
+<a name="l00054"></a>00054 <span class="keyword">    </span>{ <a class="code" href="group__world.html#ge1a29b6a91cc1910a982c916ae4dee4a" title="Get the gravity vector for a given world.">dWorldGetGravity</a> (_id,g); }
+<a name="l00055"></a>00055 
+<a name="l00056"></a>00056   <span class="keywordtype">void</span> setERP (dReal erp)
+<a name="l00057"></a>00057     { <a class="code" href="group__world.html#gacd0778bdaa939d22f093fc2d5d5f868" title="Set the global ERP value, that controls how much error correction is performed in...">dWorldSetERP</a>(_id, erp); }
+<a name="l00058"></a>00058   dReal getERP()<span class="keyword"> const</span>
+<a name="l00059"></a>00059 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__world.html#g033cd87a0b22889a94d4d84149bda5a0" title="Get the error reduction parameter.">dWorldGetERP</a>(_id); }
+<a name="l00060"></a>00060 
+<a name="l00061"></a>00061   <span class="keywordtype">void</span> setCFM (dReal cfm)
+<a name="l00062"></a>00062     { <a class="code" href="group__world.html#g8b7913fe46d0afc468418c655da79233" title="Set the global CFM (constraint force mixing) value.">dWorldSetCFM</a>(_id, cfm); }
+<a name="l00063"></a>00063   dReal getCFM()<span class="keyword"> const</span>
+<a name="l00064"></a>00064 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__world.html#gc7a431f2b3fc6f887fe91ad676828ba3" title="Get the constraint force mixing value.">dWorldGetCFM</a>(_id); }
+<a name="l00065"></a>00065 
+<a name="l00066"></a>00066   <span class="keywordtype">void</span> step (dReal stepsize)
+<a name="l00067"></a>00067     { <a class="code" href="group__world.html#g8f547ebeb3deed27e0f7b8143d475f50" title="Step the world.">dWorldStep</a> (_id,stepsize); }
+<a name="l00068"></a>00068 
+<a name="l00069"></a>00069   <span class="keywordtype">void</span> stepFast1 (dReal stepsize, <span class="keywordtype">int</span> maxiterations)
+<a name="l00070"></a>00070     { <a class="code" href="group__world.html#gefa68c714bb3c8f70503f101ea062c03" title="Step the world using the StepFast1 algorithm.">dWorldStepFast1</a> (_id,stepsize,maxiterations); }
+<a name="l00071"></a>00071   <span class="keywordtype">void</span> setAutoEnableDepthSF1(dWorldID, <span class="keywordtype">int</span> depth)
+<a name="l00072"></a>00072     { <a class="code" href="group__disable.html#g280c6deffe6b4b8ba39d60bf25355347" title="Set the AutoEnableDepth parameter used by the StepFast1 algorithm.">dWorldSetAutoEnableDepthSF1</a> (_id, depth); }
+<a name="l00073"></a>00073   <span class="keywordtype">int</span> getAutoEnableDepthSF1(dWorldID)
+<a name="l00074"></a>00074     { <span class="keywordflow">return</span> <a class="code" href="group__disable.html#g5438f43d9c71d8090a44171f685de196" title="Get the AutoEnableDepth parameter used by the StepFast1 algorithm.">dWorldGetAutoEnableDepthSF1</a> (_id); }
+<a name="l00075"></a>00075 
+<a name="l00076"></a>00076   <span class="keywordtype">void</span>  setAutoDisableLinearThreshold (dReal threshold) 
+<a name="l00077"></a>00077     { <a class="code" href="group__disable.html#ga1070c6f127352fb0a87ab1d42677b8e" title="Set auto disable linear threshold for newly created bodies.">dWorldSetAutoDisableLinearThreshold</a> (_id,threshold); }
+<a name="l00078"></a>00078   dReal getAutoDisableLinearThreshold()
+<a name="l00079"></a>00079     { <span class="keywordflow">return</span> <a class="code" href="group__disable.html#g48802a9736cc8cc9c1a14cbc3125d9b2" title="Get auto disable linear threshold for newly created bodies.">dWorldGetAutoDisableLinearThreshold</a> (_id); }
+<a name="l00080"></a>00080   <span class="keywordtype">void</span> setAutoDisableAngularThreshold (dReal threshold)
+<a name="l00081"></a>00081     { <a class="code" href="group__disable.html#g61cae2bd156129a918c3a1e69ac1b6dd" title="Set auto disable angular threshold for newly created bodies.">dWorldSetAutoDisableAngularThreshold</a> (_id,threshold); }
+<a name="l00082"></a>00082   dReal getAutoDisableAngularThreshold()
+<a name="l00083"></a>00083     { <span class="keywordflow">return</span> <a class="code" href="group__disable.html#g9d32b31b5d343c324897434a97387abc" title="Get auto disable angular threshold for newly created bodies.">dWorldGetAutoDisableAngularThreshold</a> (_id); }
+<a name="l00084"></a>00084   <span class="keywordtype">void</span> setAutoDisableSteps (<span class="keywordtype">int</span> steps)
+<a name="l00085"></a>00085     { <a class="code" href="group__disable.html#gdb9f69119d1aa259a0e32a8ff94e2535" title="Set auto disable steps for newly created bodies.">dWorldSetAutoDisableSteps</a> (_id,steps); }
+<a name="l00086"></a>00086   <span class="keywordtype">int</span> getAutoDisableSteps()
+<a name="l00087"></a>00087     { <span class="keywordflow">return</span> <a class="code" href="group__disable.html#gb0a26f648b9e40d8d4639bf187d5ac94" title="Get auto disable steps for newly created bodies.">dWorldGetAutoDisableSteps</a> (_id); }
+<a name="l00088"></a>00088   <span class="keywordtype">void</span> setAutoDisableTime (dReal time)
+<a name="l00089"></a>00089     { <a class="code" href="group__disable.html#g06828866a19cab7aeb129ca9ec76863b" title="Set auto disable time for newly created bodies.">dWorldSetAutoDisableTime</a> (_id,time); }
+<a name="l00090"></a>00090   dReal getAutoDisableTime()
+<a name="l00091"></a>00091     { <span class="keywordflow">return</span> <a class="code" href="group__disable.html#gbc004c37efff5f962fa2ac271b3be8e1" title="Get auto disable time for newly created bodies.">dWorldGetAutoDisableTime</a> (_id); }
+<a name="l00092"></a>00092   <span class="keywordtype">void</span> setAutoDisableFlag (<span class="keywordtype">int</span> do_auto_disable)
+<a name="l00093"></a>00093     { <a class="code" href="group__disable.html#g58959b92ae4706e612bca673e85bfc50" title="Set auto disable flag for newly created bodies.">dWorldSetAutoDisableFlag</a> (_id,do_auto_disable); }
+<a name="l00094"></a>00094   <span class="keywordtype">int</span> getAutoDisableFlag()
+<a name="l00095"></a>00095     { <span class="keywordflow">return</span> <a class="code" href="group__disable.html#g7617d19f08c7b1d22cf17ccf22bbdc00" title="Get auto disable flag for newly created bodies.">dWorldGetAutoDisableFlag</a> (_id); }
+<a name="l00096"></a>00096 
+<a name="l00097"></a>00097   <span class="keywordtype">void</span> impulseToForce (dReal stepsize, dReal ix, dReal iy, dReal iz,
+<a name="l00098"></a>00098              dVector3 force)
+<a name="l00099"></a>00099     { <a class="code" href="group__world.html#ga9c564b4dd7d8fa4c6f4b32dd95fc33a" title="Converts an impulse to a force.">dWorldImpulseToForce</a> (_id,stepsize,ix,iy,iz,force); }
+<a name="l00100"></a>00100 };
+<a name="l00101"></a>00101 
+<a name="l00102"></a>00102 
+<a name="l00103"></a>00103 <span class="keyword">class </span>dBody {
+<a name="l00104"></a>00104   dBodyID _id;
+<a name="l00105"></a>00105 
+<a name="l00106"></a>00106   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00107"></a>00107   dBody (<span class="keyword">const</span> dBody &amp;);
+<a name="l00108"></a>00108   <span class="keywordtype">void</span> operator= (<span class="keyword">const</span> dBody &amp;);
+<a name="l00109"></a>00109 
+<a name="l00110"></a>00110 <span class="keyword">public</span>:
+<a name="l00111"></a>00111   dBody()
+<a name="l00112"></a>00112     { _id = 0; }
+<a name="l00113"></a>00113   dBody (dWorldID world)
+<a name="l00114"></a>00114     { _id = <a class="code" href="group__bodies.html#g578137bbaf82d4b8896d2baee3a032a6" title="Create a body in given world.">dBodyCreate</a> (world); }
+<a name="l00115"></a>00115   ~dBody()
+<a name="l00116"></a>00116     { <span class="keywordflow">if</span> (_id) <a class="code" href="group__bodies.html#gc1a0ee96898f14017a29b2afa0eafe13" title="Destroy a body.">dBodyDestroy</a> (_id); }
+<a name="l00117"></a>00117 
+<a name="l00118"></a>00118   <span class="keywordtype">void</span> create (dWorldID world) {
+<a name="l00119"></a>00119     <span class="keywordflow">if</span> (_id) <a class="code" href="group__bodies.html#gc1a0ee96898f14017a29b2afa0eafe13" title="Destroy a body.">dBodyDestroy</a> (_id);
+<a name="l00120"></a>00120     _id = <a class="code" href="group__bodies.html#g578137bbaf82d4b8896d2baee3a032a6" title="Create a body in given world.">dBodyCreate</a> (world);
+<a name="l00121"></a>00121   }
+<a name="l00122"></a>00122 
+<a name="l00123"></a>00123   dBodyID id()<span class="keyword"> const</span>
+<a name="l00124"></a>00124 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00125"></a>00125   operator dBodyID()<span class="keyword"> const</span>
+<a name="l00126"></a>00126 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00127"></a>00127 
+<a name="l00128"></a>00128   <span class="keywordtype">void</span> setData (<span class="keywordtype">void</span> *data)
+<a name="l00129"></a>00129     { <a class="code" href="group__bodies.html#gf9cbe9e1ed1bd4559bb5603b8d0f92f2" title="Set the body&amp;#39;s user-data pointer.">dBodySetData</a> (_id,data); }
+<a name="l00130"></a>00130   <span class="keywordtype">void</span> *getData()<span class="keyword"> const</span>
+<a name="l00131"></a>00131 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g68d3d80c7476776dd4512d577bf70325" title="Get the body&amp;#39;s user-data pointer.">dBodyGetData</a> (_id); }
+<a name="l00132"></a>00132 
+<a name="l00133"></a>00133   <span class="keywordtype">void</span> setPosition (dReal x, dReal y, dReal z)
+<a name="l00134"></a>00134     { <a class="code" href="group__bodies.html#gb84612b793366f18ff5b5cbdbed092da" title="Set position of a body.">dBodySetPosition</a> (_id,x,y,z); }
+<a name="l00135"></a>00135   <span class="keywordtype">void</span> setRotation (<span class="keyword">const</span> dMatrix3 R)
+<a name="l00136"></a>00136     { <a class="code" href="group__bodies.html#gb5f04968ec37ef46d2aaffad6c344468" title="Set the orientation of a body.">dBodySetRotation</a> (_id,R); }
+<a name="l00137"></a>00137   <span class="keywordtype">void</span> setQuaternion (<span class="keyword">const</span> dQuaternion q)
+<a name="l00138"></a>00138     { <a class="code" href="group__bodies.html#ga5f51dd3605c402320e9eae4231d7ad4" title="Set the orientation of a body.">dBodySetQuaternion</a> (_id,q); }
+<a name="l00139"></a>00139   <span class="keywordtype">void</span> setLinearVel  (dReal x, dReal y, dReal z)
+<a name="l00140"></a>00140     { <a class="code" href="group__bodies.html#gafe72e03c1df0f2150e2d7b8677e1460" title="Set the linear velocity of a body.">dBodySetLinearVel</a> (_id,x,y,z); }
+<a name="l00141"></a>00141   <span class="keywordtype">void</span> setAngularVel (dReal x, dReal y, dReal z)
+<a name="l00142"></a>00142     { <a class="code" href="group__bodies.html#g7b4f90c1986333395375c086c4f3ec41" title="Set the angular velocity of a body.">dBodySetAngularVel</a> (_id,x,y,z); }
+<a name="l00143"></a>00143 
+<a name="l00144"></a>00144   <span class="keyword">const</span> dReal * getPosition()<span class="keyword"> const</span>
+<a name="l00145"></a>00145 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g2bddae29591b9f14c5175411b783d570" title="Get the position of a body.">dBodyGetPosition</a> (_id); }
+<a name="l00146"></a>00146   <span class="keyword">const</span> dReal * getRotation()<span class="keyword"> const</span>
+<a name="l00147"></a>00147 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g2374da7ff88a2bac607e2fbce529ad27" title="Get the rotation of a body.">dBodyGetRotation</a> (_id); }
+<a name="l00148"></a>00148   <span class="keyword">const</span> dReal * getQuaternion()<span class="keyword"> const</span>
+<a name="l00149"></a>00149 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g36b7e19622ed47fe6b9dcfbac20237e7" title="Get the rotation of a body.">dBodyGetQuaternion</a> (_id); }
+<a name="l00150"></a>00150   <span class="keyword">const</span> dReal * getLinearVel()<span class="keyword"> const</span>
+<a name="l00151"></a>00151 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g2a0a986c12d53efd5a3753dd4b509cac" title="Get the linear velocity of a body.">dBodyGetLinearVel</a> (_id); }
+<a name="l00152"></a>00152   <span class="keyword">const</span> dReal * getAngularVel()<span class="keyword"> const</span>
+<a name="l00153"></a>00153 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g54dc73be9562cdece52d0a7d8decd1d0" title="Get the angular velocity of a body.">dBodyGetAngularVel</a> (_id); }
+<a name="l00154"></a>00154 
+<a name="l00155"></a>00155   <span class="keywordtype">void</span> setMass (<span class="keyword">const</span> dMass *mass)
+<a name="l00156"></a>00156     { <a class="code" href="group__bodies.html#gf3609b58548e34471ef8ad4727b33e52" title="Set the mass of a body.">dBodySetMass</a> (_id,mass); }
+<a name="l00157"></a>00157   <span class="keywordtype">void</span> getMass (dMass *mass)<span class="keyword"> const</span>
+<a name="l00158"></a>00158 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#g7aa7944f6e36a96d3e578f3369ac4171" title="Get the mass of a body.">dBodyGetMass</a> (_id,mass); }
+<a name="l00159"></a>00159 
+<a name="l00160"></a>00160   <span class="keywordtype">void</span> addForce (dReal fx, dReal fy, dReal fz)
+<a name="l00161"></a>00161     { <a class="code" href="group__bodies.html#g1e1352dc350ad42bff5818f2200ba792" title="Add force at centre of mass of body in absolute coordinates.">dBodyAddForce</a> (_id, fx, fy, fz); }
+<a name="l00162"></a>00162   <span class="keywordtype">void</span> addTorque (dReal fx, dReal fy, dReal fz)
+<a name="l00163"></a>00163     { <a class="code" href="group__bodies.html#g8378560dd168ee8d7a4b74e3de510ebc" title="Add torque at centre of mass of body in absolute coordinates.">dBodyAddTorque</a> (_id, fx, fy, fz); }
+<a name="l00164"></a>00164   <span class="keywordtype">void</span> addRelForce (dReal fx, dReal fy, dReal fz)
+<a name="l00165"></a>00165     { <a class="code" href="group__bodies.html#g0a91e5416c5af7729177c465346837ad" title="Add force at centre of mass of body in coordinates relative to body.">dBodyAddRelForce</a> (_id, fx, fy, fz); }
+<a name="l00166"></a>00166   <span class="keywordtype">void</span> addRelTorque (dReal fx, dReal fy, dReal fz)
+<a name="l00167"></a>00167     { <a class="code" href="group__bodies.html#g172a59e64f6dfa4a59bcd45b694585de" title="Add torque at centre of mass of body in coordinates relative to body.">dBodyAddRelTorque</a> (_id, fx, fy, fz); }
+<a name="l00168"></a>00168   <span class="keywordtype">void</span> addForceAtPos (dReal fx, dReal fy, dReal fz,
+<a name="l00169"></a>00169             dReal px, dReal py, dReal pz)
+<a name="l00170"></a>00170     { <a class="code" href="group__bodies.html#gfa134c6b7b455680b890b677c5789c2b" title="Add force at specified point in body in global coordinates.">dBodyAddForceAtPos</a> (_id, fx, fy, fz, px, py, pz); }
+<a name="l00171"></a>00171   <span class="keywordtype">void</span> addForceAtRelPos (dReal fx, dReal fy, dReal fz,
+<a name="l00172"></a>00172             dReal px, dReal py, dReal pz)
+<a name="l00173"></a>00173     { <a class="code" href="group__bodies.html#g77606cdb23029337a7ed43dee5a59ee1" title="Add force at specified point in body in local coordinates.">dBodyAddForceAtRelPos</a> (_id, fx, fy, fz, px, py, pz); }
+<a name="l00174"></a>00174   <span class="keywordtype">void</span> addRelForceAtPos (dReal fx, dReal fy, dReal fz,
+<a name="l00175"></a>00175           dReal px, dReal py, dReal pz)
+<a name="l00176"></a>00176     { <a class="code" href="group__bodies.html#ga024b08f8dfb85705b86e18b99a0ef8e" title="Add force at specified point in body in global coordinates.">dBodyAddRelForceAtPos</a> (_id, fx, fy, fz, px, py, pz); }
+<a name="l00177"></a>00177   <span class="keywordtype">void</span> addRelForceAtRelPos (dReal fx, dReal fy, dReal fz,
+<a name="l00178"></a>00178              dReal px, dReal py, dReal pz)
+<a name="l00179"></a>00179     { <a class="code" href="group__bodies.html#g7e5d20b6bb36f74d0dedb08f5eefddcb" title="Add force at specified point in body in local coordinates.">dBodyAddRelForceAtRelPos</a> (_id, fx, fy, fz, px, py, pz); }
+<a name="l00180"></a>00180 
+<a name="l00181"></a>00181   <span class="keyword">const</span> dReal * getForce()<span class="keyword"> const</span>
+<a name="l00182"></a>00182 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g3b458397a79f09b1957cb6e5a85e9eba" title="Return the current accumulated force vector.">dBodyGetForce</a>(_id); }
+<a name="l00183"></a>00183   <span class="keyword">const</span> dReal * getTorque()<span class="keyword"> const</span>
+<a name="l00184"></a>00184 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#gfe88a5bc363fc812c8f154e3d5f8ea5d" title="Return the current accumulated torque vector.">dBodyGetTorque</a>(_id); }
+<a name="l00185"></a>00185   <span class="keywordtype">void</span> setForce (dReal x, dReal y, dReal z)
+<a name="l00186"></a>00186     { <a class="code" href="group__bodies.html#gbd56079db36d4562db0e18aebea4f95f" title="Set the body force accumulation vector.">dBodySetForce</a> (_id,x,y,z); }
+<a name="l00187"></a>00187   <span class="keywordtype">void</span> setTorque (dReal x, dReal y, dReal z)
+<a name="l00188"></a>00188     { <a class="code" href="group__bodies.html#gfcd3e44223a878ba52428ad3a124fa94" title="Set the body torque accumulation vector.">dBodySetTorque</a> (_id,x,y,z); }
+<a name="l00189"></a>00189 
+<a name="l00190"></a>00190   <span class="keywordtype">void</span> enable()
+<a name="l00191"></a>00191     { <a class="code" href="group__bodies.html#gd0776c40f667b235f8642e10755543f8" title="Manually enable a body.">dBodyEnable</a> (_id); }
+<a name="l00192"></a>00192   <span class="keywordtype">void</span> disable()
+<a name="l00193"></a>00193     { <a class="code" href="group__bodies.html#ga78092d7cadae36373441aa9be7e6157" title="Manually disable a body.">dBodyDisable</a> (_id); }
+<a name="l00194"></a>00194   <span class="keywordtype">int</span> isEnabled()<span class="keyword"> const</span>
+<a name="l00195"></a>00195 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g7e7803132dfcfceee04a6ab0ca1e0bf8" title="Check wether a body is enabled.">dBodyIsEnabled</a> (_id); }
+<a name="l00196"></a>00196 
+<a name="l00197"></a>00197   <span class="keywordtype">void</span> getRelPointPos (dReal px, dReal py, dReal pz, dVector3 result)<span class="keyword"> const</span>
+<a name="l00198"></a>00198 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#gfcf00cd9c4c754c82189fb9d1eb9f102" title="Get world position of a relative point on body.">dBodyGetRelPointPos</a> (_id, px, py, pz, result); }
+<a name="l00199"></a>00199   <span class="keywordtype">void</span> getRelPointVel (dReal px, dReal py, dReal pz, dVector3 result)<span class="keyword"> const</span>
+<a name="l00200"></a>00200 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#g7fd4f4c7e70c59380da11277b2e97510" title="Get velocity vector in global coords of a relative point on body.">dBodyGetRelPointVel</a> (_id, px, py, pz, result); }
+<a name="l00201"></a>00201   <span class="keywordtype">void</span> getPointVel (dReal px, dReal py, dReal pz, dVector3 result)<span class="keyword"> const</span>
+<a name="l00202"></a>00202 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#g89dd6a4a3c6f3cd98c8377e8d4dec015" title="Get velocity vector in global coords of a globally specified point on a body.">dBodyGetPointVel</a> (_id,px,py,pz,result); }
+<a name="l00203"></a>00203   <span class="keywordtype">void</span> getPosRelPoint (dReal px, dReal py, dReal pz, dVector3 result)<span class="keyword"> const</span>
+<a name="l00204"></a>00204 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#g0334d9d523cbfeec742ac4a814834199" title="takes a point in global coordinates and returns the point&amp;#39;s position in body-relative...">dBodyGetPosRelPoint</a> (_id,px,py,pz,result); }
+<a name="l00205"></a>00205   <span class="keywordtype">void</span> vectorToWorld (dReal px, dReal py, dReal pz, dVector3 result)<span class="keyword"> const</span>
+<a name="l00206"></a>00206 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#g0a2cd6f7499bcfeb8275cbb981465bbf" title="Convert from local to world coordinates.">dBodyVectorToWorld</a> (_id,px,py,pz,result); }
+<a name="l00207"></a>00207   <span class="keywordtype">void</span> vectorFromWorld (dReal px, dReal py, dReal pz, dVector3 result)<span class="keyword"> const</span>
+<a name="l00208"></a>00208 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#g1e3ac3ef038e806d4942ea8b399ab575" title="Convert from world to local coordinates.">dBodyVectorFromWorld</a> (_id,px,py,pz,result); }
+<a name="l00209"></a>00209 
+<a name="l00210"></a>00210   <span class="keywordtype">void</span> setFiniteRotationMode (<span class="keywordtype">int</span> mode)
+<a name="l00211"></a>00211     { <a class="code" href="group__bodies.html#gc474ca36d734fb67b8bd504b672527fa" title="controls the way a body&amp;#39;s orientation is updated at each timestep.">dBodySetFiniteRotationMode</a> (_id, mode); }
+<a name="l00212"></a>00212   <span class="keywordtype">void</span> setFiniteRotationAxis (dReal x, dReal y, dReal z)
+<a name="l00213"></a>00213     { <a class="code" href="group__bodies.html#ga9546c1ea6119fcbf80c71a96f56d052" title="sets the finite rotation axis for a body.">dBodySetFiniteRotationAxis</a> (_id, x, y, z); }
+<a name="l00214"></a>00214 
+<a name="l00215"></a>00215   <span class="keywordtype">int</span> getFiniteRotationMode()<span class="keyword"> const</span>
+<a name="l00216"></a>00216 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g3fb10ac984d64c92e4f138e50b704f9e" title="Get the way a body&amp;#39;s orientation is updated each timestep.">dBodyGetFiniteRotationMode</a> (_id); }
+<a name="l00217"></a>00217   <span class="keywordtype">void</span> getFiniteRotationAxis (dVector3 result)<span class="keyword"> const</span>
+<a name="l00218"></a>00218 <span class="keyword">    </span>{ <a class="code" href="group__bodies.html#gfc8853ff678be731881665ff7abf61ad" title="Get the finite rotation axis.">dBodyGetFiniteRotationAxis</a> (_id, result); }
+<a name="l00219"></a>00219 
+<a name="l00220"></a>00220   <span class="keywordtype">int</span> getNumJoints()<span class="keyword"> const</span>
+<a name="l00221"></a>00221 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g79fd517a57ac9c3594cb71850f649af7" title="Get the number of joints that are attached to this body.">dBodyGetNumJoints</a> (_id); }
+<a name="l00222"></a>00222   dJointID getJoint (<span class="keywordtype">int</span> index)<span class="keyword"> const</span>
+<a name="l00223"></a>00223 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g095e41c5b5632b22aa9bd1a4bd051f8d" title="Return a joint attached to this body, given by index.">dBodyGetJoint</a> (_id, index); }
+<a name="l00224"></a>00224 
+<a name="l00225"></a>00225   <span class="keywordtype">void</span> setGravityMode (<span class="keywordtype">int</span> mode)
+<a name="l00226"></a>00226     { <a class="code" href="group__bodies.html#g5465d605e7fbe82d63a0d4e1000da731" title="Set whether the body is influenced by the world&amp;#39;s gravity or not.">dBodySetGravityMode</a> (_id,mode); }
+<a name="l00227"></a>00227   <span class="keywordtype">int</span> getGravityMode()<span class="keyword"> const</span>
+<a name="l00228"></a>00228 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g0df2f4fed454c567f10fc8bbb8c70455" title="Get whether the body is influenced by the world&amp;#39;s gravity or not.">dBodyGetGravityMode</a> (_id); }
+<a name="l00229"></a>00229 
+<a name="l00230"></a>00230   <span class="keywordtype">int</span> isConnectedTo (dBodyID body)<span class="keyword"> const</span>
+<a name="l00231"></a>00231 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g68eb2f4daea03713db4d8b4daca663ae" title="Utility function.">dAreConnected</a> (_id, body); }
+<a name="l00232"></a>00232 
+<a name="l00233"></a>00233   <span class="keywordtype">void</span>  setAutoDisableLinearThreshold (dReal threshold) 
+<a name="l00234"></a>00234     { <a class="code" href="group__bodies.html#gb8f6e736830cfea86c35e7a0cdfa3112" title="Set auto disable linear average threshold.">dBodySetAutoDisableLinearThreshold</a> (_id,threshold); }
+<a name="l00235"></a>00235   dReal getAutoDisableLinearThreshold()
+<a name="l00236"></a>00236     { <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g57c1e1b1bd50fdcafc5140c1ed89c7d7" title="Get auto disable linear average threshold.">dBodyGetAutoDisableLinearThreshold</a> (_id); }
+<a name="l00237"></a>00237   <span class="keywordtype">void</span> setAutoDisableAngularThreshold (dReal threshold)
+<a name="l00238"></a>00238     { <a class="code" href="group__bodies.html#g206ccf22f027a62aaf5e45a16ddc4040" title="Set auto disable angular average threshold.">dBodySetAutoDisableAngularThreshold</a> (_id,threshold); }
+<a name="l00239"></a>00239   dReal getAutoDisableAngularThreshold()
+<a name="l00240"></a>00240     { <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g5b988719423e9bc3af1be2146872e2d6" title="Get auto disable angular average threshold.">dBodyGetAutoDisableAngularThreshold</a> (_id); }
+<a name="l00241"></a>00241   <span class="keywordtype">void</span> setAutoDisableSteps (<span class="keywordtype">int</span> steps)
+<a name="l00242"></a>00242     { <a class="code" href="group__bodies.html#g03cc329bdc8e19e59c4bfe62cf736578" title="Set auto disable steps.">dBodySetAutoDisableSteps</a> (_id,steps); }
+<a name="l00243"></a>00243   <span class="keywordtype">int</span> getAutoDisableSteps()
+<a name="l00244"></a>00244     { <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#g797ad84c737a2ae4ef3f8a37dfa02183" title="Get auto steps a body must be thought of as idle to disable.">dBodyGetAutoDisableSteps</a> (_id); }
+<a name="l00245"></a>00245   <span class="keywordtype">void</span> setAutoDisableTime (dReal time)
+<a name="l00246"></a>00246     { <a class="code" href="group__bodies.html#g0ae2f08bb38359934151f9420cdef341" title="Set auto disable time.">dBodySetAutoDisableTime</a> (_id,time); }
+<a name="l00247"></a>00247   dReal getAutoDisableTime()
+<a name="l00248"></a>00248     { <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#ga2f4d01a8fb5c4d7e77efd5f0e4dd72b" title="Get auto disable time.">dBodyGetAutoDisableTime</a> (_id); }
+<a name="l00249"></a>00249   <span class="keywordtype">void</span> setAutoDisableFlag (<span class="keywordtype">int</span> do_auto_disable)
+<a name="l00250"></a>00250     { <a class="code" href="group__bodies.html#ge352fdcd8851224f07da53f35691ceb7" title="Set auto disable flag.">dBodySetAutoDisableFlag</a> (_id,do_auto_disable); }
+<a name="l00251"></a>00251   <span class="keywordtype">int</span> getAutoDisableFlag()
+<a name="l00252"></a>00252     { <span class="keywordflow">return</span> <a class="code" href="group__bodies.html#gfe44b3ae620abb1091472089cb07f64e" title="Get auto disable flag.">dBodyGetAutoDisableFlag</a> (_id); }
+<a name="l00253"></a>00253 };
+<a name="l00254"></a>00254 
+<a name="l00255"></a>00255 
+<a name="l00256"></a>00256 <span class="keyword">class </span>dJointGroup {
+<a name="l00257"></a>00257   dJointGroupID _id;
+<a name="l00258"></a>00258 
+<a name="l00259"></a>00259   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00260"></a>00260   dJointGroup (<span class="keyword">const</span> dJointGroup &amp;);
+<a name="l00261"></a>00261   <span class="keywordtype">void</span> operator= (<span class="keyword">const</span> dJointGroup &amp;);
+<a name="l00262"></a>00262 
+<a name="l00263"></a>00263 <span class="keyword">public</span>:
+<a name="l00264"></a>00264   dJointGroup (<span class="keywordtype">int</span> dummy_arg=0)
+<a name="l00265"></a>00265     { _id = <a class="code" href="group__joints.html#gaaec687b184a1214133a41503e7c628f" title="Create a joint group.">dJointGroupCreate</a> (0); }
+<a name="l00266"></a>00266   ~dJointGroup()
+<a name="l00267"></a>00267     { <a class="code" href="group__joints.html#g49e664ee9a8bd7bfe5e6932bf936bb8f" title="Destroy a joint group.">dJointGroupDestroy</a> (_id); }
+<a name="l00268"></a>00268   <span class="keywordtype">void</span> create (<span class="keywordtype">int</span> dummy_arg=0) {
+<a name="l00269"></a>00269     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g49e664ee9a8bd7bfe5e6932bf936bb8f" title="Destroy a joint group.">dJointGroupDestroy</a> (_id);
+<a name="l00270"></a>00270     _id = <a class="code" href="group__joints.html#gaaec687b184a1214133a41503e7c628f" title="Create a joint group.">dJointGroupCreate</a> (0);
+<a name="l00271"></a>00271   }
+<a name="l00272"></a>00272 
+<a name="l00273"></a>00273   dJointGroupID id()<span class="keyword"> const</span>
+<a name="l00274"></a>00274 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00275"></a>00275   operator dJointGroupID()<span class="keyword"> const</span>
+<a name="l00276"></a>00276 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00277"></a>00277 
+<a name="l00278"></a>00278   <span class="keywordtype">void</span> empty()
+<a name="l00279"></a>00279     { <a class="code" href="group__joints.html#g6e055bac8a0a3261bda3b6d07499c4ea" title="Empty a joint group.">dJointGroupEmpty</a> (_id); }
+<a name="l00280"></a>00280 };
+<a name="l00281"></a>00281 
+<a name="l00282"></a>00282 
+<a name="l00283"></a>00283 <span class="keyword">class </span>dJoint {
+<a name="l00284"></a>00284 <span class="keyword">private</span>:
+<a name="l00285"></a>00285   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00286"></a>00286   dJoint (<span class="keyword">const</span> dJoint &amp;) ;
+<a name="l00287"></a>00287   <span class="keywordtype">void</span> operator= (<span class="keyword">const</span> dJoint &amp;);
+<a name="l00288"></a>00288 
+<a name="l00289"></a>00289 <span class="keyword">protected</span>:
+<a name="l00290"></a>00290   dJointID _id;
+<a name="l00291"></a>00291 
+<a name="l00292"></a>00292 <span class="keyword">public</span>:
+<a name="l00293"></a>00293   dJoint()
+<a name="l00294"></a>00294     { _id = 0; }
+<a name="l00295"></a>00295   ~dJoint()
+<a name="l00296"></a>00296     { <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id); }
+<a name="l00297"></a>00297 
+<a name="l00298"></a>00298   dJointID id()<span class="keyword"> const</span>
+<a name="l00299"></a>00299 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00300"></a>00300   operator dJointID()<span class="keyword"> const</span>
+<a name="l00301"></a>00301 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00302"></a>00302 
+<a name="l00303"></a>00303   <span class="keywordtype">void</span> attach (dBodyID body1, dBodyID body2)
+<a name="l00304"></a>00304     { <a class="code" href="group__joints.html#g8f1c9b1302c799a1b87bc29b76d0dcec" title="Attach the joint to some new bodies.">dJointAttach</a> (_id, body1, body2); }
+<a name="l00305"></a>00305 
+<a name="l00306"></a>00306   <span class="keywordtype">void</span> setData (<span class="keywordtype">void</span> *data)
+<a name="l00307"></a>00307     { <a class="code" href="group__joints.html#g5ca72d8bd498ef1ba920b0b473e79d02" title="Set the user-data pointer.">dJointSetData</a> (_id, data); }
+<a name="l00308"></a>00308   <span class="keywordtype">void</span> *getData()<span class="keyword"> const</span>
+<a name="l00309"></a>00309 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g607702a11bae2d2613295f67088b0e82" title="Get the user-data pointer.">dJointGetData</a> (_id); }
+<a name="l00310"></a>00310 
+<a name="l00311"></a>00311   <span class="keywordtype">int</span> getType()<span class="keyword"> const</span>
+<a name="l00312"></a>00312 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g6f12f69d9b1a457428a28c2f77148174" title="Get the type of the joint.">dJointGetType</a> (_id); }
+<a name="l00313"></a>00313 
+<a name="l00314"></a>00314   dBodyID getBody (<span class="keywordtype">int</span> index)<span class="keyword"> const</span>
+<a name="l00315"></a>00315 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gff13cbb464f1bfdc225fc9202c2c54c3" title="Return the bodies that this joint connects.">dJointGetBody</a> (_id, index); }
+<a name="l00316"></a>00316 
+<a name="l00317"></a>00317   <span class="keywordtype">void</span> setFeedback(dJointFeedback *fb)
+<a name="l00318"></a>00318     { <a class="code" href="group__joints.html#g87ddb9beb95e9383a4280cb8a4186f01" title="Sets the datastructure that is to receive the feedback.">dJointSetFeedback</a>(_id, fb); }
+<a name="l00319"></a>00319   dJointFeedback *getFeedback()<span class="keyword"> const</span>
+<a name="l00320"></a>00320 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gda1deef60d7afbb6b9375ddbf97e09a1" title="Gets the datastructure that is to receive the feedback.">dJointGetFeedback</a>(_id); }
+<a name="l00321"></a>00321 };
+<a name="l00322"></a>00322 
+<a name="l00323"></a>00323 
+<a name="l00324"></a>00324 <span class="keyword">class </span>dBallJoint : <span class="keyword">public</span> dJoint {
+<a name="l00325"></a>00325 <span class="keyword">private</span>:
+<a name="l00326"></a>00326   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00327"></a>00327   dBallJoint (<span class="keyword">const</span> dBallJoint &amp;);
+<a name="l00328"></a>00328   <span class="keywordtype">void</span> operator= (<span class="keyword">const</span> dBallJoint &amp;);
+<a name="l00329"></a>00329 
+<a name="l00330"></a>00330 <span class="keyword">public</span>:
+<a name="l00331"></a>00331   dBallJoint() { }
+<a name="l00332"></a>00332   dBallJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00333"></a>00333     { _id = <a class="code" href="group__joints.html#g2d23509f8d6c6066b361af4cf14166f7" title="Create a new joint of the ball type.">dJointCreateBall</a> (world, group); }
+<a name="l00334"></a>00334 
+<a name="l00335"></a>00335   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00336"></a>00336     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00337"></a>00337     _id = <a class="code" href="group__joints.html#g2d23509f8d6c6066b361af4cf14166f7" title="Create a new joint of the ball type.">dJointCreateBall</a> (world, group);
+<a name="l00338"></a>00338   }
+<a name="l00339"></a>00339 
+<a name="l00340"></a>00340   <span class="keywordtype">void</span> setAnchor (dReal x, dReal y, dReal z)
+<a name="l00341"></a>00341     { <a class="code" href="group__joints.html#g058c33a3da1ff935a1125034f779dc4a" title="Set the joint anchor point.">dJointSetBallAnchor</a> (_id, x, y, z); }
+<a name="l00342"></a>00342   <span class="keywordtype">void</span> getAnchor (dVector3 result)<span class="keyword"> const</span>
+<a name="l00343"></a>00343 <span class="keyword">    </span>{ dJointGetBallAnchor (_id, result); }
+<a name="l00344"></a>00344   <span class="keywordtype">void</span> getAnchor2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00345"></a>00345 <span class="keyword">    </span>{ dJointGetBallAnchor2 (_id, result); }
+<a name="l00346"></a>00346   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00347"></a>00347     { <a class="code" href="group__joints.html#ge58f5e11c0829aa8615622a74dd11d85" title="Param setting for Ball joints.">dJointSetBallParam</a> (_id, parameter, value); }
+<a name="l00348"></a>00348   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00349"></a>00349 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g20a27c479a75443552942059542f26ad" title="get joint parameter">dJointGetBallParam</a> (_id, parameter); }
+<a name="l00350"></a>00350 } ;
+<a name="l00351"></a>00351 
+<a name="l00352"></a>00352 
+<a name="l00353"></a>00353 <span class="keyword">class </span>dHingeJoint : <span class="keyword">public</span> dJoint {
+<a name="l00354"></a>00354   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00355"></a>00355   dHingeJoint (<span class="keyword">const</span> dHingeJoint &amp;);
+<a name="l00356"></a>00356   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dHingeJoint &amp;);
+<a name="l00357"></a>00357 
+<a name="l00358"></a>00358 <span class="keyword">public</span>:
+<a name="l00359"></a>00359   dHingeJoint() { }
+<a name="l00360"></a>00360   dHingeJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00361"></a>00361     { _id = <a class="code" href="group__joints.html#g2f18d431d48c905abc9d72ce011c00bd" title="Create a new joint of the hinge type.">dJointCreateHinge</a> (world, group); }
+<a name="l00362"></a>00362 
+<a name="l00363"></a>00363   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00364"></a>00364     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00365"></a>00365     _id = <a class="code" href="group__joints.html#g2f18d431d48c905abc9d72ce011c00bd" title="Create a new joint of the hinge type.">dJointCreateHinge</a> (world, group);
+<a name="l00366"></a>00366   }
+<a name="l00367"></a>00367 
+<a name="l00368"></a>00368   <span class="keywordtype">void</span> setAnchor (dReal x, dReal y, dReal z)
+<a name="l00369"></a>00369     { <a class="code" href="group__joints.html#gc5727a125de0abbe2abd61af7a55da26" title="Set hinge anchor parameter.">dJointSetHingeAnchor</a> (_id, x, y, z); }
+<a name="l00370"></a>00370   <span class="keywordtype">void</span> getAnchor (dVector3 result)<span class="keyword"> const</span>
+<a name="l00371"></a>00371 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g1d1c4f9b10c550f6fec550f9cc80c7ab" title="Get the hinge anchor point, in world coordinates.">dJointGetHingeAnchor</a> (_id, result); }
+<a name="l00372"></a>00372   <span class="keywordtype">void</span> getAnchor2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00373"></a>00373 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#gfdc1d9c7bd8824ec3e79cc5aa67ddfa1" title="Get the joint anchor point, in world coordinates.">dJointGetHingeAnchor2</a> (_id, result); }
+<a name="l00374"></a>00374 
+<a name="l00375"></a>00375   <span class="keywordtype">void</span> setAxis (dReal x, dReal y, dReal z)
+<a name="l00376"></a>00376     { <a class="code" href="group__joints.html#ga434229f033472ec7aa031a01c6cabed" title="Set hinge axis.">dJointSetHingeAxis</a> (_id, x, y, z); }
+<a name="l00377"></a>00377   <span class="keywordtype">void</span> getAxis (dVector3 result)<span class="keyword"> const</span>
+<a name="l00378"></a>00378 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g17b812897bc5faab33584cc5e3e4d3a4" title="get axis">dJointGetHingeAxis</a> (_id, result); }
+<a name="l00379"></a>00379 
+<a name="l00380"></a>00380   dReal getAngle()<span class="keyword"> const</span>
+<a name="l00381"></a>00381 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g7ca6bdfe2b919b6bc2a27ba6f0e069f0" title="Get the hinge angle.">dJointGetHingeAngle</a> (_id); }
+<a name="l00382"></a>00382   dReal getAngleRate()<span class="keyword"> const</span>
+<a name="l00383"></a>00383 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g0d92377b748eb468dc38252df12afc76" title="Get the hinge angle time derivative.">dJointGetHingeAngleRate</a> (_id); }
+<a name="l00384"></a>00384 
+<a name="l00385"></a>00385   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00386"></a>00386     { <a class="code" href="group__joints.html#g6f9d34a01181e65639eb1f67da7a3e4c" title="set joint parameter">dJointSetHingeParam</a> (_id, parameter, value); }
+<a name="l00387"></a>00387   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00388"></a>00388 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g43416613e72d1b16a32331a0ba3c7d70" title="get joint parameter">dJointGetHingeParam</a> (_id, parameter); }
+<a name="l00389"></a>00389 
+<a name="l00390"></a>00390   <span class="keywordtype">void</span> addTorque (dReal torque)
+<a name="l00391"></a>00391    { <a class="code" href="group__joints.html#ga1725abe170f80b0731321ed38785019" title="Applies the torque about the hinge axis.">dJointAddHingeTorque</a>(_id, torque); }
+<a name="l00392"></a>00392 };
+<a name="l00393"></a>00393 
+<a name="l00394"></a>00394 
+<a name="l00395"></a>00395 <span class="keyword">class </span>dSliderJoint : <span class="keyword">public</span> dJoint {
+<a name="l00396"></a>00396   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00397"></a>00397   dSliderJoint (<span class="keyword">const</span> dSliderJoint &amp;);
+<a name="l00398"></a>00398   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dSliderJoint &amp;);
+<a name="l00399"></a>00399 
+<a name="l00400"></a>00400 <span class="keyword">public</span>:
+<a name="l00401"></a>00401   dSliderJoint() { }
+<a name="l00402"></a>00402   dSliderJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00403"></a>00403     { _id = <a class="code" href="group__joints.html#geccc4c67b2d409016685a6a9163be539" title="Create a new joint of the slider type.">dJointCreateSlider</a> (world, group); }
+<a name="l00404"></a>00404 
+<a name="l00405"></a>00405   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00406"></a>00406     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00407"></a>00407     _id = <a class="code" href="group__joints.html#geccc4c67b2d409016685a6a9163be539" title="Create a new joint of the slider type.">dJointCreateSlider</a> (world, group);
+<a name="l00408"></a>00408   }
+<a name="l00409"></a>00409 
+<a name="l00410"></a>00410   <span class="keywordtype">void</span> setAxis (dReal x, dReal y, dReal z)
+<a name="l00411"></a>00411     { <a class="code" href="group__joints.html#gb2f662b1190507551f49ffa29d276b61" title="set the joint axis">dJointSetSliderAxis</a> (_id, x, y, z); }
+<a name="l00412"></a>00412   <span class="keywordtype">void</span> getAxis (dVector3 result)<span class="keyword"> const</span>
+<a name="l00413"></a>00413 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g17e31e7a877446213c39d1431269788e" title="Get the slider axis.">dJointGetSliderAxis</a> (_id, result); }
+<a name="l00414"></a>00414 
+<a name="l00415"></a>00415   dReal getPosition()<span class="keyword"> const</span>
+<a name="l00416"></a>00416 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g7f35449914cbc4a86b845dcd85a617c0" title="Get the slider linear position (i.e. the slider&amp;#39;s extension).">dJointGetSliderPosition</a> (_id); }
+<a name="l00417"></a>00417   dReal getPositionRate()<span class="keyword"> const</span>
+<a name="l00418"></a>00418 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g93378c9c2d0cd50c79cfb78ca881f8ec" title="Get the slider linear position&amp;#39;s time derivative.">dJointGetSliderPositionRate</a> (_id); }
+<a name="l00419"></a>00419 
+<a name="l00420"></a>00420   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00421"></a>00421     { <a class="code" href="group__joints.html#g648964f4ca4122309e71a9cc6c24c985" title="set joint parameter">dJointSetSliderParam</a> (_id, parameter, value); }
+<a name="l00422"></a>00422   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00423"></a>00423 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gc76d8bb4bf8587af70ef5932025048fe" title="get joint parameter">dJointGetSliderParam</a> (_id, parameter); }
+<a name="l00424"></a>00424 
+<a name="l00425"></a>00425   <span class="keywordtype">void</span> addForce (dReal force)
+<a name="l00426"></a>00426    { <a class="code" href="group__joints.html#g8b0e018cc3df6ea5ddb42320913455e7" title="Applies the given force in the slider&amp;#39;s direction.">dJointAddSliderForce</a>(_id, force); }
+<a name="l00427"></a>00427 };
+<a name="l00428"></a>00428 
+<a name="l00429"></a>00429 
+<a name="l00430"></a>00430 <span class="keyword">class </span>dUniversalJoint : <span class="keyword">public</span> dJoint {
+<a name="l00431"></a>00431   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00432"></a>00432   dUniversalJoint (<span class="keyword">const</span> dUniversalJoint &amp;);
+<a name="l00433"></a>00433   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dUniversalJoint &amp;);
+<a name="l00434"></a>00434 
+<a name="l00435"></a>00435 <span class="keyword">public</span>:
+<a name="l00436"></a>00436   dUniversalJoint() { }
+<a name="l00437"></a>00437   dUniversalJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00438"></a>00438     { _id = <a class="code" href="group__joints.html#g1cb2e7668242313b5d24acb5d43e5c62" title="Create a new joint of the universal type.">dJointCreateUniversal</a> (world, group); }
+<a name="l00439"></a>00439 
+<a name="l00440"></a>00440   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00441"></a>00441     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00442"></a>00442     _id = <a class="code" href="group__joints.html#g1cb2e7668242313b5d24acb5d43e5c62" title="Create a new joint of the universal type.">dJointCreateUniversal</a> (world, group);
+<a name="l00443"></a>00443   }
+<a name="l00444"></a>00444 
+<a name="l00445"></a>00445   <span class="keywordtype">void</span> setAnchor (dReal x, dReal y, dReal z)
+<a name="l00446"></a>00446     { <a class="code" href="group__joints.html#gaf4657aed67f3cd7cce775215995c05d" title="set anchor">dJointSetUniversalAnchor</a> (_id, x, y, z); }
+<a name="l00447"></a>00447   <span class="keywordtype">void</span> setAxis1 (dReal x, dReal y, dReal z)
+<a name="l00448"></a>00448     { <a class="code" href="group__joints.html#ge0a831da9447ff65d76a0808502038e8" title="set axis">dJointSetUniversalAxis1</a> (_id, x, y, z); }
+<a name="l00449"></a>00449   <span class="keywordtype">void</span> setAxis2 (dReal x, dReal y, dReal z)
+<a name="l00450"></a>00450     { <a class="code" href="group__joints.html#gf3668eed7dc5aaf8fee19d7f87347343" title="set axis">dJointSetUniversalAxis2</a> (_id, x, y, z); }
+<a name="l00451"></a>00451   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00452"></a>00452     { <a class="code" href="group__joints.html#g3c58284c43e997a028b06dc250064e32" title="set joint parameter">dJointSetUniversalParam</a> (_id, parameter, value); }
+<a name="l00453"></a>00453 
+<a name="l00454"></a>00454   <span class="keywordtype">void</span> getAnchor (dVector3 result)<span class="keyword"> const</span>
+<a name="l00455"></a>00455 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#ga768432c561cb76ba2490913f42d1aaf" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor</a> (_id, result); }
+<a name="l00456"></a>00456   <span class="keywordtype">void</span> getAnchor2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00457"></a>00457 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g00d5018903a90d75c324c4f870b0e7ea" title="Get the joint anchor point, in world coordinates.">dJointGetUniversalAnchor2</a> (_id, result); }
+<a name="l00458"></a>00458   <span class="keywordtype">void</span> getAxis1 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00459"></a>00459 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#geaa8e546d93c304755a86ad3fa6d2abe" title="Get axis.">dJointGetUniversalAxis1</a> (_id, result); }
+<a name="l00460"></a>00460   <span class="keywordtype">void</span> getAxis2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00461"></a>00461 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g13c01cbc9c5e918740bac0540f6473b3" title="Get axis.">dJointGetUniversalAxis2</a> (_id, result); }
+<a name="l00462"></a>00462   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00463"></a>00463 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gf96e70e676058b7eb385f5810fec641a" title="get joint parameter">dJointGetUniversalParam</a> (_id, parameter); }
+<a name="l00464"></a>00464  <span class="keywordtype">void</span> getAngles(dReal *angle1, dReal *angle2)<span class="keyword"> const</span>
+<a name="l00465"></a>00465 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g3c0fafbd1ccd8e450c01012ce600f6ab" title="Get both angles at the same time.">dJointGetUniversalAngles</a> (_id, angle1, angle2); }
+<a name="l00466"></a>00466 
+<a name="l00467"></a>00467   dReal getAngle1()<span class="keyword"> const</span>
+<a name="l00468"></a>00468 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g3a08e2fed2e88eb0c964a33fb8c0c61f" title="Get angle.">dJointGetUniversalAngle1</a> (_id); }
+<a name="l00469"></a>00469   dReal getAngle1Rate()<span class="keyword"> const</span>
+<a name="l00470"></a>00470 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g1f8ff99b6c33d3da2004a8846112427c" title="Get time derivative of angle.">dJointGetUniversalAngle1Rate</a> (_id); }
+<a name="l00471"></a>00471   dReal getAngle2()<span class="keyword"> const</span>
+<a name="l00472"></a>00472 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g4026a7331d7956eef31e72e20e0c703b" title="Get angle.">dJointGetUniversalAngle2</a> (_id); }
+<a name="l00473"></a>00473   dReal getAngle2Rate()<span class="keyword"> const</span>
+<a name="l00474"></a>00474 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g94fb28ecb65cb0711b555558c22396cf" title="Get time derivative of angle.">dJointGetUniversalAngle2Rate</a> (_id); }
+<a name="l00475"></a>00475 
+<a name="l00476"></a>00476   <span class="keywordtype">void</span> addTorques (dReal torque1, dReal torque2)
+<a name="l00477"></a>00477    { <a class="code" href="group__joints.html#g36607569e2ee26f39d3d42cba2397898" title="Applies torque1 about the universal&amp;#39;s axis 1, torque2 about the universal&amp;#39;s...">dJointAddUniversalTorques</a>(_id, torque1, torque2); }
+<a name="l00478"></a>00478 };
+<a name="l00479"></a>00479 
+<a name="l00480"></a>00480 
+<a name="l00481"></a>00481 <span class="keyword">class </span>dHinge2Joint : <span class="keyword">public</span> dJoint {
+<a name="l00482"></a>00482   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00483"></a>00483   dHinge2Joint (<span class="keyword">const</span> dHinge2Joint &amp;);
+<a name="l00484"></a>00484   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dHinge2Joint &amp;);
+<a name="l00485"></a>00485 
+<a name="l00486"></a>00486 <span class="keyword">public</span>:
+<a name="l00487"></a>00487   dHinge2Joint() { }
+<a name="l00488"></a>00488   dHinge2Joint (dWorldID world, dJointGroupID group=0)
+<a name="l00489"></a>00489     { _id = <a class="code" href="group__joints.html#g6a6e32d35bdda9352d1be8d4df973f8f" title="Create a new joint of the hinge2 type.">dJointCreateHinge2</a> (world, group); }
+<a name="l00490"></a>00490 
+<a name="l00491"></a>00491   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00492"></a>00492     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00493"></a>00493     _id = <a class="code" href="group__joints.html#g6a6e32d35bdda9352d1be8d4df973f8f" title="Create a new joint of the hinge2 type.">dJointCreateHinge2</a> (world, group);
+<a name="l00494"></a>00494   }
+<a name="l00495"></a>00495 
+<a name="l00496"></a>00496   <span class="keywordtype">void</span> setAnchor (dReal x, dReal y, dReal z)
+<a name="l00497"></a>00497     { <a class="code" href="group__joints.html#gf839c13fa85aff0287a87986ff447d29" title="set anchor">dJointSetHinge2Anchor</a> (_id, x, y, z); }
+<a name="l00498"></a>00498   <span class="keywordtype">void</span> setAxis1 (dReal x, dReal y, dReal z)
+<a name="l00499"></a>00499     { <a class="code" href="group__joints.html#gcdf78fbb0f5b0a09b4d3ac2059b07002" title="set axis">dJointSetHinge2Axis1</a> (_id, x, y, z); }
+<a name="l00500"></a>00500   <span class="keywordtype">void</span> setAxis2 (dReal x, dReal y, dReal z)
+<a name="l00501"></a>00501     { <a class="code" href="group__joints.html#gdfef9f6365c87dacb95b4850a9e9f0ee" title="set axis">dJointSetHinge2Axis2</a> (_id, x, y, z); }
+<a name="l00502"></a>00502 
+<a name="l00503"></a>00503   <span class="keywordtype">void</span> getAnchor (dVector3 result)<span class="keyword"> const</span>
+<a name="l00504"></a>00504 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g879999d011f82c73acf94029132cc198" title="Get the joint anchor point, in world coordinates.">dJointGetHinge2Anchor</a> (_id, result); }
+<a name="l00505"></a>00505   <span class="keywordtype">void</span> getAnchor2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00506"></a>00506 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#ga67cde755a0c9b699859ead5b5c81d26" title="Get the joint anchor point, in world coordinates. This returns the point on body...">dJointGetHinge2Anchor2</a> (_id, result); }
+<a name="l00507"></a>00507   <span class="keywordtype">void</span> getAxis1 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00508"></a>00508 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g5d3e60c78ed85e8086dd60b13c3054f5" title="Get joint axis.">dJointGetHinge2Axis1</a> (_id, result); }
+<a name="l00509"></a>00509   <span class="keywordtype">void</span> getAxis2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00510"></a>00510 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g9459009e9370ea1a1e4de10f60053c87" title="Get joint axis.">dJointGetHinge2Axis2</a> (_id, result); }
+<a name="l00511"></a>00511 
+<a name="l00512"></a>00512   dReal getAngle1()<span class="keyword"> const</span>
+<a name="l00513"></a>00513 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g430ed7cafe907e88929b28fdb17533c0" title="Get angle.">dJointGetHinge2Angle1</a> (_id); }
+<a name="l00514"></a>00514   dReal getAngle1Rate()<span class="keyword"> const</span>
+<a name="l00515"></a>00515 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g61881501e905ec1072aba05464fe44fb" title="Get time derivative of angle.">dJointGetHinge2Angle1Rate</a> (_id); }
+<a name="l00516"></a>00516   dReal getAngle2Rate()<span class="keyword"> const</span>
+<a name="l00517"></a>00517 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g028c47d8ff409f6856492d9eb0367c8a" title="Get time derivative of angle.">dJointGetHinge2Angle2Rate</a> (_id); }
+<a name="l00518"></a>00518 
+<a name="l00519"></a>00519   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00520"></a>00520     { <a class="code" href="group__joints.html#g9a2d8d03776ccb22869667337457a7a9" title="set joint parameter">dJointSetHinge2Param</a> (_id, parameter, value); }
+<a name="l00521"></a>00521   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00522"></a>00522 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g9fe8b60ba59aa9451e5758491e34045a" title="get joint parameter">dJointGetHinge2Param</a> (_id, parameter); }
+<a name="l00523"></a>00523 
+<a name="l00524"></a>00524   <span class="keywordtype">void</span> addTorques(dReal torque1, dReal torque2)
+<a name="l00525"></a>00525    { <a class="code" href="group__joints.html#ga5ba1541d092f28c93b1bdc3bfb1b69f" title="Applies torque1 about the hinge2&amp;#39;s axis 1, torque2 about the hinge2&amp;#39;s axis...">dJointAddHinge2Torques</a>(_id, torque1, torque2); }
+<a name="l00526"></a>00526 };
+<a name="l00527"></a>00527 
+<a name="l00528"></a>00528 
+<a name="l00529"></a>00529 <span class="keyword">class </span>dPRJoint : <span class="keyword">public</span> dJoint {
+<a name="l00530"></a>00530   dPRJoint (<span class="keyword">const</span> dPRJoint &amp;);
+<a name="l00531"></a>00531   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dPRJoint &amp;);
+<a name="l00532"></a>00532 
+<a name="l00533"></a>00533 <span class="keyword">public</span>:
+<a name="l00534"></a>00534   dPRJoint() { }
+<a name="l00535"></a>00535   dPRJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00536"></a>00536     { _id = <a class="code" href="group__joints.html#gdc867f10ba9931d191244fa879e43cb2" title="Create a new joint of the PR (Prismatic and Rotoide) type.">dJointCreatePR</a> (world, group); }
+<a name="l00537"></a>00537 
+<a name="l00538"></a>00538   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00539"></a>00539     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00540"></a>00540     _id = <a class="code" href="group__joints.html#gdc867f10ba9931d191244fa879e43cb2" title="Create a new joint of the PR (Prismatic and Rotoide) type.">dJointCreatePR</a> (world, group);
+<a name="l00541"></a>00541   }
+<a name="l00542"></a>00542 
+<a name="l00543"></a>00543   <span class="keywordtype">void</span> setAnchor (dReal x, dReal y, dReal z)
+<a name="l00544"></a>00544     { <a class="code" href="group__joints.html#ge46251e2cea2d31521b1fb9b151f640f" title="set anchor">dJointSetPRAnchor</a> (_id, x, y, z); }
+<a name="l00545"></a>00545   <span class="keywordtype">void</span> setAxis1 (dReal x, dReal y, dReal z)
+<a name="l00546"></a>00546     { <a class="code" href="group__joints.html#ga2ae3ab1fa58ec22bd443476f786fa81" title="set the axis for the prismatic articulation">dJointSetPRAxis1</a> (_id, x, y, z); }
+<a name="l00547"></a>00547   <span class="keywordtype">void</span> setAxis2 (dReal x, dReal y, dReal z)
+<a name="l00548"></a>00548     { <a class="code" href="group__joints.html#gc8c61c6dd7b28a58a4c0eaf2e91ecbd5" title="set the axis for the rotoide articulation">dJointSetPRAxis2</a> (_id, x, y, z); }
+<a name="l00549"></a>00549 
+<a name="l00550"></a>00550   <span class="keywordtype">void</span> getAnchor (dVector3 result)<span class="keyword"> const</span>
+<a name="l00551"></a>00551 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g88b176c70948c3f96e5c9173904b04fe" title="Get the joint anchor point, in world coordinates.">dJointGetPRAnchor</a> (_id, result); }
+<a name="l00552"></a>00552   <span class="keywordtype">void</span> getAxis1 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00553"></a>00553 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g826424aac5023739bb13426df672ab32" title="Get the prismatic axis.">dJointGetPRAxis1</a> (_id, result); }
+<a name="l00554"></a>00554   <span class="keywordtype">void</span> getAxis2 (dVector3 result)<span class="keyword"> const</span>
+<a name="l00555"></a>00555 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g5f175ed66c5df1119a251fad8a51059d" title="Get the Rotoide axis.">dJointGetPRAxis2</a> (_id, result); }
+<a name="l00556"></a>00556 
+<a name="l00557"></a>00557   dReal getPosition()<span class="keyword"> const</span>
+<a name="l00558"></a>00558 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gd8b95871e93525f44badcdaf8e521da7" title="Get the PR linear position (i.e. the prismatic&amp;#39;s extension).">dJointGetPRPosition</a> (_id); }
+<a name="l00559"></a>00559   dReal getPositionRate()<span class="keyword"> const</span>
+<a name="l00560"></a>00560 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gc3a434069c8bf31ae5140e2bff3bbb26" title="Get the PR linear position&amp;#39;s time derivative.">dJointGetPRPositionRate</a> (_id); }
+<a name="l00561"></a>00561 
+<a name="l00562"></a>00562   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00563"></a>00563     { <a class="code" href="group__joints.html#gc08a28659605f17307d563f45db0824b" title="set joint parameter">dJointSetPRParam</a> (_id, parameter, value); }
+<a name="l00564"></a>00564   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00565"></a>00565 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g968b868bd1598b24a3101a04320206c6" title="get joint parameter">dJointGetPRParam</a> (_id, parameter); }
+<a name="l00566"></a>00566 };
+<a name="l00567"></a>00567 
+<a name="l00568"></a>00568 
+<a name="l00569"></a>00569 <span class="keyword">class </span>dFixedJoint : <span class="keyword">public</span> dJoint {
+<a name="l00570"></a>00570   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00571"></a>00571   dFixedJoint (<span class="keyword">const</span> dFixedJoint &amp;);
+<a name="l00572"></a>00572   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dFixedJoint &amp;);
+<a name="l00573"></a>00573 
+<a name="l00574"></a>00574 <span class="keyword">public</span>:
+<a name="l00575"></a>00575   dFixedJoint() { }
+<a name="l00576"></a>00576   dFixedJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00577"></a>00577     { _id = <a class="code" href="group__joints.html#ge568995d03077e1acb13882a627dcf32" title="Create a new joint of the fixed type.">dJointCreateFixed</a> (world, group); }
+<a name="l00578"></a>00578 
+<a name="l00579"></a>00579   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00580"></a>00580     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00581"></a>00581     _id = <a class="code" href="group__joints.html#ge568995d03077e1acb13882a627dcf32" title="Create a new joint of the fixed type.">dJointCreateFixed</a> (world, group);
+<a name="l00582"></a>00582   }
+<a name="l00583"></a>00583 
+<a name="l00584"></a>00584   <span class="keywordtype">void</span> <span class="keyword">set</span>()
+<a name="l00585"></a>00585     { <a class="code" href="group__joints.html#g8051a8232b4232f7b0d0fd57a3932072" title="Call this on the fixed joint after it has been attached to remember the current desired...">dJointSetFixed</a> (_id); }
+<a name="l00586"></a>00586 
+<a name="l00587"></a>00587   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00588"></a>00588     { dJointSetFixedParam (_id, parameter, value); }
+<a name="l00589"></a>00589 
+<a name="l00590"></a>00590   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00591"></a>00591 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#ge433a5eac5f8600d8e6325666c2e12c2" title="get joint parameter">dJointGetFixedParam</a> (_id, parameter); }
+<a name="l00592"></a>00592 };
+<a name="l00593"></a>00593 
+<a name="l00594"></a>00594 
+<a name="l00595"></a>00595 <span class="keyword">class </span>dContactJoint : <span class="keyword">public</span> dJoint {
+<a name="l00596"></a>00596   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00597"></a>00597   dContactJoint (<span class="keyword">const</span> dContactJoint &amp;);
+<a name="l00598"></a>00598   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dContactJoint &amp;);
+<a name="l00599"></a>00599 
+<a name="l00600"></a>00600 <span class="keyword">public</span>:
+<a name="l00601"></a>00601   dContactJoint() { }
+<a name="l00602"></a>00602   dContactJoint (dWorldID world, dJointGroupID group, dContact *contact)
+<a name="l00603"></a>00603     { _id = <a class="code" href="group__joints.html#gfa5e1543239ba44ecbdc178ebc7c3cc4" title="Create a new joint of the contact type.">dJointCreateContact</a> (world, group, contact); }
+<a name="l00604"></a>00604 
+<a name="l00605"></a>00605   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group, dContact *contact) {
+<a name="l00606"></a>00606     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00607"></a>00607     _id = <a class="code" href="group__joints.html#gfa5e1543239ba44ecbdc178ebc7c3cc4" title="Create a new joint of the contact type.">dJointCreateContact</a> (world, group, contact);
+<a name="l00608"></a>00608   }
+<a name="l00609"></a>00609 };
+<a name="l00610"></a>00610 
+<a name="l00611"></a>00611 
+<a name="l00612"></a>00612 <span class="keyword">class </span>dNullJoint : <span class="keyword">public</span> dJoint {
+<a name="l00613"></a>00613   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00614"></a>00614   dNullJoint (<span class="keyword">const</span> dNullJoint &amp;);
+<a name="l00615"></a>00615   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dNullJoint &amp;);
+<a name="l00616"></a>00616 
+<a name="l00617"></a>00617 <span class="keyword">public</span>:
+<a name="l00618"></a>00618   dNullJoint() { }
+<a name="l00619"></a>00619   dNullJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00620"></a>00620     { _id = dJointCreateNull (world, group); }
+<a name="l00621"></a>00621 
+<a name="l00622"></a>00622   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00623"></a>00623     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00624"></a>00624     _id = dJointCreateNull (world, group);
+<a name="l00625"></a>00625   }
+<a name="l00626"></a>00626 };
+<a name="l00627"></a>00627 
+<a name="l00628"></a>00628 
+<a name="l00629"></a>00629 <span class="keyword">class </span>dAMotorJoint : <span class="keyword">public</span> dJoint {
+<a name="l00630"></a>00630   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00631"></a>00631   dAMotorJoint (<span class="keyword">const</span> dAMotorJoint &amp;);
+<a name="l00632"></a>00632   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dAMotorJoint &amp;);
+<a name="l00633"></a>00633 
+<a name="l00634"></a>00634 <span class="keyword">public</span>:
+<a name="l00635"></a>00635   dAMotorJoint() { }
+<a name="l00636"></a>00636   dAMotorJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00637"></a>00637     { _id = <a class="code" href="group__joints.html#gf23195ce77e12031393e591abd0e28e6" title="Create a new joint of the A-motor type.">dJointCreateAMotor</a> (world, group); }
+<a name="l00638"></a>00638 
+<a name="l00639"></a>00639   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00640"></a>00640     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00641"></a>00641     _id = <a class="code" href="group__joints.html#gf23195ce77e12031393e591abd0e28e6" title="Create a new joint of the A-motor type.">dJointCreateAMotor</a> (world, group);
+<a name="l00642"></a>00642   }
+<a name="l00643"></a>00643 
+<a name="l00644"></a>00644   <span class="keywordtype">void</span> setMode (<span class="keywordtype">int</span> mode)
+<a name="l00645"></a>00645     { <a class="code" href="group__joints.html#gb0a3a8527810717c62a2c68dc4dfa822" title="set mode">dJointSetAMotorMode</a> (_id, mode); }
+<a name="l00646"></a>00646   <span class="keywordtype">int</span> getMode()<span class="keyword"> const</span>
+<a name="l00647"></a>00647 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gf2430c2062414bc28660bdc06a0d72d5" title="Get the angular motor mode.">dJointGetAMotorMode</a> (_id); }
+<a name="l00648"></a>00648 
+<a name="l00649"></a>00649   <span class="keywordtype">void</span> setNumAxes (<span class="keywordtype">int</span> num)
+<a name="l00650"></a>00650     { <a class="code" href="group__joints.html#g1406f976045a1b7edffbb46bf626d04f" title="set the nr of axes">dJointSetAMotorNumAxes</a> (_id, num); }
+<a name="l00651"></a>00651   <span class="keywordtype">int</span> getNumAxes()<span class="keyword"> const</span>
+<a name="l00652"></a>00652 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g35f0392af69ece0d0c3ef7ed88b532bf" title="Get the number of angular axes that will be controlled by the AMotor.">dJointGetAMotorNumAxes</a> (_id); }
+<a name="l00653"></a>00653 
+<a name="l00654"></a>00654   <span class="keywordtype">void</span> setAxis (<span class="keywordtype">int</span> anum, <span class="keywordtype">int</span> rel, dReal x, dReal y, dReal z)
+<a name="l00655"></a>00655     { <a class="code" href="group__joints.html#gbef7d92227b62e04b60eb9df02359603" title="set axis">dJointSetAMotorAxis</a> (_id, anum, rel, x, y, z); }
+<a name="l00656"></a>00656   <span class="keywordtype">void</span> getAxis (<span class="keywordtype">int</span> anum, dVector3 result)<span class="keyword"> const</span>
+<a name="l00657"></a>00657 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#gef1af77cc19d81b24ad00025f3c9d5ec" title="Get the AMotor axes.">dJointGetAMotorAxis</a> (_id, anum, result); }
+<a name="l00658"></a>00658   <span class="keywordtype">int</span> getAxisRel (<span class="keywordtype">int</span> anum)<span class="keyword"> const</span>
+<a name="l00659"></a>00659 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g1887538374f044e22f9742650d14ae69" title="Get axis.">dJointGetAMotorAxisRel</a> (_id, anum); }
+<a name="l00660"></a>00660 
+<a name="l00661"></a>00661   <span class="keywordtype">void</span> setAngle (<span class="keywordtype">int</span> anum, dReal angle)
+<a name="l00662"></a>00662     { <a class="code" href="group__joints.html#g17b2089e6512e22d71340befb40100d2" title="Tell the AMotor what the current angle is along axis anum.">dJointSetAMotorAngle</a> (_id, anum, angle); }
+<a name="l00663"></a>00663   dReal getAngle (<span class="keywordtype">int</span> anum)<span class="keyword"> const</span>
+<a name="l00664"></a>00664 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g3634444b00ac33a5f34a7af4fffda8b2" title="Get the current angle for axis.">dJointGetAMotorAngle</a> (_id, anum); }
+<a name="l00665"></a>00665   dReal getAngleRate (<span class="keywordtype">int</span> anum)
+<a name="l00666"></a>00666     { <span class="keywordflow">return</span> <a class="code" href="group__joints.html#ga65abc36177390330037299b689b70c7" title="Get the current angle rate for axis anum.">dJointGetAMotorAngleRate</a> (_id,anum); }
+<a name="l00667"></a>00667 
+<a name="l00668"></a>00668   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00669"></a>00669     { <a class="code" href="group__joints.html#gac3f00196ee0cdb772e00dc259ef639a" title="set joint parameter">dJointSetAMotorParam</a> (_id, parameter, value); }
+<a name="l00670"></a>00670   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00671"></a>00671 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gfc4cd1046089baa4309d30ae7832d289" title="get joint parameter">dJointGetAMotorParam</a> (_id, parameter); }
+<a name="l00672"></a>00672 
+<a name="l00673"></a>00673   <span class="keywordtype">void</span> addTorques(dReal torque1, dReal torque2, dReal torque3)
+<a name="l00674"></a>00674    { <a class="code" href="group__joints.html#g69d13d54516716020d2adb841699b77b" title="Applies torque0 about the AMotor&amp;#39;s axis 0, torque1 about the AMotor&amp;#39;s axis...">dJointAddAMotorTorques</a>(_id, torque1, torque2, torque3); }
+<a name="l00675"></a>00675 };
+<a name="l00676"></a>00676 
+<a name="l00677"></a>00677 
+<a name="l00678"></a>00678 <span class="keyword">class </span>dLMotorJoint : <span class="keyword">public</span> dJoint {
+<a name="l00679"></a>00679   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00680"></a>00680   dLMotorJoint (<span class="keyword">const</span> dLMotorJoint &amp;);
+<a name="l00681"></a>00681   <span class="keywordtype">void</span> operator = (<span class="keyword">const</span> dLMotorJoint &amp;);
+<a name="l00682"></a>00682 
+<a name="l00683"></a>00683 <span class="keyword">public</span>:
+<a name="l00684"></a>00684   dLMotorJoint() { }
+<a name="l00685"></a>00685   dLMotorJoint (dWorldID world, dJointGroupID group=0)
+<a name="l00686"></a>00686     { _id = <a class="code" href="group__joints.html#g21c8c99615269c5d9d3c57c674f6fd56" title="Create a new joint of the L-motor type.">dJointCreateLMotor</a> (world, group); }
+<a name="l00687"></a>00687 
+<a name="l00688"></a>00688   <span class="keywordtype">void</span> create (dWorldID world, dJointGroupID group=0) {
+<a name="l00689"></a>00689     <span class="keywordflow">if</span> (_id) <a class="code" href="group__joints.html#g2187ccbcf51c951f680eb6c9a210801a" title="Destroy a joint.">dJointDestroy</a> (_id);
+<a name="l00690"></a>00690     _id = <a class="code" href="group__joints.html#g21c8c99615269c5d9d3c57c674f6fd56" title="Create a new joint of the L-motor type.">dJointCreateLMotor</a> (world, group);
+<a name="l00691"></a>00691   }
+<a name="l00692"></a>00692 
+<a name="l00693"></a>00693   <span class="keywordtype">void</span> setNumAxes (<span class="keywordtype">int</span> num)
+<a name="l00694"></a>00694     { <a class="code" href="group__joints.html#gcbfb4014567d69010aba3024d9b7bccd" title="Set the number of axes that will be controlled by the LMotor.">dJointSetLMotorNumAxes</a> (_id, num); }
+<a name="l00695"></a>00695   <span class="keywordtype">int</span> getNumAxes()<span class="keyword"> const</span>
+<a name="l00696"></a>00696 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#g6d7557b5e94e0ee37561cadc5bf85cb7" title="Get nr of axes.">dJointGetLMotorNumAxes</a> (_id); }
+<a name="l00697"></a>00697 
+<a name="l00698"></a>00698   <span class="keywordtype">void</span> setAxis (<span class="keywordtype">int</span> anum, <span class="keywordtype">int</span> rel, dReal x, dReal y, dReal z)
+<a name="l00699"></a>00699     { <a class="code" href="group__joints.html#g080b7739f5b2b37a798742cee0ef38a4" title="Set the AMotor axes.">dJointSetLMotorAxis</a> (_id, anum, rel, x, y, z); }
+<a name="l00700"></a>00700   <span class="keywordtype">void</span> getAxis (<span class="keywordtype">int</span> anum, dVector3 result)<span class="keyword"> const</span>
+<a name="l00701"></a>00701 <span class="keyword">    </span>{ <a class="code" href="group__joints.html#g4ef7e0ca633583e82d90679c8eb6d5c3" title="Get axis.">dJointGetLMotorAxis</a> (_id, anum, result); }
+<a name="l00702"></a>00702 
+<a name="l00703"></a>00703   <span class="keywordtype">void</span> setParam (<span class="keywordtype">int</span> parameter, dReal value)
+<a name="l00704"></a>00704     { <a class="code" href="group__joints.html#g791bfa6e65d0c3dce99ca0bcd3beb8d6" title="set joint parameter">dJointSetLMotorParam</a> (_id, parameter, value); }
+<a name="l00705"></a>00705   dReal getParam (<span class="keywordtype">int</span> parameter)<span class="keyword"> const</span>
+<a name="l00706"></a>00706 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__joints.html#gcbc48fd61857e3843923166abf81a7a0" title="get joint parameter">dJointGetLMotorParam</a> (_id, parameter); }
+<a name="l00707"></a>00707 };
+<a name="l00708"></a>00708 
+<a name="l00709"></a>00709 
+<a name="l00710"></a>00710 
+<a name="l00711"></a>00711 <span class="preprocessor">#endif</span>
+<a name="l00712"></a>00712 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/odecpp__collision_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/odecpp__collision_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/odecpp__collision_8h-source.html	(revision 216)
@@ -0,0 +1,366 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: odecpp_collision.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>odecpp_collision.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                          *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.    *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org    *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                          *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or   *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:             *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *  Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *  your option) any later version. The text of the GNU Lesser  *</span>
+<a name="l00011"></a>00011 <span class="comment"> *  General Public License is included with this library in the    *</span>
+<a name="l00012"></a>00012 <span class="comment"> *  file LICENSE.TXT.                   *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in  *</span>
+<a name="l00014"></a>00014 <span class="comment"> *  the file LICENSE-BSD.TXT.              *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                          *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,    *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of  *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.         *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                          *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="comment">/* C++ interface for new collision API */</span>
+<a name="l00024"></a>00024 
+<a name="l00025"></a>00025 
+<a name="l00026"></a>00026 <span class="preprocessor">#ifndef _ODE_ODECPP_COLLISION_H_</span>
+<a name="l00027"></a>00027 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_ODECPP_COLLISION_H_</span>
+<a name="l00028"></a>00028 <span class="preprocessor"></span><span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span>
+<a name="l00030"></a>00030 <span class="preprocessor">#include &lt;ode/error.h&gt;</span>
+<a name="l00031"></a>00031 
+<a name="l00032"></a>00032 
+<a name="l00033"></a>00033 <span class="keyword">class </span>dGeom {
+<a name="l00034"></a>00034   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00035"></a>00035   dGeom (dGeom &amp;);
+<a name="l00036"></a>00036   <span class="keywordtype">void</span> operator= (dGeom &amp;);
+<a name="l00037"></a>00037 
+<a name="l00038"></a>00038 <span class="keyword">protected</span>:
+<a name="l00039"></a>00039   dGeomID _id;
+<a name="l00040"></a>00040 
+<a name="l00041"></a>00041 <span class="keyword">public</span>:
+<a name="l00042"></a>00042   dGeom()
+<a name="l00043"></a>00043     { _id = 0; }
+<a name="l00044"></a>00044   ~dGeom()
+<a name="l00045"></a>00045     { <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id); }
+<a name="l00046"></a>00046 
+<a name="l00047"></a>00047   dGeomID id()<span class="keyword"> const</span>
+<a name="l00048"></a>00048 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00049"></a>00049   operator dGeomID()<span class="keyword"> const</span>
+<a name="l00050"></a>00050 <span class="keyword">    </span>{ <span class="keywordflow">return</span> _id; }
+<a name="l00051"></a>00051 
+<a name="l00052"></a>00052   <span class="keywordtype">void</span> destroy() {
+<a name="l00053"></a>00053     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00054"></a>00054     _id = 0;
+<a name="l00055"></a>00055   }
+<a name="l00056"></a>00056 
+<a name="l00057"></a>00057   <span class="keywordtype">int</span> getClass()<span class="keyword"> const</span>
+<a name="l00058"></a>00058 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide.html#g07b5ed5b915f756f419a4a7ce69dc67e" title="Given a geom, this returns its class.">dGeomGetClass</a> (_id); }
+<a name="l00059"></a>00059 
+<a name="l00060"></a>00060   dSpaceID getSpace()<span class="keyword"> const</span>
+<a name="l00061"></a>00061 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide.html#gfdc35eade2cbd0b6886ce957325d7c03" title="Query for the space containing a particular geom.">dGeomGetSpace</a> (_id); }
+<a name="l00062"></a>00062 
+<a name="l00063"></a>00063   <span class="keywordtype">void</span> setData (<span class="keywordtype">void</span> *data)
+<a name="l00064"></a>00064     { <a class="code" href="group__collide.html#gf68eb443d5c66ab1aaa8a7d38d1dbc4f" title="Set the user-defined data pointer stored in the geom.">dGeomSetData</a> (_id,data); }
+<a name="l00065"></a>00065   <span class="keywordtype">void</span> *getData()<span class="keyword"> const</span>
+<a name="l00066"></a>00066 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide.html#gc1a185e22b136814fd3afc8469d98996" title="Get the user-defined data pointer stored in the geom.">dGeomGetData</a> (_id); }
+<a name="l00067"></a>00067 
+<a name="l00068"></a>00068   <span class="keywordtype">void</span> setBody (dBodyID b)
+<a name="l00069"></a>00069     { <a class="code" href="group__collide.html#g97cad1194789477eac19fe364d986505" title="Set the body associated with a placeable geom.">dGeomSetBody</a> (_id,b); }
+<a name="l00070"></a>00070   dBodyID getBody()<span class="keyword"> const</span>
+<a name="l00071"></a>00071 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide.html#gd6cedf77fde0dddf751c5d42fcc8eebf" title="Get the body associated with a placeable geom.">dGeomGetBody</a> (_id); }
+<a name="l00072"></a>00072 
+<a name="l00073"></a>00073   <span class="keywordtype">void</span> setPosition (dReal x, dReal y, dReal z)
+<a name="l00074"></a>00074     { <a class="code" href="group__collide.html#g71043b70a735e8f5451c3e13cef345fe" title="Set the position vector of a placeable geom.">dGeomSetPosition</a> (_id,x,y,z); }
+<a name="l00075"></a>00075   <span class="keyword">const</span> dReal * getPosition()<span class="keyword"> const</span>
+<a name="l00076"></a>00076 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide.html#g95b93f803880cac2619fe2635aa93ad8" title="Get the position vector of a placeable geom.">dGeomGetPosition</a> (_id); }
+<a name="l00077"></a>00077 
+<a name="l00078"></a>00078   <span class="keywordtype">void</span> setRotation (<span class="keyword">const</span> dMatrix3 R)
+<a name="l00079"></a>00079     { <a class="code" href="group__collide.html#g76c510f4b7d5a036d8a36f2d60d670e5" title="Set the rotation matrix of a placeable geom.">dGeomSetRotation</a> (_id,R); }
+<a name="l00080"></a>00080   <span class="keyword">const</span> dReal * getRotation()<span class="keyword"> const</span>
+<a name="l00081"></a>00081 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide.html#g293b2264cefb12f9a6659cacc6a722f7" title="Get the rotation matrix of a placeable geom.">dGeomGetRotation</a> (_id); }
+<a name="l00082"></a>00082     
+<a name="l00083"></a>00083   <span class="keywordtype">void</span> setQuaternion (<span class="keyword">const</span> dQuaternion quat)
+<a name="l00084"></a>00084     { <a class="code" href="group__collide.html#g989149d93162264d699444a57b045150" title="Set the rotation of a placeable geom.">dGeomSetQuaternion</a> (_id,quat); }
+<a name="l00085"></a>00085   <span class="keywordtype">void</span> getQuaternion (dQuaternion quat)<span class="keyword"> const</span>
+<a name="l00086"></a>00086 <span class="keyword">    </span>{ <a class="code" href="group__collide.html#g11ad7f0098639b06f4bcd2d681122842" title="Get the rotation quaternion of a placeable geom.">dGeomGetQuaternion</a> (_id,quat); }
+<a name="l00087"></a>00087 
+<a name="l00088"></a>00088   <span class="keywordtype">void</span> getAABB (dReal aabb[6])<span class="keyword"> const</span>
+<a name="l00089"></a>00089 <span class="keyword">    </span>{ <a class="code" href="group__collide.html#g904e360ac6e9e85a05e67929990e5b72" title="Return the axis-aligned bounding box.">dGeomGetAABB</a> (_id, aabb); }
+<a name="l00090"></a>00090 
+<a name="l00091"></a>00091   <span class="keywordtype">int</span> isSpace()
+<a name="l00092"></a>00092     { <span class="keywordflow">return</span> <a class="code" href="group__collide.html#ge5a58bdc78fb4f163a0e9c3ecabf64c9" title="Determing if a geom is a space.">dGeomIsSpace</a> (_id); }
+<a name="l00093"></a>00093 
+<a name="l00094"></a>00094   <span class="keywordtype">void</span> setCategoryBits (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> bits)
+<a name="l00095"></a>00095     { <a class="code" href="group__collide.html#g80fd5741701eb48472521780d5e2f9b9" title="Set the &amp;quot;category&amp;quot; bitfield for the given geom.">dGeomSetCategoryBits</a> (_id, bits); }
+<a name="l00096"></a>00096   <span class="keywordtype">void</span> setCollideBits (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> bits)
+<a name="l00097"></a>00097     { <a class="code" href="group__collide.html#ga55b4de01a61be41668685857b78455d" title="Set the &amp;quot;collide&amp;quot; bitfield for the given geom.">dGeomSetCollideBits</a> (_id, bits); }
+<a name="l00098"></a>00098   <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> getCategoryBits()
+<a name="l00099"></a>00099     { <span class="keywordflow">return</span> <a class="code" href="group__collide.html#gfb62d3493b6789382f65776ab931e78d" title="Get the &amp;quot;category&amp;quot; bitfield for the given geom.">dGeomGetCategoryBits</a> (_id); }
+<a name="l00100"></a>00100   <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> getCollideBits()
+<a name="l00101"></a>00101     { <span class="keywordflow">return</span> <a class="code" href="group__collide.html#g5591e5c496a5a6f8b66dc57e03d0cd8d" title="Get the &amp;quot;collide&amp;quot; bitfield for the given geom.">dGeomGetCollideBits</a> (_id); }
+<a name="l00102"></a>00102 
+<a name="l00103"></a>00103   <span class="keywordtype">void</span> enable()
+<a name="l00104"></a>00104     { <a class="code" href="group__collide.html#ga7c64b8fcae37ee9541208a0351f3d05" title="Enable a geom.">dGeomEnable</a> (_id); }
+<a name="l00105"></a>00105   <span class="keywordtype">void</span> disable()
+<a name="l00106"></a>00106     { <a class="code" href="group__collide.html#g6cb32b4161435fe491859680b463fc12" title="Disable a geom.">dGeomDisable</a> (_id); }
+<a name="l00107"></a>00107   <span class="keywordtype">int</span> isEnabled()
+<a name="l00108"></a>00108     { <span class="keywordflow">return</span> <a class="code" href="group__collide.html#g6533d33f870cf0fb6684ec05e5c0562e" title="Check to see if a geom is enabled.">dGeomIsEnabled</a> (_id); }
+<a name="l00109"></a>00109 
+<a name="l00110"></a>00110   <span class="keywordtype">void</span> collide2 (dGeomID g, <span class="keywordtype">void</span> *data, <a class="code" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0" title="User callback for geom-geom collision testing.">dNearCallback</a> *callback)
+<a name="l00111"></a>00111     { <a class="code" href="group__collide.html#g72a6bb0b550d3e181f8b7a9be7179db5" title="Determines which geoms from one space may potentially intersect with geoms from another...">dSpaceCollide2</a> (_id,g,data,callback); }
+<a name="l00112"></a>00112 };
+<a name="l00113"></a>00113 
+<a name="l00114"></a>00114 
+<a name="l00115"></a>00115 <span class="keyword">class </span>dSpace : <span class="keyword">public</span> dGeom {
+<a name="l00116"></a>00116   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00117"></a>00117   dSpace (dSpace &amp;);
+<a name="l00118"></a>00118   <span class="keywordtype">void</span> operator= (dSpace &amp;);
+<a name="l00119"></a>00119 
+<a name="l00120"></a>00120 <span class="keyword">protected</span>:
+<a name="l00121"></a>00121   <span class="comment">// the default constructor is protected so that you</span>
+<a name="l00122"></a>00122   <span class="comment">// can't instance this class. you must instance one</span>
+<a name="l00123"></a>00123   <span class="comment">// of its subclasses instead.</span>
+<a name="l00124"></a>00124   dSpace () { _id = 0; }
+<a name="l00125"></a>00125 
+<a name="l00126"></a>00126 <span class="keyword">public</span>:
+<a name="l00127"></a>00127   dSpaceID id()<span class="keyword"> const</span>
+<a name="l00128"></a>00128 <span class="keyword">    </span>{ <span class="keywordflow">return</span> (dSpaceID) _id; }
+<a name="l00129"></a>00129   operator dSpaceID()<span class="keyword"> const</span>
+<a name="l00130"></a>00130 <span class="keyword">    </span>{ <span class="keywordflow">return</span> (dSpaceID) _id; }
+<a name="l00131"></a>00131 
+<a name="l00132"></a>00132   <span class="keywordtype">void</span> setCleanup (<span class="keywordtype">int</span> mode)
+<a name="l00133"></a>00133     { dSpaceSetCleanup (<span class="keywordtype">id</span>(), mode); }
+<a name="l00134"></a>00134   <span class="keywordtype">int</span> getCleanup()
+<a name="l00135"></a>00135     { <span class="keywordflow">return</span> dSpaceGetCleanup (<span class="keywordtype">id</span>()); }
+<a name="l00136"></a>00136 
+<a name="l00137"></a>00137   <span class="keywordtype">void</span> <span class="keyword">add</span> (dGeomID x)
+<a name="l00138"></a>00138     { dSpaceAdd (<span class="keywordtype">id</span>(), x); }
+<a name="l00139"></a>00139   <span class="keywordtype">void</span> <span class="keyword">remove</span> (dGeomID x)
+<a name="l00140"></a>00140     { dSpaceRemove (<span class="keywordtype">id</span>(), x); }
+<a name="l00141"></a>00141   <span class="keywordtype">int</span> query (dGeomID x)
+<a name="l00142"></a>00142     { <span class="keywordflow">return</span> dSpaceQuery (<span class="keywordtype">id</span>(),x); }
+<a name="l00143"></a>00143 
+<a name="l00144"></a>00144   <span class="keywordtype">int</span> getNumGeoms()
+<a name="l00145"></a>00145     { <span class="keywordflow">return</span> dSpaceGetNumGeoms (<span class="keywordtype">id</span>()); }
+<a name="l00146"></a>00146   dGeomID getGeom (<span class="keywordtype">int</span> i)
+<a name="l00147"></a>00147     { <span class="keywordflow">return</span> dSpaceGetGeom (<span class="keywordtype">id</span>(),i); }
+<a name="l00148"></a>00148 
+<a name="l00149"></a>00149   <span class="keywordtype">void</span> collide (<span class="keywordtype">void</span> *data, <a class="code" href="group__collide.html#g9f458413ace07fa9e3e7e52d6652ace0" title="User callback for geom-geom collision testing.">dNearCallback</a> *callback)
+<a name="l00150"></a>00150     { <a class="code" href="group__collide.html#gfd185829b6940e2b3238517e1acd2fbb" title="Determines which pairs of geoms in a space may potentially intersect, and calls the...">dSpaceCollide</a> (<span class="keywordtype">id</span>(),data,callback); }
+<a name="l00151"></a>00151 };
+<a name="l00152"></a>00152 
+<a name="l00153"></a>00153 
+<a name="l00154"></a>00154 <span class="keyword">class </span>dSimpleSpace : <span class="keyword">public</span> dSpace {
+<a name="l00155"></a>00155   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00156"></a>00156   dSimpleSpace (dSimpleSpace &amp;);
+<a name="l00157"></a>00157   <span class="keywordtype">void</span> operator= (dSimpleSpace &amp;);
+<a name="l00158"></a>00158 
+<a name="l00159"></a>00159 <span class="keyword">public</span>:
+<a name="l00160"></a>00160   dSimpleSpace (dSpaceID space)
+<a name="l00161"></a>00161     { _id = (dGeomID) dSimpleSpaceCreate (space); }
+<a name="l00162"></a>00162 };
+<a name="l00163"></a>00163 
+<a name="l00164"></a>00164 
+<a name="l00165"></a>00165 <span class="keyword">class </span>dHashSpace : <span class="keyword">public</span> dSpace {
+<a name="l00166"></a>00166   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00167"></a>00167   dHashSpace (dHashSpace &amp;);
+<a name="l00168"></a>00168   <span class="keywordtype">void</span> operator= (dHashSpace &amp;);
+<a name="l00169"></a>00169 
+<a name="l00170"></a>00170 <span class="keyword">public</span>:
+<a name="l00171"></a>00171   dHashSpace (dSpaceID space)
+<a name="l00172"></a>00172     { _id = (dGeomID) dHashSpaceCreate (space); }
+<a name="l00173"></a>00173   <span class="keywordtype">void</span> setLevels (<span class="keywordtype">int</span> minlevel, <span class="keywordtype">int</span> maxlevel)
+<a name="l00174"></a>00174     { dHashSpaceSetLevels (<span class="keywordtype">id</span>(),minlevel,maxlevel); }
+<a name="l00175"></a>00175 };
+<a name="l00176"></a>00176 
+<a name="l00177"></a>00177 
+<a name="l00178"></a>00178 <span class="keyword">class </span>dQuadTreeSpace : <span class="keyword">public</span> dSpace {
+<a name="l00179"></a>00179   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00180"></a>00180   dQuadTreeSpace (dQuadTreeSpace &amp;);
+<a name="l00181"></a>00181   <span class="keywordtype">void</span> operator= (dQuadTreeSpace &amp;);
+<a name="l00182"></a>00182 
+<a name="l00183"></a>00183 <span class="keyword">public</span>:
+<a name="l00184"></a>00184   dQuadTreeSpace (dSpaceID space, dVector3 center, dVector3 extents, <span class="keywordtype">int</span> depth)
+<a name="l00185"></a>00185     { _id = (dGeomID) dQuadTreeSpaceCreate (space,center,extents,depth); }
+<a name="l00186"></a>00186 };
+<a name="l00187"></a>00187 
+<a name="l00188"></a>00188 
+<a name="l00189"></a>00189 <span class="keyword">class </span>dSphere : <span class="keyword">public</span> dGeom {
+<a name="l00190"></a>00190   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00191"></a>00191   dSphere (dSphere &amp;);
+<a name="l00192"></a>00192   <span class="keywordtype">void</span> operator= (dSphere &amp;);
+<a name="l00193"></a>00193 
+<a name="l00194"></a>00194 <span class="keyword">public</span>:
+<a name="l00195"></a>00195   dSphere () { }
+<a name="l00196"></a>00196   dSphere (dSpaceID space, dReal radius)
+<a name="l00197"></a>00197     { _id = <a class="code" href="group__collide__sphere.html#g53c79c860638ca3600744a193da68474" title="Create a sphere geom of the given radius, and return its ID.">dCreateSphere</a> (space, radius); }
+<a name="l00198"></a>00198 
+<a name="l00199"></a>00199   <span class="keywordtype">void</span> create (dSpaceID space, dReal radius) {
+<a name="l00200"></a>00200     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00201"></a>00201     _id = <a class="code" href="group__collide__sphere.html#g53c79c860638ca3600744a193da68474" title="Create a sphere geom of the given radius, and return its ID.">dCreateSphere</a> (space, radius);
+<a name="l00202"></a>00202   }
+<a name="l00203"></a>00203 
+<a name="l00204"></a>00204   <span class="keywordtype">void</span> setRadius (dReal radius)
+<a name="l00205"></a>00205     { <a class="code" href="group__collide__sphere.html#g2341ae9b3b733571eff7a1857109f394" title="Set the radius of a sphere geom.">dGeomSphereSetRadius</a> (_id, radius); }
+<a name="l00206"></a>00206   dReal getRadius()<span class="keyword"> const</span>
+<a name="l00207"></a>00207 <span class="keyword">    </span>{ <span class="keywordflow">return</span> <a class="code" href="group__collide__sphere.html#g0e7f664deb9f557a6a24f93705b29fa9" title="Retrieves the radius of a sphere geom.">dGeomSphereGetRadius</a> (_id); }
+<a name="l00208"></a>00208 };
+<a name="l00209"></a>00209 
+<a name="l00210"></a>00210 
+<a name="l00211"></a>00211 <span class="keyword">class </span>dBox : <span class="keyword">public</span> dGeom {
+<a name="l00212"></a>00212   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00213"></a>00213   dBox (dBox &amp;);
+<a name="l00214"></a>00214   <span class="keywordtype">void</span> operator= (dBox &amp;);
+<a name="l00215"></a>00215 
+<a name="l00216"></a>00216 <span class="keyword">public</span>:
+<a name="l00217"></a>00217   dBox () { }
+<a name="l00218"></a>00218   dBox (dSpaceID space, dReal lx, dReal ly, dReal lz)
+<a name="l00219"></a>00219     { _id = <a class="code" href="group__collide__box.html#g3e3b0b249a8ccd40a9969e3a26548397" title="Create a box geom with the provided side lengths.">dCreateBox</a> (space,lx,ly,lz); }
+<a name="l00220"></a>00220 
+<a name="l00221"></a>00221   <span class="keywordtype">void</span> create (dSpaceID space, dReal lx, dReal ly, dReal lz) {
+<a name="l00222"></a>00222     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00223"></a>00223     _id = <a class="code" href="group__collide__box.html#g3e3b0b249a8ccd40a9969e3a26548397" title="Create a box geom with the provided side lengths.">dCreateBox</a> (space,lx,ly,lz);
+<a name="l00224"></a>00224   }
+<a name="l00225"></a>00225 
+<a name="l00226"></a>00226   <span class="keywordtype">void</span> setLengths (dReal lx, dReal ly, dReal lz)
+<a name="l00227"></a>00227     { <a class="code" href="group__collide__box.html#g4c7060780be9eaf74228565910168273" title="Set the side lengths of the given box.">dGeomBoxSetLengths</a> (_id, lx, ly, lz); }
+<a name="l00228"></a>00228   <span class="keywordtype">void</span> getLengths (dVector3 result)<span class="keyword"> const</span>
+<a name="l00229"></a>00229 <span class="keyword">    </span>{ <a class="code" href="group__collide__box.html#ge24d9264235d2487b2e2d52b2c62c879" title="Get the side lengths of a box.">dGeomBoxGetLengths</a> (_id,result); }
+<a name="l00230"></a>00230 };
+<a name="l00231"></a>00231 
+<a name="l00232"></a>00232 
+<a name="l00233"></a>00233 <span class="keyword">class </span>dPlane : <span class="keyword">public</span> dGeom {
+<a name="l00234"></a>00234   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00235"></a>00235   dPlane (dPlane &amp;);
+<a name="l00236"></a>00236   <span class="keywordtype">void</span> operator= (dPlane &amp;);
+<a name="l00237"></a>00237 
+<a name="l00238"></a>00238 <span class="keyword">public</span>:
+<a name="l00239"></a>00239   dPlane() { }
+<a name="l00240"></a>00240   dPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d)
+<a name="l00241"></a>00241     { _id = dCreatePlane (space,a,b,c,d); }
+<a name="l00242"></a>00242 
+<a name="l00243"></a>00243   <span class="keywordtype">void</span> create (dSpaceID space, dReal a, dReal b, dReal c, dReal d) {
+<a name="l00244"></a>00244     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00245"></a>00245     _id = dCreatePlane (space,a,b,c,d);
+<a name="l00246"></a>00246   }
+<a name="l00247"></a>00247 
+<a name="l00248"></a>00248   <span class="keywordtype">void</span> setParams (dReal a, dReal b, dReal c, dReal d)
+<a name="l00249"></a>00249     { dGeomPlaneSetParams (_id, a, b, c, d); }
+<a name="l00250"></a>00250   <span class="keywordtype">void</span> getParams (dVector4 result)<span class="keyword"> const</span>
+<a name="l00251"></a>00251 <span class="keyword">    </span>{ dGeomPlaneGetParams (_id,result); }
+<a name="l00252"></a>00252 };
+<a name="l00253"></a>00253 
+<a name="l00254"></a>00254 
+<a name="l00255"></a>00255 <span class="keyword">class </span>dCapsule : <span class="keyword">public</span> dGeom {
+<a name="l00256"></a>00256   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00257"></a>00257   dCapsule (dCapsule &amp;);
+<a name="l00258"></a>00258   <span class="keywordtype">void</span> operator= (dCapsule &amp;);
+<a name="l00259"></a>00259 
+<a name="l00260"></a>00260 <span class="keyword">public</span>:
+<a name="l00261"></a>00261   dCapsule() { }
+<a name="l00262"></a>00262   dCapsule (dSpaceID space, dReal radius, dReal length)
+<a name="l00263"></a>00263     { _id = dCreateCapsule (space,radius,length); }
+<a name="l00264"></a>00264 
+<a name="l00265"></a>00265   <span class="keywordtype">void</span> create (dSpaceID space, dReal radius, dReal length) {
+<a name="l00266"></a>00266     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00267"></a>00267     _id = dCreateCapsule (space,radius,length);
+<a name="l00268"></a>00268   }
+<a name="l00269"></a>00269 
+<a name="l00270"></a>00270   <span class="keywordtype">void</span> setParams (dReal radius, dReal length)
+<a name="l00271"></a>00271     { dGeomCapsuleSetParams (_id, radius, length); }
+<a name="l00272"></a>00272   <span class="keywordtype">void</span> getParams (dReal *radius, dReal *length)<span class="keyword"> const</span>
+<a name="l00273"></a>00273 <span class="keyword">    </span>{ dGeomCapsuleGetParams (_id,radius,length); }
+<a name="l00274"></a>00274 };
+<a name="l00275"></a>00275 
+<a name="l00276"></a>00276 
+<a name="l00277"></a>00277 <span class="keyword">class </span>dRay : <span class="keyword">public</span> dGeom {
+<a name="l00278"></a>00278   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00279"></a>00279   dRay (dRay &amp;);
+<a name="l00280"></a>00280   <span class="keywordtype">void</span> operator= (dRay &amp;);
+<a name="l00281"></a>00281 
+<a name="l00282"></a>00282 <span class="keyword">public</span>:
+<a name="l00283"></a>00283   dRay() { }
+<a name="l00284"></a>00284   dRay (dSpaceID space, dReal length)
+<a name="l00285"></a>00285     { _id = dCreateRay (space,length); }
+<a name="l00286"></a>00286 
+<a name="l00287"></a>00287   <span class="keywordtype">void</span> create (dSpaceID space, dReal length) {
+<a name="l00288"></a>00288     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00289"></a>00289     _id = dCreateRay (space,length);
+<a name="l00290"></a>00290   }
+<a name="l00291"></a>00291 
+<a name="l00292"></a>00292   <span class="keywordtype">void</span> setLength (dReal length)
+<a name="l00293"></a>00293     { dGeomRaySetLength (_id, length); }
+<a name="l00294"></a>00294   dReal getLength()
+<a name="l00295"></a>00295     { <span class="keywordflow">return</span> dGeomRayGetLength (_id); }
+<a name="l00296"></a>00296 
+<a name="l00297"></a>00297   <span class="keywordtype">void</span> <span class="keyword">set</span> (dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz)
+<a name="l00298"></a>00298     { dGeomRaySet (_id, px, py, pz, dx, dy, dz); }
+<a name="l00299"></a>00299   <span class="keywordtype">void</span> <span class="keyword">get</span> (dVector3 start, dVector3 dir)
+<a name="l00300"></a>00300     { dGeomRayGet (_id, start, dir); }
+<a name="l00301"></a>00301 
+<a name="l00302"></a>00302   <span class="keywordtype">void</span> setParams (<span class="keywordtype">int</span> firstContact, <span class="keywordtype">int</span> backfaceCull)
+<a name="l00303"></a>00303     { dGeomRaySetParams (_id, firstContact, backfaceCull); }
+<a name="l00304"></a>00304   <span class="keywordtype">void</span> getParams (<span class="keywordtype">int</span> *firstContact, <span class="keywordtype">int</span> *backfaceCull)
+<a name="l00305"></a>00305     { dGeomRayGetParams (_id, firstContact, backfaceCull); }
+<a name="l00306"></a>00306   <span class="keywordtype">void</span> setClosestHit (<span class="keywordtype">int</span> closestHit)
+<a name="l00307"></a>00307     { dGeomRaySetClosestHit (_id, closestHit); }
+<a name="l00308"></a>00308   <span class="keywordtype">int</span> getClosestHit()
+<a name="l00309"></a>00309     { <span class="keywordflow">return</span> dGeomRayGetClosestHit (_id); }
+<a name="l00310"></a>00310 };
+<a name="l00311"></a>00311 
+<a name="l00312"></a>00312 
+<a name="l00313"></a>00313 <span class="keyword">class </span>dGeomTransform : <span class="keyword">public</span> dGeom {
+<a name="l00314"></a>00314   <span class="comment">// intentionally undefined, don't use these</span>
+<a name="l00315"></a>00315   dGeomTransform (dGeomTransform &amp;);
+<a name="l00316"></a>00316   <span class="keywordtype">void</span> operator= (dGeomTransform &amp;);
+<a name="l00317"></a>00317 
+<a name="l00318"></a>00318 <span class="keyword">public</span>:
+<a name="l00319"></a>00319   dGeomTransform() { }
+<a name="l00320"></a>00320   dGeomTransform (dSpaceID space)
+<a name="l00321"></a>00321     { _id = dCreateGeomTransform (space); }
+<a name="l00322"></a>00322 
+<a name="l00323"></a>00323   <span class="keywordtype">void</span> create (dSpaceID space=0) {
+<a name="l00324"></a>00324     <span class="keywordflow">if</span> (_id) <a class="code" href="group__collide.html#g96b9e7d3a7ca769b0c8f37eecfaf98c6" title="Destroy a geom, removing it from any space.">dGeomDestroy</a> (_id);
+<a name="l00325"></a>00325     _id = dCreateGeomTransform (space);
+<a name="l00326"></a>00326   }
+<a name="l00327"></a>00327 
+<a name="l00328"></a>00328   <span class="keywordtype">void</span> setGeom (dGeomID geom)
+<a name="l00329"></a>00329     { dGeomTransformSetGeom (_id, geom); }
+<a name="l00330"></a>00330   dGeomID getGeom()<span class="keyword"> const</span>
+<a name="l00331"></a>00331 <span class="keyword">    </span>{ <span class="keywordflow">return</span> dGeomTransformGetGeom (_id); }
+<a name="l00332"></a>00332 
+<a name="l00333"></a>00333   <span class="keywordtype">void</span> setCleanup (<span class="keywordtype">int</span> mode)
+<a name="l00334"></a>00334     { dGeomTransformSetCleanup (_id,mode); }
+<a name="l00335"></a>00335   <span class="keywordtype">int</span> getCleanup ()
+<a name="l00336"></a>00336     { <span class="keywordflow">return</span> dGeomTransformGetCleanup (_id); }
+<a name="l00337"></a>00337 
+<a name="l00338"></a>00338   <span class="keywordtype">void</span> setInfo (<span class="keywordtype">int</span> mode)
+<a name="l00339"></a>00339     { dGeomTransformSetInfo (_id,mode); }
+<a name="l00340"></a>00340   <span class="keywordtype">int</span> getInfo()
+<a name="l00341"></a>00341     { <span class="keywordflow">return</span> dGeomTransformGetInfo (_id); }
+<a name="l00342"></a>00342 };
+<a name="l00343"></a>00343 
+<a name="l00344"></a>00344 
+<a name="l00345"></a>00345 <span class="preprocessor">#endif</span>
+<a name="l00346"></a>00346 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/odemath_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/odemath_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/odemath_8h-source.html	(revision 216)
@@ -0,0 +1,350 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: odemath.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>odemath.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_ODEMATH_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_ODEMATH_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 <span class="preprocessor">#ifdef __GNUC__</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span><span class="preprocessor">#define PURE_INLINE extern inline</span>
+<a name="l00030"></a>00030 <span class="preprocessor"></span><span class="preprocessor">#else</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="preprocessor">#define PURE_INLINE inline</span>
+<a name="l00032"></a>00032 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00033"></a>00033 <span class="preprocessor"></span>
+<a name="l00034"></a>00034 <span class="comment">/*</span>
+<a name="l00035"></a>00035 <span class="comment"> * macro to access elements i,j in an NxM matrix A, independent of the</span>
+<a name="l00036"></a>00036 <span class="comment"> * matrix storage convention.</span>
+<a name="l00037"></a>00037 <span class="comment"> */</span>
+<a name="l00038"></a>00038 <span class="preprocessor">#define dACCESS33(A,i,j) ((A)[(i)*4+(j)])</span>
+<a name="l00039"></a>00039 <span class="preprocessor"></span>
+<a name="l00040"></a>00040 <span class="comment">/*</span>
+<a name="l00041"></a>00041 <span class="comment"> * Macro to test for valid floating point values</span>
+<a name="l00042"></a>00042 <span class="comment"> */</span>
+<a name="l00043"></a>00043 <span class="preprocessor">#define dVALIDVEC3(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2])))</span>
+<a name="l00044"></a>00044 <span class="preprocessor"></span><span class="preprocessor">#define dVALIDVEC4(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3])))</span>
+<a name="l00045"></a>00045 <span class="preprocessor"></span><span class="preprocessor">#define dVALIDMAT3(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11])))</span>
+<a name="l00046"></a>00046 <span class="preprocessor"></span><span class="preprocessor">#define dVALIDMAT4(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11]) || dIsNan(m[12]) || dIsNan(m[13]) || dIsNan(m[14]) || dIsNan(m[15]) ))</span>
+<a name="l00047"></a>00047 <span class="preprocessor"></span>
+<a name="l00048"></a>00048 
+<a name="l00049"></a>00049 
+<a name="l00050"></a>00050 <span class="comment">/*</span>
+<a name="l00051"></a>00051 <span class="comment"> * General purpose vector operations with other vectors or constants.</span>
+<a name="l00052"></a>00052 <span class="comment"> */</span>
+<a name="l00053"></a>00053 
+<a name="l00054"></a>00054 <span class="preprocessor">#define dOP(a,op,b,c) \</span>
+<a name="l00055"></a>00055 <span class="preprocessor">    (a)[0] = ((b)[0]) op ((c)[0]); \</span>
+<a name="l00056"></a>00056 <span class="preprocessor">    (a)[1] = ((b)[1]) op ((c)[1]); \</span>
+<a name="l00057"></a>00057 <span class="preprocessor">    (a)[2] = ((b)[2]) op ((c)[2]);</span>
+<a name="l00058"></a>00058 <span class="preprocessor"></span><span class="preprocessor">#define dOPC(a,op,b,c) \</span>
+<a name="l00059"></a>00059 <span class="preprocessor">    (a)[0] = ((b)[0]) op (c); \</span>
+<a name="l00060"></a>00060 <span class="preprocessor">    (a)[1] = ((b)[1]) op (c); \</span>
+<a name="l00061"></a>00061 <span class="preprocessor">    (a)[2] = ((b)[2]) op (c);</span>
+<a name="l00062"></a>00062 <span class="preprocessor"></span><span class="preprocessor">#define dOPE(a,op,b) \</span>
+<a name="l00063"></a>00063 <span class="preprocessor">    (a)[0] op ((b)[0]); \</span>
+<a name="l00064"></a>00064 <span class="preprocessor">    (a)[1] op ((b)[1]); \</span>
+<a name="l00065"></a>00065 <span class="preprocessor">    (a)[2] op ((b)[2]);</span>
+<a name="l00066"></a>00066 <span class="preprocessor"></span><span class="preprocessor">#define dOPEC(a,op,c) \</span>
+<a name="l00067"></a>00067 <span class="preprocessor">    (a)[0] op (c); \</span>
+<a name="l00068"></a>00068 <span class="preprocessor">    (a)[1] op (c); \</span>
+<a name="l00069"></a>00069 <span class="preprocessor">    (a)[2] op (c);</span>
+<a name="l00070"></a>00070 <span class="preprocessor"></span>
+<a name="l00071"></a>00071 
+<a name="l00072"></a>00072 <span class="comment">/*</span>
+<a name="l00073"></a>00073 <span class="comment"> * Length, and squared length helpers. dLENGTH returns the length of a dVector3.</span>
+<a name="l00074"></a>00074 <span class="comment"> * dLENGTHSQUARED return the squared length of a dVector3.</span>
+<a name="l00075"></a>00075 <span class="comment"> */</span>
+<a name="l00076"></a>00076 
+<a name="l00077"></a>00077 <span class="preprocessor">#define dLENGTHSQUARED(a) (((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]))</span>
+<a name="l00078"></a>00078 <span class="preprocessor"></span>
+<a name="l00079"></a>00079 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00080"></a>00080 <span class="preprocessor"></span>
+<a name="l00081"></a>00081 PURE_INLINE dReal dLENGTH (<span class="keyword">const</span> dReal *a) { <span class="keywordflow">return</span> dSqrt(dLENGTHSQUARED(a)); }
+<a name="l00082"></a>00082 
+<a name="l00083"></a>00083 <span class="preprocessor">#else</span>
+<a name="l00084"></a>00084 <span class="preprocessor"></span>
+<a name="l00085"></a>00085 <span class="preprocessor">#define dLENGTH(a) ( dSqrt( ((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]) ) )</span>
+<a name="l00086"></a>00086 <span class="preprocessor"></span>
+<a name="l00087"></a>00087 <span class="preprocessor">#endif </span><span class="comment">/* __cplusplus */</span>
+<a name="l00088"></a>00088 
+<a name="l00089"></a>00089 
+<a name="l00090"></a>00090 
+<a name="l00091"></a>00091 
+<a name="l00092"></a>00092 
+<a name="l00093"></a>00093 <span class="comment">/*</span>
+<a name="l00094"></a>00094 <span class="comment"> * 3-way dot product. dDOTpq means that elements of `a' and `b' are spaced</span>
+<a name="l00095"></a>00095 <span class="comment"> * p and q indexes apart respectively. dDOT() means dDOT11.</span>
+<a name="l00096"></a>00096 <span class="comment"> * in C++ we could use function templates to get all the versions of these</span>
+<a name="l00097"></a>00097 <span class="comment"> * functions - but on some compilers this will result in sub-optimal code.</span>
+<a name="l00098"></a>00098 <span class="comment"> */</span>
+<a name="l00099"></a>00099 
+<a name="l00100"></a>00100 <span class="preprocessor">#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])</span>
+<a name="l00101"></a>00101 <span class="preprocessor"></span>
+<a name="l00102"></a>00102 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00103"></a>00103 <span class="preprocessor"></span>
+<a name="l00104"></a>00104 PURE_INLINE dReal dDOT   (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,1,1); }
+<a name="l00105"></a>00105 PURE_INLINE dReal dDOT13 (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,1,3); }
+<a name="l00106"></a>00106 PURE_INLINE dReal dDOT31 (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,3,1); }
+<a name="l00107"></a>00107 PURE_INLINE dReal dDOT33 (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,3,3); }
+<a name="l00108"></a>00108 PURE_INLINE dReal dDOT14 (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,1,4); }
+<a name="l00109"></a>00109 PURE_INLINE dReal dDOT41 (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,4,1); }
+<a name="l00110"></a>00110 PURE_INLINE dReal dDOT44 (<span class="keyword">const</span> dReal *a, <span class="keyword">const</span> dReal *b) { <span class="keywordflow">return</span> dDOTpq(a,b,4,4); }
+<a name="l00111"></a>00111 
+<a name="l00112"></a>00112 <span class="preprocessor">#else</span>
+<a name="l00113"></a>00113 <span class="preprocessor"></span>
+<a name="l00114"></a>00114 <span class="preprocessor">#define dDOT(a,b)   dDOTpq(a,b,1,1)</span>
+<a name="l00115"></a>00115 <span class="preprocessor"></span><span class="preprocessor">#define dDOT13(a,b) dDOTpq(a,b,1,3)</span>
+<a name="l00116"></a>00116 <span class="preprocessor"></span><span class="preprocessor">#define dDOT31(a,b) dDOTpq(a,b,3,1)</span>
+<a name="l00117"></a>00117 <span class="preprocessor"></span><span class="preprocessor">#define dDOT33(a,b) dDOTpq(a,b,3,3)</span>
+<a name="l00118"></a>00118 <span class="preprocessor"></span><span class="preprocessor">#define dDOT14(a,b) dDOTpq(a,b,1,4)</span>
+<a name="l00119"></a>00119 <span class="preprocessor"></span><span class="preprocessor">#define dDOT41(a,b) dDOTpq(a,b,4,1)</span>
+<a name="l00120"></a>00120 <span class="preprocessor"></span><span class="preprocessor">#define dDOT44(a,b) dDOTpq(a,b,4,4)</span>
+<a name="l00121"></a>00121 <span class="preprocessor"></span>
+<a name="l00122"></a>00122 <span class="preprocessor">#endif </span><span class="comment">/* __cplusplus */</span>
+<a name="l00123"></a>00123 
+<a name="l00124"></a>00124 
+<a name="l00125"></a>00125 <span class="comment">/*</span>
+<a name="l00126"></a>00126 <span class="comment"> * cross product, set a = b x c. dCROSSpqr means that elements of `a', `b'</span>
+<a name="l00127"></a>00127 <span class="comment"> * and `c' are spaced p, q and r indexes apart respectively.</span>
+<a name="l00128"></a>00128 <span class="comment"> * dCROSS() means dCROSS111. `op' is normally `=', but you can set it to</span>
+<a name="l00129"></a>00129 <span class="comment"> * +=, -= etc to get other effects.</span>
+<a name="l00130"></a>00130 <span class="comment"> */</span>
+<a name="l00131"></a>00131 
+<a name="l00132"></a>00132 <span class="preprocessor">#define dCROSS(a,op,b,c) \</span>
+<a name="l00133"></a>00133 <span class="preprocessor">do { \</span>
+<a name="l00134"></a>00134 <span class="preprocessor">  (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \</span>
+<a name="l00135"></a>00135 <span class="preprocessor">  (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \</span>
+<a name="l00136"></a>00136 <span class="preprocessor">  (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); \</span>
+<a name="l00137"></a>00137 <span class="preprocessor">} while(0)</span>
+<a name="l00138"></a>00138 <span class="preprocessor"></span><span class="preprocessor">#define dCROSSpqr(a,op,b,c,p,q,r) \</span>
+<a name="l00139"></a>00139 <span class="preprocessor">do { \</span>
+<a name="l00140"></a>00140 <span class="preprocessor">  (a)[  0] op ((b)[  q]*(c)[2*r] - (b)[2*q]*(c)[  r]); \</span>
+<a name="l00141"></a>00141 <span class="preprocessor">  (a)[  p] op ((b)[2*q]*(c)[  0] - (b)[  0]*(c)[2*r]); \</span>
+<a name="l00142"></a>00142 <span class="preprocessor">  (a)[2*p] op ((b)[  0]*(c)[  r] - (b)[  q]*(c)[  0]); \</span>
+<a name="l00143"></a>00143 <span class="preprocessor">} while(0)</span>
+<a name="l00144"></a>00144 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS114(a,op,b,c) dCROSSpqr(a,op,b,c,1,1,4)</span>
+<a name="l00145"></a>00145 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS141(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,1)</span>
+<a name="l00146"></a>00146 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS144(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,4)</span>
+<a name="l00147"></a>00147 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS411(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,1)</span>
+<a name="l00148"></a>00148 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS414(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,4)</span>
+<a name="l00149"></a>00149 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS441(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,1)</span>
+<a name="l00150"></a>00150 <span class="preprocessor"></span><span class="preprocessor">#define dCROSS444(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,4)</span>
+<a name="l00151"></a>00151 <span class="preprocessor"></span>
+<a name="l00152"></a>00152 
+<a name="l00153"></a>00153 <span class="comment">/*</span>
+<a name="l00154"></a>00154 <span class="comment"> * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.</span>
+<a name="l00155"></a>00155 <span class="comment"> * A is stored by rows, and has `skip' elements per row. the matrix is</span>
+<a name="l00156"></a>00156 <span class="comment"> * assumed to be already zero, so this does not write zero elements!</span>
+<a name="l00157"></a>00157 <span class="comment"> * if (plus,minus) is (+,-) then a positive version will be written.</span>
+<a name="l00158"></a>00158 <span class="comment"> * if (plus,minus) is (-,+) then a negative version will be written.</span>
+<a name="l00159"></a>00159 <span class="comment"> */</span>
+<a name="l00160"></a>00160 
+<a name="l00161"></a>00161 <span class="preprocessor">#define dCROSSMAT(A,a,skip,plus,minus) \</span>
+<a name="l00162"></a>00162 <span class="preprocessor">do { \</span>
+<a name="l00163"></a>00163 <span class="preprocessor">  (A)[1] = minus (a)[2]; \</span>
+<a name="l00164"></a>00164 <span class="preprocessor">  (A)[2] = plus (a)[1]; \</span>
+<a name="l00165"></a>00165 <span class="preprocessor">  (A)[(skip)+0] = plus (a)[2]; \</span>
+<a name="l00166"></a>00166 <span class="preprocessor">  (A)[(skip)+2] = minus (a)[0]; \</span>
+<a name="l00167"></a>00167 <span class="preprocessor">  (A)[2*(skip)+0] = minus (a)[1]; \</span>
+<a name="l00168"></a>00168 <span class="preprocessor">  (A)[2*(skip)+1] = plus (a)[0]; \</span>
+<a name="l00169"></a>00169 <span class="preprocessor">} while(0)</span>
+<a name="l00170"></a>00170 <span class="preprocessor"></span>
+<a name="l00171"></a>00171 
+<a name="l00172"></a>00172 <span class="comment">/*</span>
+<a name="l00173"></a>00173 <span class="comment"> * compute the distance between two 3D-vectors</span>
+<a name="l00174"></a>00174 <span class="comment"> */</span>
+<a name="l00175"></a>00175 
+<a name="l00176"></a>00176 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00177"></a>00177 <span class="preprocessor"></span>PURE_INLINE dReal dDISTANCE (<span class="keyword">const</span> dVector3 a, <span class="keyword">const</span> dVector3 b)
+<a name="l00178"></a>00178    { <span class="keywordflow">return</span> dSqrt( (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]) ); }
+<a name="l00179"></a>00179 <span class="preprocessor">#else</span>
+<a name="l00180"></a>00180 <span class="preprocessor"></span><span class="preprocessor">#define dDISTANCE(a,b) \</span>
+<a name="l00181"></a>00181 <span class="preprocessor">   (dSqrt( ((a)[0]-(b)[0])*((a)[0]-(b)[0]) + ((a)[1]-(b)[1])*((a)[1]-(b)[1]) + ((a)[2]-(b)[2])*((a)[2]-(b)[2]) ))</span>
+<a name="l00182"></a>00182 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00183"></a>00183 <span class="preprocessor"></span>
+<a name="l00184"></a>00184 
+<a name="l00185"></a>00185 <span class="comment">/*</span>
+<a name="l00186"></a>00186 <span class="comment"> * special case matrix multipication, with operator selection</span>
+<a name="l00187"></a>00187 <span class="comment"> */</span>
+<a name="l00188"></a>00188 
+<a name="l00189"></a>00189 <span class="preprocessor">#define dMULTIPLYOP0_331(A,op,B,C) \</span>
+<a name="l00190"></a>00190 <span class="preprocessor">do { \</span>
+<a name="l00191"></a>00191 <span class="preprocessor">  (A)[0] op dDOT((B),(C)); \</span>
+<a name="l00192"></a>00192 <span class="preprocessor">  (A)[1] op dDOT((B+4),(C)); \</span>
+<a name="l00193"></a>00193 <span class="preprocessor">  (A)[2] op dDOT((B+8),(C)); \</span>
+<a name="l00194"></a>00194 <span class="preprocessor">} while(0)</span>
+<a name="l00195"></a>00195 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYOP1_331(A,op,B,C) \</span>
+<a name="l00196"></a>00196 <span class="preprocessor">do { \</span>
+<a name="l00197"></a>00197 <span class="preprocessor">  (A)[0] op dDOT41((B),(C)); \</span>
+<a name="l00198"></a>00198 <span class="preprocessor">  (A)[1] op dDOT41((B+1),(C)); \</span>
+<a name="l00199"></a>00199 <span class="preprocessor">  (A)[2] op dDOT41((B+2),(C)); \</span>
+<a name="l00200"></a>00200 <span class="preprocessor">} while(0)</span>
+<a name="l00201"></a>00201 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYOP0_133(A,op,B,C) \</span>
+<a name="l00202"></a>00202 <span class="preprocessor">do { \</span>
+<a name="l00203"></a>00203 <span class="preprocessor">  (A)[0] op dDOT14((B),(C)); \</span>
+<a name="l00204"></a>00204 <span class="preprocessor">  (A)[1] op dDOT14((B),(C+1)); \</span>
+<a name="l00205"></a>00205 <span class="preprocessor">  (A)[2] op dDOT14((B),(C+2)); \</span>
+<a name="l00206"></a>00206 <span class="preprocessor">} while(0)</span>
+<a name="l00207"></a>00207 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYOP0_333(A,op,B,C) \</span>
+<a name="l00208"></a>00208 <span class="preprocessor">do { \</span>
+<a name="l00209"></a>00209 <span class="preprocessor">  (A)[0] op dDOT14((B),(C)); \</span>
+<a name="l00210"></a>00210 <span class="preprocessor">  (A)[1] op dDOT14((B),(C+1)); \</span>
+<a name="l00211"></a>00211 <span class="preprocessor">  (A)[2] op dDOT14((B),(C+2)); \</span>
+<a name="l00212"></a>00212 <span class="preprocessor">  (A)[4] op dDOT14((B+4),(C)); \</span>
+<a name="l00213"></a>00213 <span class="preprocessor">  (A)[5] op dDOT14((B+4),(C+1)); \</span>
+<a name="l00214"></a>00214 <span class="preprocessor">  (A)[6] op dDOT14((B+4),(C+2)); \</span>
+<a name="l00215"></a>00215 <span class="preprocessor">  (A)[8] op dDOT14((B+8),(C)); \</span>
+<a name="l00216"></a>00216 <span class="preprocessor">  (A)[9] op dDOT14((B+8),(C+1)); \</span>
+<a name="l00217"></a>00217 <span class="preprocessor">  (A)[10] op dDOT14((B+8),(C+2)); \</span>
+<a name="l00218"></a>00218 <span class="preprocessor">} while(0)</span>
+<a name="l00219"></a>00219 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYOP1_333(A,op,B,C) \</span>
+<a name="l00220"></a>00220 <span class="preprocessor">do { \</span>
+<a name="l00221"></a>00221 <span class="preprocessor">  (A)[0] op dDOT44((B),(C)); \</span>
+<a name="l00222"></a>00222 <span class="preprocessor">  (A)[1] op dDOT44((B),(C+1)); \</span>
+<a name="l00223"></a>00223 <span class="preprocessor">  (A)[2] op dDOT44((B),(C+2)); \</span>
+<a name="l00224"></a>00224 <span class="preprocessor">  (A)[4] op dDOT44((B+1),(C)); \</span>
+<a name="l00225"></a>00225 <span class="preprocessor">  (A)[5] op dDOT44((B+1),(C+1)); \</span>
+<a name="l00226"></a>00226 <span class="preprocessor">  (A)[6] op dDOT44((B+1),(C+2)); \</span>
+<a name="l00227"></a>00227 <span class="preprocessor">  (A)[8] op dDOT44((B+2),(C)); \</span>
+<a name="l00228"></a>00228 <span class="preprocessor">  (A)[9] op dDOT44((B+2),(C+1)); \</span>
+<a name="l00229"></a>00229 <span class="preprocessor">  (A)[10] op dDOT44((B+2),(C+2)); \</span>
+<a name="l00230"></a>00230 <span class="preprocessor">} while(0)</span>
+<a name="l00231"></a>00231 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYOP2_333(A,op,B,C) \</span>
+<a name="l00232"></a>00232 <span class="preprocessor">do { \</span>
+<a name="l00233"></a>00233 <span class="preprocessor">  (A)[0] op dDOT((B),(C)); \</span>
+<a name="l00234"></a>00234 <span class="preprocessor">  (A)[1] op dDOT((B),(C+4)); \</span>
+<a name="l00235"></a>00235 <span class="preprocessor">  (A)[2] op dDOT((B),(C+8)); \</span>
+<a name="l00236"></a>00236 <span class="preprocessor">  (A)[4] op dDOT((B+4),(C)); \</span>
+<a name="l00237"></a>00237 <span class="preprocessor">  (A)[5] op dDOT((B+4),(C+4)); \</span>
+<a name="l00238"></a>00238 <span class="preprocessor">  (A)[6] op dDOT((B+4),(C+8)); \</span>
+<a name="l00239"></a>00239 <span class="preprocessor">  (A)[8] op dDOT((B+8),(C)); \</span>
+<a name="l00240"></a>00240 <span class="preprocessor">  (A)[9] op dDOT((B+8),(C+4)); \</span>
+<a name="l00241"></a>00241 <span class="preprocessor">  (A)[10] op dDOT((B+8),(C+8)); \</span>
+<a name="l00242"></a>00242 <span class="preprocessor">} while(0)</span>
+<a name="l00243"></a>00243 <span class="preprocessor"></span>
+<a name="l00244"></a>00244 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00245"></a>00245 <span class="preprocessor"></span>
+<a name="l00246"></a>00246 <span class="preprocessor">#define DECL template &lt;class TA, class TB, class TC&gt; PURE_INLINE void</span>
+<a name="l00247"></a>00247 <span class="preprocessor"></span>
+<a name="l00248"></a>00248 DECL dMULTIPLY0_331(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP0_331(A,=,B,C); }
+<a name="l00249"></a>00249 DECL dMULTIPLY1_331(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP1_331(A,=,B,C); }
+<a name="l00250"></a>00250 DECL dMULTIPLY0_133(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP0_133(A,=,B,C); }
+<a name="l00251"></a>00251 DECL dMULTIPLY0_333(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP0_333(A,=,B,C); }
+<a name="l00252"></a>00252 DECL dMULTIPLY1_333(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP1_333(A,=,B,C); }
+<a name="l00253"></a>00253 DECL dMULTIPLY2_333(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP2_333(A,=,B,C); }
+<a name="l00254"></a>00254 
+<a name="l00255"></a>00255 DECL dMULTIPLYADD0_331(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP0_331(A,+=,B,C); }
+<a name="l00256"></a>00256 DECL dMULTIPLYADD1_331(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP1_331(A,+=,B,C); }
+<a name="l00257"></a>00257 DECL dMULTIPLYADD0_133(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP0_133(A,+=,B,C); }
+<a name="l00258"></a>00258 DECL dMULTIPLYADD0_333(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP0_333(A,+=,B,C); }
+<a name="l00259"></a>00259 DECL dMULTIPLYADD1_333(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP1_333(A,+=,B,C); }
+<a name="l00260"></a>00260 DECL dMULTIPLYADD2_333(TA *A, <span class="keyword">const</span> TB *B, <span class="keyword">const</span> TC *C) { dMULTIPLYOP2_333(A,+=,B,C); }
+<a name="l00261"></a>00261 
+<a name="l00262"></a>00262 <span class="preprocessor">#undef DECL</span>
+<a name="l00263"></a>00263 <span class="preprocessor"></span>
+<a name="l00264"></a>00264 <span class="preprocessor">#else</span>
+<a name="l00265"></a>00265 <span class="preprocessor"></span>
+<a name="l00266"></a>00266 <span class="preprocessor">#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)</span>
+<a name="l00267"></a>00267 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)</span>
+<a name="l00268"></a>00268 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLY0_133(A,B,C) dMULTIPLYOP0_133(A,=,B,C)</span>
+<a name="l00269"></a>00269 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C)</span>
+<a name="l00270"></a>00270 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLY1_333(A,B,C) dMULTIPLYOP1_333(A,=,B,C)</span>
+<a name="l00271"></a>00271 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C)</span>
+<a name="l00272"></a>00272 <span class="preprocessor"></span>
+<a name="l00273"></a>00273 <span class="preprocessor">#define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C)</span>
+<a name="l00274"></a>00274 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYADD1_331(A,B,C) dMULTIPLYOP1_331(A,+=,B,C)</span>
+<a name="l00275"></a>00275 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYADD0_133(A,B,C) dMULTIPLYOP0_133(A,+=,B,C)</span>
+<a name="l00276"></a>00276 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYADD0_333(A,B,C) dMULTIPLYOP0_333(A,+=,B,C)</span>
+<a name="l00277"></a>00277 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYADD1_333(A,B,C) dMULTIPLYOP1_333(A,+=,B,C)</span>
+<a name="l00278"></a>00278 <span class="preprocessor"></span><span class="preprocessor">#define dMULTIPLYADD2_333(A,B,C) dMULTIPLYOP2_333(A,+=,B,C)</span>
+<a name="l00279"></a>00279 <span class="preprocessor"></span>
+<a name="l00280"></a>00280 <span class="preprocessor">#endif</span>
+<a name="l00281"></a>00281 <span class="preprocessor"></span>
+<a name="l00282"></a>00282 
+<a name="l00283"></a>00283 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00284"></a>00284 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00285"></a>00285 <span class="preprocessor">#endif</span>
+<a name="l00286"></a>00286 <span class="preprocessor"></span>
+<a name="l00287"></a>00287 <span class="comment">/*</span>
+<a name="l00288"></a>00288 <span class="comment"> * normalize 3x1 and 4x1 vectors (i.e. scale them to unit length)</span>
+<a name="l00289"></a>00289 <span class="comment"> */</span>
+<a name="l00290"></a>00290 ODE_API <span class="keywordtype">int</span>  dSafeNormalize3 (dVector3 a);
+<a name="l00291"></a>00291 ODE_API <span class="keywordtype">int</span>  dSafeNormalize4 (dVector4 a);
+<a name="l00292"></a>00292 
+<a name="l00293"></a>00293 <span class="comment">// For some reason demo_chain1.c does not understand "inline" keyword.</span>
+<a name="l00294"></a>00294 <span class="keyword">static</span> __inline <span class="keywordtype">void</span> _dNormalize3(dVector3 a)
+<a name="l00295"></a>00295 {
+<a name="l00296"></a>00296    <span class="keywordtype">int</span> bNormalizationResult = dSafeNormalize3(a);
+<a name="l00297"></a>00297    dIASSERT(bNormalizationResult);
+<a name="l00298"></a>00298    dVARIABLEUSED(bNormalizationResult);
+<a name="l00299"></a>00299 }
+<a name="l00300"></a>00300 
+<a name="l00301"></a>00301 <span class="keyword">static</span> __inline <span class="keywordtype">void</span> _dNormalize4(dVector4 a)
+<a name="l00302"></a>00302 {
+<a name="l00303"></a>00303    <span class="keywordtype">int</span> bNormalizationResult = dSafeNormalize4(a);
+<a name="l00304"></a>00304    dIASSERT(bNormalizationResult);
+<a name="l00305"></a>00305    dVARIABLEUSED(bNormalizationResult);
+<a name="l00306"></a>00306 }
+<a name="l00307"></a>00307 
+<a name="l00308"></a>00308 <span class="comment">// For DLL export</span>
+<a name="l00309"></a>00309 ODE_API <span class="keywordtype">void</span> dNormalize3 (dVector3 a); <span class="comment">// Potentially asserts on zero vec</span>
+<a name="l00310"></a>00310 ODE_API <span class="keywordtype">void</span> dNormalize4 (dVector4 a); <span class="comment">// Potentially asserts on zero vec</span>
+<a name="l00311"></a>00311 
+<a name="l00312"></a>00312 <span class="comment">// For internal use</span>
+<a name="l00313"></a>00313 <span class="preprocessor">#define dNormalize3(a) _dNormalize3(a)</span>
+<a name="l00314"></a>00314 <span class="preprocessor"></span><span class="preprocessor">#define dNormalize4(a) _dNormalize4(a)</span>
+<a name="l00315"></a>00315 <span class="preprocessor"></span>
+<a name="l00316"></a>00316 <span class="comment">/*</span>
+<a name="l00317"></a>00317 <span class="comment"> * given a unit length "normal" vector n, generate vectors p and q vectors</span>
+<a name="l00318"></a>00318 <span class="comment"> * that are an orthonormal basis for the plane space perpendicular to n.</span>
+<a name="l00319"></a>00319 <span class="comment"> * i.e. this makes p,q such that n,p,q are all perpendicular to each other.</span>
+<a name="l00320"></a>00320 <span class="comment"> * q will equal n x p. if n is not unit length then p will be unit length but</span>
+<a name="l00321"></a>00321 <span class="comment"> * q wont be.</span>
+<a name="l00322"></a>00322 <span class="comment"> */</span>
+<a name="l00323"></a>00323 
+<a name="l00324"></a>00324 ODE_API <span class="keywordtype">void</span> dPlaneSpace (<span class="keyword">const</span> dVector3 n, dVector3 p, dVector3 q);
+<a name="l00325"></a>00325 
+<a name="l00326"></a>00326 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00327"></a>00327 <span class="preprocessor"></span>}
+<a name="l00328"></a>00328 <span class="preprocessor">#endif</span>
+<a name="l00329"></a>00329 <span class="preprocessor"></span>
+<a name="l00330"></a>00330 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/rotation_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/rotation_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/rotation_8h-source.html	(revision 216)
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: rotation.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>rotation.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_ROTATION_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_ROTATION_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/common.h&gt;</span>
+<a name="l00027"></a>00027 <span class="preprocessor">#include &lt;ode/compatibility.h&gt;</span>
+<a name="l00028"></a>00028 
+<a name="l00029"></a>00029 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00030"></a>00030 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00031"></a>00031 <span class="preprocessor">#endif</span>
+<a name="l00032"></a>00032 <span class="preprocessor"></span>
+<a name="l00033"></a>00033 
+<a name="l00034"></a>00034 ODE_API <span class="keywordtype">void</span> dRSetIdentity (dMatrix3 R);
+<a name="l00035"></a>00035 
+<a name="l00036"></a>00036 ODE_API <span class="keywordtype">void</span> dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az,
+<a name="l00037"></a>00037           dReal angle);
+<a name="l00038"></a>00038 
+<a name="l00039"></a>00039 ODE_API <span class="keywordtype">void</span> dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi);
+<a name="l00040"></a>00040 
+<a name="l00041"></a>00041 ODE_API <span class="keywordtype">void</span> dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az,
+<a name="l00042"></a>00042         dReal bx, dReal by, dReal bz);
+<a name="l00043"></a>00043 
+<a name="l00044"></a>00044 ODE_API <span class="keywordtype">void</span> dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az);
+<a name="l00045"></a>00045 
+<a name="l00046"></a>00046 ODE_API <span class="keywordtype">void</span> dQSetIdentity (dQuaternion q);
+<a name="l00047"></a>00047 
+<a name="l00048"></a>00048 ODE_API <span class="keywordtype">void</span> dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az,
+<a name="l00049"></a>00049           dReal angle);
+<a name="l00050"></a>00050 
+<a name="l00051"></a>00051 <span class="comment">/* Quaternion multiplication, analogous to the matrix multiplication routines. */</span>
+<a name="l00052"></a>00052 <span class="comment">/* qa = rotate by qc, then qb */</span>
+<a name="l00053"></a>00053 ODE_API <span class="keywordtype">void</span> dQMultiply0 (dQuaternion qa, <span class="keyword">const</span> dQuaternion qb, <span class="keyword">const</span> dQuaternion qc);
+<a name="l00054"></a>00054 <span class="comment">/* qa = rotate by qc, then by inverse of qb */</span>
+<a name="l00055"></a>00055 ODE_API <span class="keywordtype">void</span> dQMultiply1 (dQuaternion qa, <span class="keyword">const</span> dQuaternion qb, <span class="keyword">const</span> dQuaternion qc);
+<a name="l00056"></a>00056 <span class="comment">/* qa = rotate by inverse of qc, then by qb */</span>
+<a name="l00057"></a>00057 ODE_API <span class="keywordtype">void</span> dQMultiply2 (dQuaternion qa, <span class="keyword">const</span> dQuaternion qb, <span class="keyword">const</span> dQuaternion qc);
+<a name="l00058"></a>00058 <span class="comment">/* qa = rotate by inverse of qc, then by inverse of qb */</span>
+<a name="l00059"></a>00059 ODE_API <span class="keywordtype">void</span> dQMultiply3 (dQuaternion qa, <span class="keyword">const</span> dQuaternion qb, <span class="keyword">const</span> dQuaternion qc);
+<a name="l00060"></a>00060 
+<a name="l00061"></a>00061 ODE_API <span class="keywordtype">void</span> dRfromQ (dMatrix3 R, <span class="keyword">const</span> dQuaternion q);
+<a name="l00062"></a>00062 ODE_API <span class="keywordtype">void</span> dQfromR (dQuaternion q, <span class="keyword">const</span> dMatrix3 R);
+<a name="l00063"></a>00063 ODE_API <span class="keywordtype">void</span> dDQfromW (dReal dq[4], <span class="keyword">const</span> dVector3 w, <span class="keyword">const</span> dQuaternion q);
+<a name="l00064"></a>00064 
+<a name="l00065"></a>00065 
+<a name="l00066"></a>00066 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00067"></a>00067 <span class="preprocessor"></span>}
+<a name="l00068"></a>00068 <span class="preprocessor">#endif</span>
+<a name="l00069"></a>00069 <span class="preprocessor"></span>
+<a name="l00070"></a>00070 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/structd_contact_geom.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/structd_contact_geom.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/structd_contact_geom.html	(revision 216)
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: dContactGeom Struct Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li class="current"><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="functions.html"><span>Data&nbsp;Fields</span></a></li>
+  </ul>
+</div>
+<h1>dContactGeom Struct Reference<br>
+<small>
+[<a class="el" href="group__collide.html">Collision Detection</a>]</small>
+</h1><!-- doxytag: class="dContactGeom" -->Describe the contact point between two geoms.  
+<a href="#_details">More...</a>
+<p>
+<code>#include &lt;<a class="el" href="contact_8h-source.html">contact.h</a>&gt;</code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="2fa7323ee3826d1f55c8cad6157e38a5"></a><!-- doxytag: member="dContactGeom::pos" ref="2fa7323ee3826d1f55c8cad6157e38a5" args="" -->
+dVector3&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structd_contact_geom.html#2fa7323ee3826d1f55c8cad6157e38a5">pos</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">contact position <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="7665d3379904821bbdb7b7d1028fcda3"></a><!-- doxytag: member="dContactGeom::normal" ref="7665d3379904821bbdb7b7d1028fcda3" args="" -->
+dVector3&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structd_contact_geom.html#7665d3379904821bbdb7b7d1028fcda3">normal</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">normal vector <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="29c32c1cb4355186d4110b7abeb58bf0"></a><!-- doxytag: member="dContactGeom::depth" ref="29c32c1cb4355186d4110b7abeb58bf0" args="" -->
+dReal&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structd_contact_geom.html#29c32c1cb4355186d4110b7abeb58bf0">depth</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">penetration depth <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="6049a3a67dba58f65a6ce15a4d9b4cfd"></a><!-- doxytag: member="dContactGeom::g1" ref="6049a3a67dba58f65a6ce15a4d9b4cfd" args="" -->
+dGeomID&nbsp;</td><td class="memItemRight" valign="bottom"><b>g1</b></td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="7dd16e7bbc0c5b5e17116c1e5179281b"></a><!-- doxytag: member="dContactGeom::g2" ref="7dd16e7bbc0c5b5e17116c1e5179281b" args="" -->
+dGeomID&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structd_contact_geom.html#7dd16e7bbc0c5b5e17116c1e5179281b">g2</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the colliding geoms <br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="10bb8b02cd842d19240e3b643469fb33"></a><!-- doxytag: member="dContactGeom::side1" ref="10bb8b02cd842d19240e3b643469fb33" args="" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>side1</b></td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="7a8a080b98c12e0d1f52c86d2738552e"></a><!-- doxytag: member="dContactGeom::side2" ref="7a8a080b98c12e0d1f52c86d2738552e" args="" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structd_contact_geom.html#7a8a080b98c12e0d1f52c86d2738552e">side2</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">(to be documented) <br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Describe the contact point between two geoms. 
+<p>
+If two bodies touch, or if a body touches a static feature in its environment, the contact is represented by one or more "contact points", described by <a class="el" href="structd_contact_geom.html" title="Describe the contact point between two geoms.">dContactGeom</a>.<p>
+The convention is that if body 1 is moved along the normal vector by a distance depth (or equivalently if body 2 is moved the same distance in the opposite direction) then the contact depth will be reduced to zero. This means that the normal vector points "in" to body 1. <hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="contact_8h-source.html">contact.h</a></ul>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/structds_functions.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/structds_functions.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/structds_functions.html	(revision 216)
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: dsFunctions Struct Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li class="current"><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<div class="tabs">
+  <ul>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li><a href="functions.html"><span>Data&nbsp;Fields</span></a></li>
+  </ul>
+</div>
+<h1>dsFunctions Struct Reference<br>
+<small>
+[<a class="el" href="group__drawstuff.html">DrawStuff</a>]</small>
+</h1><!-- doxytag: class="dsFunctions" -->Set of functions to be used as callbacks by the simulation loop.  
+<a href="#_details">More...</a>
+<p>
+<code>#include &lt;<a class="el" href="drawstuff_8h-source.html">drawstuff.h</a>&gt;</code>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Fields</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="b9dd3fbba4366fad5531214cebb47d94"></a><!-- doxytag: member="dsFunctions::version" ref="b9dd3fbba4366fad5531214cebb47d94" args="" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>version</b></td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="22cef28f3bb9f83bc497a1343f4305d0"></a><!-- doxytag: member="dsFunctions::start" ref="22cef28f3bb9f83bc497a1343f4305d0" args=")()" -->
+void(*&nbsp;</td><td class="memItemRight" valign="bottom"><b>start</b> )()</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="232c4ad2d795826a52592b4267b5cbe9"></a><!-- doxytag: member="dsFunctions::step" ref="232c4ad2d795826a52592b4267b5cbe9" args=")(int pause)" -->
+void(*&nbsp;</td><td class="memItemRight" valign="bottom"><b>step</b> )(int pause)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="e9481850ebd8267a71764556cd454d9c"></a><!-- doxytag: member="dsFunctions::command" ref="e9481850ebd8267a71764556cd454d9c" args=")(int cmd)" -->
+void(*&nbsp;</td><td class="memItemRight" valign="bottom"><b>command</b> )(int cmd)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="a0b6965c89af9af4b92243a611f8787b"></a><!-- doxytag: member="dsFunctions::stop" ref="a0b6965c89af9af4b92243a611f8787b" args=")()" -->
+void(*&nbsp;</td><td class="memItemRight" valign="bottom"><b>stop</b> )()</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="65706b30adf57fe5eefdf6e141d249dd"></a><!-- doxytag: member="dsFunctions::path_to_textures" ref="65706b30adf57fe5eefdf6e141d249dd" args="" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>path_to_textures</b></td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Set of functions to be used as callbacks by the simulation loop. <hr>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="drawstuff_8h-source.html">drawstuff.h</a></ul>
+<hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:52 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/tabs.css
===================================================================
--- /code/branches/ode/ode-0.9/docs/tabs.css	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/tabs.css	(revision 216)
@@ -0,0 +1,102 @@
+/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */
+
+DIV.tabs
+{
+   float            : left;
+   width            : 100%;
+   background       : url("tab_b.gif") repeat-x bottom;
+   margin-bottom    : 4px;
+}
+
+DIV.tabs UL
+{
+   margin           : 0px;
+   padding-left     : 10px;
+   list-style       : none;
+}
+
+DIV.tabs LI, DIV.tabs FORM
+{
+   display          : inline;
+   margin           : 0px;
+   padding          : 0px;
+}
+
+DIV.tabs FORM
+{
+   float            : right;
+}
+
+DIV.tabs A
+{
+   float            : left;
+   background       : url("tab_r.gif") no-repeat right top;
+   border-bottom    : 1px solid #84B0C7;
+   font-size        : x-small;
+   font-weight      : bold;
+   text-decoration  : none;
+}
+
+DIV.tabs A:hover
+{
+   background-position: 100% -150px;
+}
+
+DIV.tabs A:link, DIV.tabs A:visited,
+DIV.tabs A:active, DIV.tabs A:hover
+{
+       color: #1A419D;
+}
+
+DIV.tabs SPAN
+{
+   float            : left;
+   display          : block;
+   background       : url("tab_l.gif") no-repeat left top;
+   padding          : 5px 9px;
+   white-space      : nowrap;
+}
+
+DIV.tabs INPUT
+{
+   float            : right;
+   display          : inline;
+   font-size        : 1em;
+}
+
+DIV.tabs TD
+{
+   font-size        : x-small;
+   font-weight      : bold;
+   text-decoration  : none;
+}
+
+
+
+/* Commented Backslash Hack hides rule from IE5-Mac \*/
+DIV.tabs SPAN {float : none;}
+/* End IE5-Mac hack */
+
+DIV.tabs A:hover SPAN
+{
+   background-position: 0% -150px;
+}
+
+DIV.tabs LI.current A
+{
+   background-position: 100% -150px;
+   border-width     : 0px;
+}
+
+DIV.tabs LI.current SPAN
+{
+   background-position: 0% -150px;
+   padding-bottom   : 6px;
+}
+
+DIV.nav
+{
+   background       : none;
+   border           : none;
+   border-bottom    : 1px solid #84B0C7;
+}
Index: /code/branches/ode/ode-0.9/docs/timer_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/timer_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/timer_8h-source.html	(revision 216)
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: timer.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>timer.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef _ODE_TIMER_H_</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define _ODE_TIMER_H_</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="preprocessor">#include &lt;ode/config.h&gt;</span>
+<a name="l00027"></a>00027 
+<a name="l00028"></a>00028 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00029"></a>00029 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
+<a name="l00030"></a>00030 <span class="preprocessor">#endif</span>
+<a name="l00031"></a>00031 <span class="preprocessor"></span>
+<a name="l00032"></a>00032 
+<a name="l00033"></a>00033 <span class="comment">/* stop watch objects */</span>
+<a name="l00034"></a>00034 
+<a name="l00035"></a>00035 <span class="keyword">typedef</span> <span class="keyword">struct </span>dStopwatch {
+<a name="l00036"></a>00036   <span class="keywordtype">double</span> time;       <span class="comment">/* total clock count */</span>
+<a name="l00037"></a>00037   <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> cc[2];     <span class="comment">/* clock count since last `start' */</span>
+<a name="l00038"></a>00038 } dStopwatch;
+<a name="l00039"></a>00039 
+<a name="l00040"></a>00040 ODE_API <span class="keywordtype">void</span> dStopwatchReset (dStopwatch *);
+<a name="l00041"></a>00041 ODE_API <span class="keywordtype">void</span> dStopwatchStart (dStopwatch *);
+<a name="l00042"></a>00042 ODE_API <span class="keywordtype">void</span> dStopwatchStop  (dStopwatch *);
+<a name="l00043"></a>00043 ODE_API <span class="keywordtype">double</span> dStopwatchTime (dStopwatch *);   <span class="comment">/* returns total time in secs */</span>
+<a name="l00044"></a>00044 
+<a name="l00045"></a>00045 
+<a name="l00046"></a>00046 <span class="comment">/* code timers */</span>
+<a name="l00047"></a>00047 
+<a name="l00048"></a>00048 ODE_API <span class="keywordtype">void</span> dTimerStart (<span class="keyword">const</span> <span class="keywordtype">char</span> *description);   <span class="comment">/* pass a static string here */</span>
+<a name="l00049"></a>00049 ODE_API <span class="keywordtype">void</span> dTimerNow (<span class="keyword">const</span> <span class="keywordtype">char</span> *description);  <span class="comment">/* pass a static string here */</span>
+<a name="l00050"></a>00050 ODE_API <span class="keywordtype">void</span> dTimerEnd(<span class="keywordtype">void</span>);
+<a name="l00051"></a>00051 
+<a name="l00052"></a>00052 <span class="comment">/* print out a timer report. if `average' is nonzero, print out the average</span>
+<a name="l00053"></a>00053 <span class="comment"> * time for each slot (this is only meaningful if the same start-now-end</span>
+<a name="l00054"></a>00054 <span class="comment"> * calls are being made repeatedly.</span>
+<a name="l00055"></a>00055 <span class="comment"> */</span>
+<a name="l00056"></a>00056 ODE_API <span class="keywordtype">void</span> dTimerReport (FILE *fout, <span class="keywordtype">int</span> average);
+<a name="l00057"></a>00057 
+<a name="l00058"></a>00058 
+<a name="l00059"></a>00059 <span class="comment">/* resolution */</span>
+<a name="l00060"></a>00060 
+<a name="l00061"></a>00061 <span class="comment">/* returns the timer ticks per second implied by the timing hardware or API.</span>
+<a name="l00062"></a>00062 <span class="comment"> * the actual timer resolution may not be this great.</span>
+<a name="l00063"></a>00063 <span class="comment"> */</span>
+<a name="l00064"></a>00064 ODE_API <span class="keywordtype">double</span> dTimerTicksPerSecond(<span class="keywordtype">void</span>);
+<a name="l00065"></a>00065 
+<a name="l00066"></a>00066 <span class="comment">/* returns an estimate of the actual timer resolution, in seconds. this may</span>
+<a name="l00067"></a>00067 <span class="comment"> * be greater than 1/ticks_per_second.</span>
+<a name="l00068"></a>00068 <span class="comment"> */</span>
+<a name="l00069"></a>00069 ODE_API <span class="keywordtype">double</span> dTimerResolution(<span class="keywordtype">void</span>);
+<a name="l00070"></a>00070 
+<a name="l00071"></a>00071 
+<a name="l00072"></a>00072 <span class="preprocessor">#ifdef __cplusplus</span>
+<a name="l00073"></a>00073 <span class="preprocessor"></span>}
+<a name="l00074"></a>00074 <span class="preprocessor">#endif</span>
+<a name="l00075"></a>00075 <span class="preprocessor"></span>
+<a name="l00076"></a>00076 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/docs/version_8h-source.html
===================================================================
--- /code/branches/ode/ode-0.9/docs/version_8h-source.html	(revision 216)
+++ /code/branches/ode/ode-0.9/docs/version_8h-source.html	(revision 216)
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+<title>Open Dynamics Engine: version.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.3 -->
+<div class="tabs">
+  <ul>
+    <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+    <li><a href="modules.html"><span>Modules</span></a></li>
+    <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
+    <li class="current"><a href="files.html"><span>Files</span></a></li>
+  </ul>
+</div>
+<h1>version.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*************************************************************************</span>
+<a name="l00002"></a>00002 <span class="comment"> *                                                                       *</span>
+<a name="l00003"></a>00003 <span class="comment"> * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *</span>
+<a name="l00004"></a>00004 <span class="comment"> * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *</span>
+<a name="l00005"></a>00005 <span class="comment"> *                                                                       *</span>
+<a name="l00006"></a>00006 <span class="comment"> * This library is free software; you can redistribute it and/or         *</span>
+<a name="l00007"></a>00007 <span class="comment"> * modify it under the terms of EITHER:                                  *</span>
+<a name="l00008"></a>00008 <span class="comment"> *   (1) The GNU Lesser General Public License as published by the Free  *</span>
+<a name="l00009"></a>00009 <span class="comment"> *       Software Foundation; either version 2.1 of the License, or (at  *</span>
+<a name="l00010"></a>00010 <span class="comment"> *       your option) any later version. The text of the GNU Lesser      *</span>
+<a name="l00011"></a>00011 <span class="comment"> *       General Public License is included with this library in the     *</span>
+<a name="l00012"></a>00012 <span class="comment"> *       file LICENSE.TXT.                                               *</span>
+<a name="l00013"></a>00013 <span class="comment"> *   (2) The BSD-style license that is included with this library in     *</span>
+<a name="l00014"></a>00014 <span class="comment"> *       the file LICENSE-BSD.TXT.                                       *</span>
+<a name="l00015"></a>00015 <span class="comment"> *                                                                       *</span>
+<a name="l00016"></a>00016 <span class="comment"> * This library is distributed in the hope that it will be useful,       *</span>
+<a name="l00017"></a>00017 <span class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of        *</span>
+<a name="l00018"></a>00018 <span class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *</span>
+<a name="l00019"></a>00019 <span class="comment"> * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *</span>
+<a name="l00020"></a>00020 <span class="comment"> *                                                                       *</span>
+<a name="l00021"></a>00021 <span class="comment"> *************************************************************************/</span>
+<a name="l00022"></a>00022 
+<a name="l00023"></a>00023 <span class="preprocessor">#ifndef __VERSION_H</span>
+<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define __VERSION_H</span>
+<a name="l00025"></a>00025 <span class="preprocessor"></span>
+<a name="l00026"></a>00026 <span class="comment">/* high byte is major version, low byte is minor version */</span>
+<a name="l00027"></a>00027 <span class="preprocessor">#define DS_VERSION 0x0002</span>
+<a name="l00028"></a>00028 <span class="preprocessor"></span>
+<a name="l00029"></a>00029 <span class="preprocessor">#endif</span>
+</pre></div><hr size="1"><address style="text-align: right;"><small>Generated on Fri Oct 12 08:36:51 2007 for Open Dynamics Engine by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.3 </small></address>
+</body>
+</html>
Index: /code/branches/ode/ode-0.9/drawstuff/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/Makefile.am	(revision 216)
@@ -0,0 +1,1 @@
+SUBDIRS = src dstest
Index: /code/branches/ode/ode-0.9/drawstuff/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/Makefile.in	(revision 216)
@@ -0,0 +1,488 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = drawstuff
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src dstest
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  drawstuff/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  drawstuff/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic ctags \
+	ctags-recursive distclean distclean-generic distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+	tags-recursive uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/drawstuff/dstest/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/dstest/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/dstest/Makefile.am	(revision 216)
@@ -0,0 +1,13 @@
+noinst_PROGRAMS= dstest
+dstest_CXXFLAGS = -I$(top_srcdir)/include -I$(top_builddir)
+
+dstest_SOURCES= dstest.cpp
+dstest_DEPENDENCIES=$(top_builddir)/drawstuff/src/libdrawstuff.a
+dstest_LDFLAGS = -L$(top_builddir)/drawstuff/src
+dstest_LDADD=-ldrawstuff @LDFLAGS@ @GL_LIBS@ @LIBS@
+if WIN32
+dstest_DEPENDENCIES+=resources.o
+resources.o: ../src/resources.rc ../src/resource.h
+	@WINDRES@ ../src/resources.rc -o resources.o
+dstest_LDADD+= resources.o
+endif
Index: /code/branches/ode/ode-0.9/drawstuff/dstest/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/dstest/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/dstest/Makefile.in	(revision 216)
@@ -0,0 +1,446 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = dstest$(EXEEXT)
+@WIN32_TRUE@am__append_1 = resources.o
+@WIN32_TRUE@am__append_2 = resources.o
+subdir = drawstuff/dstest
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_dstest_OBJECTS = dstest-dstest.$(OBJEXT)
+dstest_OBJECTS = $(am_dstest_OBJECTS)
+dstest_LINK = $(CXXLD) $(dstest_CXXFLAGS) $(CXXFLAGS) \
+	$(dstest_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+SOURCES = $(dstest_SOURCES)
+DIST_SOURCES = $(dstest_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+dstest_CXXFLAGS = -I$(top_srcdir)/include -I$(top_builddir)
+dstest_SOURCES = dstest.cpp
+dstest_DEPENDENCIES = $(top_builddir)/drawstuff/src/libdrawstuff.a \
+	$(am__append_1)
+dstest_LDFLAGS = -L$(top_builddir)/drawstuff/src
+dstest_LDADD = -ldrawstuff @LDFLAGS@ @GL_LIBS@ @LIBS@ $(am__append_2)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  drawstuff/dstest/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  drawstuff/dstest/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+	-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+dstest$(EXEEXT): $(dstest_OBJECTS) $(dstest_DEPENDENCIES) 
+	@rm -f dstest$(EXEEXT)
+	$(dstest_LINK) $(dstest_OBJECTS) $(dstest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dstest-dstest.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+dstest-dstest.o: dstest.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dstest_CXXFLAGS) $(CXXFLAGS) -MT dstest-dstest.o -MD -MP -MF $(DEPDIR)/dstest-dstest.Tpo -c -o dstest-dstest.o `test -f 'dstest.cpp' || echo '$(srcdir)/'`dstest.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/dstest-dstest.Tpo $(DEPDIR)/dstest-dstest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='dstest.cpp' object='dstest-dstest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dstest_CXXFLAGS) $(CXXFLAGS) -c -o dstest-dstest.o `test -f 'dstest.cpp' || echo '$(srcdir)/'`dstest.cpp
+
+dstest-dstest.obj: dstest.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dstest_CXXFLAGS) $(CXXFLAGS) -MT dstest-dstest.obj -MD -MP -MF $(DEPDIR)/dstest-dstest.Tpo -c -o dstest-dstest.obj `if test -f 'dstest.cpp'; then $(CYGPATH_W) 'dstest.cpp'; else $(CYGPATH_W) '$(srcdir)/dstest.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/dstest-dstest.Tpo $(DEPDIR)/dstest-dstest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='dstest.cpp' object='dstest-dstest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dstest_CXXFLAGS) $(CXXFLAGS) -c -o dstest-dstest.obj `if test -f 'dstest.cpp'; then $(CYGPATH_W) 'dstest.cpp'; else $(CYGPATH_W) '$(srcdir)/dstest.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstPROGRAMS ctags distclean distclean-compile \
+	distclean-generic distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am
+
+@WIN32_TRUE@resources.o: ../src/resources.rc ../src/resource.h
+@WIN32_TRUE@	@WINDRES@ ../src/resources.rc -o resources.o
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/drawstuff/dstest/dstest.cpp
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/dstest/dstest.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/dstest/dstest.cpp	(revision 216)
@@ -0,0 +1,125 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include <drawstuff/drawstuff.h>
+
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+
+void start()
+{
+  // adjust the starting viewpoint a bit
+  float xyz[3],hpr[3];
+  dsGetViewpoint (xyz,hpr);
+  hpr[0] += 7;
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+void simLoop (int pause)
+{
+  float pos[3];
+  float R[12];
+  static float a = 0;
+
+  if (!pause) a += 0.02f;
+  if (a > (2*M_PI)) a -= (float) (2*M_PI);
+  float ca = (float) cos(a);
+  float sa = (float) sin(a);
+
+  dsSetTexture (DS_WOOD);
+
+  float b = (a > M_PI) ? (2*(a-(float)M_PI)) : a*2;
+  pos[0] = -0.3f;
+  pos[1] = 0;
+  pos[2] = (float) (0.1f*(2*M_PI*b - b*b) + 0.65f);
+  R[0] = ca; R[1] = 0; R[2] = -sa;
+  R[4] = 0;  R[5] = 1; R[6] = 0;
+  R[8] = sa; R[9] = 0; R[10] = ca;
+  dsSetColor (1,0.8f,0.6f);
+  dsDrawSphere (pos,R,0.3f);
+
+  dsSetTexture (DS_NONE);
+
+  pos[0] = -0.2f;
+  pos[1] = 0.8f;
+  pos[2] = 0.4f;
+  R[0] = ca; R[1] = -sa; R[2] = 0;
+  R[4] = sa; R[5] = ca;  R[6] = 0;
+  R[8] = 0;  R[9] = 0;	 R[10] = 1;
+  float sides[3] = {0.1f,0.4f,0.8f};
+  dsSetColor (0.6f,0.6f,1);
+  dsDrawBox (pos,R,sides);
+
+  dsSetTexture (DS_WOOD);
+
+  float r = 0.3f;		      // cylinder radius
+  float d = (float)cos(a*2) * 0.4f;
+  float cd = (float)cos(-d/r);
+  float sd = (float)sin(-d/r);
+  pos[0] = -0.2f;
+  pos[1] = -1 + d;
+  pos[2] = 0.3f;
+  R[0] = 0;   R[1] = 0;  R[2] = -1;
+  R[4] = -sd; R[5] = cd; R[6] =  0;
+  R[8] =  cd; R[9] = sd; R[10] = 0;
+  dsSetColor (0.4f,1,1);
+  dsDrawCylinder (pos,R,0.8f,r);
+
+  pos[0] = 0;
+  pos[1] = 0;
+  pos[2] = 0.2f;
+  R[0] = 0; R[1] = sa; R[2] = -ca;
+  R[4] = 0; R[5] = ca; R[6] = sa;
+  R[8] = 1; R[9] = 0;  R[10] = 0;
+  dsSetColor (1,0.9f,0.2f);
+  dsDrawCappedCylinder (pos,R,0.8f,0.2f);
+}
+
+
+void command (int cmd)
+{
+  dsPrint ("received command %d (`%c')\n",cmd,cmd);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = command;
+  fn.stop = 0;
+  fn.path_to_textures = 0;	// uses default
+
+  // run simulation
+  dsSimulationLoop (argc,argv,400,400,&fn);
+
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/drawstuff/src/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/Makefile.am	(revision 216)
@@ -0,0 +1,21 @@
+# We build drawstuff as a non libtool static library manually
+# so it doesn't get installed when 'make install' is called,
+# drawstuff is meant as an aid for testing and not as a full
+# rendering library.
+
+noinst_LIBRARIES = libdrawstuff.a
+libdrawstuff_a_SOURCES = drawstuff.cpp internal.h
+libdrawstuff_a_CXXFLAGS =  @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+
+# libdrawstuff_a_LIBADD = @GL_LIBS@
+
+if WIN32
+libdrawstuff_a_SOURCES+= windows.cpp
+endif
+if X11
+libdrawstuff_a_SOURCES+= x11.cpp
+endif
+if OSX
+libdrawstuff_a_SOURCES+= osx.cpp
+endif
+
Index: /code/branches/ode/ode-0.9/drawstuff/src/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/Makefile.in	(revision 216)
@@ -0,0 +1,507 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# We build drawstuff as a non libtool static library manually
+# so it doesn't get installed when 'make install' is called,
+# drawstuff is meant as an aid for testing and not as a full
+# rendering library.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+
+# libdrawstuff_a_LIBADD = @GL_LIBS@
+@WIN32_TRUE@am__append_1 = windows.cpp
+@X11_TRUE@am__append_2 = x11.cpp
+@OSX_TRUE@am__append_3 = osx.cpp
+subdir = drawstuff/src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libdrawstuff_a_AR = $(AR) $(ARFLAGS)
+libdrawstuff_a_LIBADD =
+am__libdrawstuff_a_SOURCES_DIST = drawstuff.cpp internal.h windows.cpp \
+	x11.cpp osx.cpp
+@WIN32_TRUE@am__objects_1 = libdrawstuff_a-windows.$(OBJEXT)
+@X11_TRUE@am__objects_2 = libdrawstuff_a-x11.$(OBJEXT)
+@OSX_TRUE@am__objects_3 = libdrawstuff_a-osx.$(OBJEXT)
+am_libdrawstuff_a_OBJECTS = libdrawstuff_a-drawstuff.$(OBJEXT) \
+	$(am__objects_1) $(am__objects_2) $(am__objects_3)
+libdrawstuff_a_OBJECTS = $(am_libdrawstuff_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libdrawstuff_a_SOURCES)
+DIST_SOURCES = $(am__libdrawstuff_a_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libdrawstuff.a
+libdrawstuff_a_SOURCES = drawstuff.cpp internal.h $(am__append_1) \
+	$(am__append_2) $(am__append_3)
+libdrawstuff_a_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  drawstuff/src/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  drawstuff/src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libdrawstuff.a: $(libdrawstuff_a_OBJECTS) $(libdrawstuff_a_DEPENDENCIES) 
+	-rm -f libdrawstuff.a
+	$(libdrawstuff_a_AR) libdrawstuff.a $(libdrawstuff_a_OBJECTS) $(libdrawstuff_a_LIBADD)
+	$(RANLIB) libdrawstuff.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdrawstuff_a-drawstuff.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdrawstuff_a-osx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdrawstuff_a-windows.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdrawstuff_a-x11.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libdrawstuff_a-drawstuff.o: drawstuff.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-drawstuff.o -MD -MP -MF $(DEPDIR)/libdrawstuff_a-drawstuff.Tpo -c -o libdrawstuff_a-drawstuff.o `test -f 'drawstuff.cpp' || echo '$(srcdir)/'`drawstuff.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-drawstuff.Tpo $(DEPDIR)/libdrawstuff_a-drawstuff.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='drawstuff.cpp' object='libdrawstuff_a-drawstuff.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-drawstuff.o `test -f 'drawstuff.cpp' || echo '$(srcdir)/'`drawstuff.cpp
+
+libdrawstuff_a-drawstuff.obj: drawstuff.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-drawstuff.obj -MD -MP -MF $(DEPDIR)/libdrawstuff_a-drawstuff.Tpo -c -o libdrawstuff_a-drawstuff.obj `if test -f 'drawstuff.cpp'; then $(CYGPATH_W) 'drawstuff.cpp'; else $(CYGPATH_W) '$(srcdir)/drawstuff.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-drawstuff.Tpo $(DEPDIR)/libdrawstuff_a-drawstuff.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='drawstuff.cpp' object='libdrawstuff_a-drawstuff.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-drawstuff.obj `if test -f 'drawstuff.cpp'; then $(CYGPATH_W) 'drawstuff.cpp'; else $(CYGPATH_W) '$(srcdir)/drawstuff.cpp'; fi`
+
+libdrawstuff_a-windows.o: windows.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-windows.o -MD -MP -MF $(DEPDIR)/libdrawstuff_a-windows.Tpo -c -o libdrawstuff_a-windows.o `test -f 'windows.cpp' || echo '$(srcdir)/'`windows.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-windows.Tpo $(DEPDIR)/libdrawstuff_a-windows.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='windows.cpp' object='libdrawstuff_a-windows.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-windows.o `test -f 'windows.cpp' || echo '$(srcdir)/'`windows.cpp
+
+libdrawstuff_a-windows.obj: windows.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-windows.obj -MD -MP -MF $(DEPDIR)/libdrawstuff_a-windows.Tpo -c -o libdrawstuff_a-windows.obj `if test -f 'windows.cpp'; then $(CYGPATH_W) 'windows.cpp'; else $(CYGPATH_W) '$(srcdir)/windows.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-windows.Tpo $(DEPDIR)/libdrawstuff_a-windows.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='windows.cpp' object='libdrawstuff_a-windows.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-windows.obj `if test -f 'windows.cpp'; then $(CYGPATH_W) 'windows.cpp'; else $(CYGPATH_W) '$(srcdir)/windows.cpp'; fi`
+
+libdrawstuff_a-x11.o: x11.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-x11.o -MD -MP -MF $(DEPDIR)/libdrawstuff_a-x11.Tpo -c -o libdrawstuff_a-x11.o `test -f 'x11.cpp' || echo '$(srcdir)/'`x11.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-x11.Tpo $(DEPDIR)/libdrawstuff_a-x11.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='x11.cpp' object='libdrawstuff_a-x11.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-x11.o `test -f 'x11.cpp' || echo '$(srcdir)/'`x11.cpp
+
+libdrawstuff_a-x11.obj: x11.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-x11.obj -MD -MP -MF $(DEPDIR)/libdrawstuff_a-x11.Tpo -c -o libdrawstuff_a-x11.obj `if test -f 'x11.cpp'; then $(CYGPATH_W) 'x11.cpp'; else $(CYGPATH_W) '$(srcdir)/x11.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-x11.Tpo $(DEPDIR)/libdrawstuff_a-x11.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='x11.cpp' object='libdrawstuff_a-x11.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-x11.obj `if test -f 'x11.cpp'; then $(CYGPATH_W) 'x11.cpp'; else $(CYGPATH_W) '$(srcdir)/x11.cpp'; fi`
+
+libdrawstuff_a-osx.o: osx.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-osx.o -MD -MP -MF $(DEPDIR)/libdrawstuff_a-osx.Tpo -c -o libdrawstuff_a-osx.o `test -f 'osx.cpp' || echo '$(srcdir)/'`osx.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-osx.Tpo $(DEPDIR)/libdrawstuff_a-osx.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='osx.cpp' object='libdrawstuff_a-osx.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-osx.o `test -f 'osx.cpp' || echo '$(srcdir)/'`osx.cpp
+
+libdrawstuff_a-osx.obj: osx.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -MT libdrawstuff_a-osx.obj -MD -MP -MF $(DEPDIR)/libdrawstuff_a-osx.Tpo -c -o libdrawstuff_a-osx.obj `if test -f 'osx.cpp'; then $(CYGPATH_W) 'osx.cpp'; else $(CYGPATH_W) '$(srcdir)/osx.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libdrawstuff_a-osx.Tpo $(DEPDIR)/libdrawstuff_a-osx.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='osx.cpp' object='libdrawstuff_a-osx.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrawstuff_a_CXXFLAGS) $(CXXFLAGS) -c -o libdrawstuff_a-osx.obj `if test -f 'osx.cpp'; then $(CYGPATH_W) 'osx.cpp'; else $(CYGPATH_W) '$(srcdir)/osx.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstLIBRARIES ctags distclean distclean-compile \
+	distclean-generic distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/drawstuff/src/drawstuff.cpp
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/drawstuff.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/drawstuff.cpp	(revision 216)
@@ -0,0 +1,1597 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+simple graphics.
+
+the following command line flags can be used (typically under unix)
+	-notex		Do not use any textures
+	-noshadow[s]	Do not draw any shadows
+	-pause		Start the simulation paused
+
+TODO
+----
+
+manage openGL state changes better
+
+*/
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <ode/config.h>
+#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+
+#include "drawstuff/drawstuff.h"
+#include "internal.h"
+
+//***************************************************************************
+// misc
+
+#ifdef WIN32
+#define DEFAULT_PATH_TO_TEXTURES "..\\textures\\"
+#else
+#define DEFAULT_PATH_TO_TEXTURES "../textures/"
+#endif
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+// constants to convert degrees to radians and the reverse
+#define RAD_TO_DEG (180.0/M_PI)
+#define DEG_TO_RAD (M_PI/180.0)
+
+// light vector. LIGHTZ is implicitly 1
+#define LIGHTX (1.0f)
+#define LIGHTY (0.4f)
+
+// ground and sky
+#define SHADOW_INTENSITY (0.65f)
+#define GROUND_R (0.5f) 	// ground color for when there's no texture
+#define GROUND_G (0.5f)
+#define GROUND_B (0.3f)
+
+const float ground_scale = 1.0f/1.0f;	// ground texture scale (1/size)
+const float ground_ofsx = 0.5;		// offset of ground texture
+const float ground_ofsy = 0.5;
+const float sky_scale = 1.0f/4.0f;	// sky texture scale (1/size)
+const float sky_height = 1.0f;		// sky height above viewpoint
+
+//***************************************************************************
+// misc mathematics stuff
+
+#define dCROSS(a,op,b,c) \
+  (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \
+  (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \
+  (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]);
+
+
+inline float dDOT (const float *a, const float *b)
+  { return ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2]); }
+
+
+static void normalizeVector3 (float v[3])
+{
+  float len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+  if (len <= 0.0f) {
+    v[0] = 1;
+    v[1] = 0;
+    v[2] = 0;
+  }
+  else {
+    len = 1.0f / (float)sqrt(len);
+    v[0] *= len;
+    v[1] *= len;
+    v[2] *= len;
+  }
+}
+
+//***************************************************************************
+// PPM image object
+
+typedef unsigned char byte;
+
+class Image {
+  int image_width,image_height;
+  byte *image_data;
+public:
+  Image (char *filename);
+  // load from PPM file
+  ~Image();
+  int width() { return image_width; }
+  int height() { return image_height; }
+  byte *data() { return image_data; }
+};
+
+
+// skip over whitespace and comments in a stream.
+
+static void skipWhiteSpace (char *filename, FILE *f)
+{
+  int c,d;
+  for(;;) {
+    c = fgetc(f);
+    if (c==EOF) dsError ("unexpected end of file in \"%s\"",filename);
+
+    // skip comments
+    if (c == '#') {
+      do {
+	d = fgetc(f);
+	if (d==EOF) dsError ("unexpected end of file in \"%s\"",filename);
+      } while (d != '\n');
+      continue;
+    }
+
+    if (c > ' ') {
+      ungetc (c,f);
+      return;
+    }
+  }
+}
+
+
+// read a number from a stream, this return 0 if there is none (that's okay
+// because 0 is a bad value for all PPM numbers anyway).
+
+static int readNumber (char *filename, FILE *f)
+{
+  int c,n=0;
+  for(;;) {
+    c = fgetc(f);
+    if (c==EOF) dsError ("unexpected end of file in \"%s\"",filename);
+    if (c >= '0' && c <= '9') n = n*10 + (c - '0');
+    else {
+      ungetc (c,f);
+      return n;
+    }
+  }
+}
+
+
+Image::Image (char *filename)
+{
+  FILE *f = fopen (filename,"rb");
+  if (!f) dsError ("Can't open image file `%s'",filename);
+
+  // read in header
+  if (fgetc(f) != 'P' || fgetc(f) != '6')
+    dsError ("image file \"%s\" is not a binary PPM (no P6 header)",filename);
+  skipWhiteSpace (filename,f);
+
+  // read in image parameters
+  image_width = readNumber (filename,f);
+  skipWhiteSpace (filename,f);
+  image_height = readNumber (filename,f);
+  skipWhiteSpace (filename,f);
+  int max_value = readNumber (filename,f);
+
+  // check values
+  if (image_width < 1 || image_height < 1)
+    dsError ("bad image file \"%s\"",filename);
+  if (max_value != 255)
+    dsError ("image file \"%s\" must have color range of 255",filename);
+
+  // read either nothing, LF (10), or CR,LF (13,10)
+  int c = fgetc(f);
+  if (c == 10) {
+    // LF
+  }
+  else if (c == 13) {
+    // CR
+    c = fgetc(f);
+    if (c != 10) ungetc (c,f);
+  }
+  else ungetc (c,f);
+
+  // read in rest of data
+  image_data = new byte [image_width*image_height*3];
+  if (fread (image_data,image_width*image_height*3,1,f) != 1)
+    dsError ("Can not read data from image file `%s'",filename);
+  fclose (f);
+}
+
+
+Image::~Image()
+{
+  delete[] image_data;
+}
+
+//***************************************************************************
+// Texture object.
+
+class Texture {
+  Image *image;
+  GLuint name;
+public:
+  Texture (char *filename);
+  ~Texture();
+  void bind (int modulate);
+};
+
+
+Texture::Texture (char *filename)
+{
+  image = new Image (filename);
+  glGenTextures (1,&name);
+  glBindTexture (GL_TEXTURE_2D,name);
+
+  // set pixel unpacking mode
+  glPixelStorei (GL_UNPACK_SWAP_BYTES, 0);
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
+  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
+
+  // glTexImage2D (GL_TEXTURE_2D, 0, 3, image->width(), image->height(), 0,
+  //		   GL_RGB, GL_UNSIGNED_BYTE, image->data());
+  gluBuild2DMipmaps (GL_TEXTURE_2D, 3, image->width(), image->height(),
+		     GL_RGB, GL_UNSIGNED_BYTE, image->data());
+
+  // set texture parameters - will these also be bound to the texture???
+  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+		   GL_LINEAR_MIPMAP_LINEAR);
+
+  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+}
+
+
+Texture::~Texture()
+{
+  delete image;
+  glDeleteTextures (1,&name);
+}
+
+
+void Texture::bind (int modulate)
+{
+  glBindTexture (GL_TEXTURE_2D,name);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
+	     modulate ? GL_MODULATE : GL_DECAL);
+}
+
+//***************************************************************************
+// the current drawing state (for when the user's step function is drawing)
+
+static float color[4] = {0,0,0,0};	// current r,g,b,alpha color
+static int tnum = 0;			// current texture number
+
+//***************************************************************************
+// OpenGL utility stuff
+
+static void setCamera (float x, float y, float z, float h, float p, float r)
+{
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity();
+  glRotatef (90, 0,0,1);
+  glRotatef (90, 0,1,0);
+  glRotatef (r, 1,0,0);
+  glRotatef (p, 0,1,0);
+  glRotatef (-h, 0,0,1);
+  glTranslatef (-x,-y,-z);
+}
+
+
+// sets the material color, not the light color
+
+static void setColor (float r, float g, float b, float alpha)
+{
+  GLfloat light_ambient[4],light_diffuse[4],light_specular[4];
+  light_ambient[0] = r*0.3f;
+  light_ambient[1] = g*0.3f;
+  light_ambient[2] = b*0.3f;
+  light_ambient[3] = alpha;
+  light_diffuse[0] = r*0.7f;
+  light_diffuse[1] = g*0.7f;
+  light_diffuse[2] = b*0.7f;
+  light_diffuse[3] = alpha;
+  light_specular[0] = r*0.2f;
+  light_specular[1] = g*0.2f;
+  light_specular[2] = b*0.2f;
+  light_specular[3] = alpha;
+  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, light_ambient);
+  glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, light_diffuse);
+  glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, light_specular);
+  glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 5.0f);
+}
+
+
+static void setTransform (const float pos[3], const float R[12])
+{
+  GLfloat matrix[16];
+  matrix[0]=R[0];
+  matrix[1]=R[4];
+  matrix[2]=R[8];
+  matrix[3]=0;
+  matrix[4]=R[1];
+  matrix[5]=R[5];
+  matrix[6]=R[9];
+  matrix[7]=0;
+  matrix[8]=R[2];
+  matrix[9]=R[6];
+  matrix[10]=R[10];
+  matrix[11]=0;
+  matrix[12]=pos[0];
+  matrix[13]=pos[1];
+  matrix[14]=pos[2];
+  matrix[15]=1;
+  glPushMatrix();
+  glMultMatrixf (matrix);
+}
+static void setTransformD (const double pos[3], const double R[12])
+{
+  GLdouble matrix[16];
+  matrix[0]=R[0];
+  matrix[1]=R[4];
+  matrix[2]=R[8];
+  matrix[3]=0;
+  matrix[4]=R[1];
+  matrix[5]=R[5];
+  matrix[6]=R[9];
+  matrix[7]=0;
+  matrix[8]=R[2];
+  matrix[9]=R[6];
+  matrix[10]=R[10];
+  matrix[11]=0;
+  matrix[12]=pos[0];
+  matrix[13]=pos[1];
+  matrix[14]=pos[2];
+  matrix[15]=1;
+  glPushMatrix();
+  glMultMatrixd (matrix);
+}
+
+
+// set shadow projection transform
+
+static void setShadowTransform()
+{
+  GLfloat matrix[16];
+  for (int i=0; i<16; i++) matrix[i] = 0;
+  matrix[0]=1;
+  matrix[5]=1;
+  matrix[8]=-LIGHTX;
+  matrix[9]=-LIGHTY;
+  matrix[15]=1;
+  glPushMatrix();
+  glMultMatrixf (matrix);
+}
+
+static void drawConvex (float *_planes,unsigned int _planecount,
+			float *_points,
+			unsigned int _pointcount,
+			unsigned int *_polygons)
+{
+  unsigned int polyindex=0;
+  for(unsigned int i=0;i<_planecount;++i)
+    {
+      unsigned int pointcount=_polygons[polyindex];
+      polyindex++;
+      glBegin (GL_POLYGON);
+       glNormal3f(_planes[(i*4)+0],
+		  _planes[(i*4)+1],
+		  _planes[(i*4)+2]);
+      for(unsigned int j=0;j<pointcount;++j)
+	{
+	  glVertex3f(_points[_polygons[polyindex]*3],
+		     _points[(_polygons[polyindex]*3)+1],
+		     _points[(_polygons[polyindex]*3)+2]);
+	  polyindex++;
+	}
+      glEnd();
+    }
+}
+
+static void drawConvexD (double *_planes,unsigned int _planecount,
+			 double *_points,
+			 unsigned int _pointcount,
+			 unsigned int *_polygons)
+{
+  unsigned int polyindex=0;
+  for(unsigned int i=0;i<_planecount;++i)
+    {
+      unsigned int pointcount=_polygons[polyindex];
+      polyindex++;
+      glBegin (GL_POLYGON);
+      glNormal3d(_planes[(i*4)+0],
+		 _planes[(i*4)+1],
+		 _planes[(i*4)+2]);
+      for(unsigned int j=0;j<pointcount;++j)
+	{
+	  glVertex3d(_points[_polygons[polyindex]*3],
+		     _points[(_polygons[polyindex]*3)+1],
+		     _points[(_polygons[polyindex]*3)+2]);
+	  polyindex++;
+	}
+      glEnd();
+    }
+}
+
+static void drawBox (const float sides[3])
+{
+  float lx = sides[0]*0.5f;
+  float ly = sides[1]*0.5f;
+  float lz = sides[2]*0.5f;
+
+  // sides
+  glBegin (GL_TRIANGLE_STRIP);
+  glNormal3f (-1,0,0);
+  glVertex3f (-lx,-ly,-lz);
+  glVertex3f (-lx,-ly,lz);
+  glVertex3f (-lx,ly,-lz);
+  glVertex3f (-lx,ly,lz);
+  glNormal3f (0,1,0);
+  glVertex3f (lx,ly,-lz);
+  glVertex3f (lx,ly,lz);
+  glNormal3f (1,0,0);
+  glVertex3f (lx,-ly,-lz);
+  glVertex3f (lx,-ly,lz);
+  glNormal3f (0,-1,0);
+  glVertex3f (-lx,-ly,-lz);
+  glVertex3f (-lx,-ly,lz);
+  glEnd();
+
+  // top face
+  glBegin (GL_TRIANGLE_FAN);
+  glNormal3f (0,0,1);
+  glVertex3f (-lx,-ly,lz);
+  glVertex3f (lx,-ly,lz);
+  glVertex3f (lx,ly,lz);
+  glVertex3f (-lx,ly,lz);
+  glEnd();
+
+  // bottom face
+  glBegin (GL_TRIANGLE_FAN);
+  glNormal3f (0,0,-1);
+  glVertex3f (-lx,-ly,-lz);
+  glVertex3f (-lx,ly,-lz);
+  glVertex3f (lx,ly,-lz);
+  glVertex3f (lx,-ly,-lz);
+  glEnd();
+}
+
+
+// This is recursively subdivides a triangular area (vertices p1,p2,p3) into
+// smaller triangles, and then draws the triangles. All triangle vertices are
+// normalized to a distance of 1.0 from the origin (p1,p2,p3 are assumed
+// to be already normalized). Note this is not super-fast because it draws
+// triangles rather than triangle strips.
+
+static void drawPatch (float p1[3], float p2[3], float p3[3], int level)
+{
+  int i;
+  if (level > 0) {
+    float q1[3],q2[3],q3[3];		 // sub-vertices
+    for (i=0; i<3; i++) {
+      q1[i] = 0.5f*(p1[i]+p2[i]);
+      q2[i] = 0.5f*(p2[i]+p3[i]);
+      q3[i] = 0.5f*(p3[i]+p1[i]);
+    }
+    float length1 = (float)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2]));
+    float length2 = (float)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2]));
+    float length3 = (float)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2]));
+    for (i=0; i<3; i++) {
+      q1[i] *= length1;
+      q2[i] *= length2;
+      q3[i] *= length3;
+    }
+    drawPatch (p1,q1,q3,level-1);
+    drawPatch (q1,p2,q2,level-1);
+    drawPatch (q1,q2,q3,level-1);
+    drawPatch (q3,q2,p3,level-1);
+  }
+  else {
+    glNormal3f (p1[0],p1[1],p1[2]);
+    glVertex3f (p1[0],p1[1],p1[2]);
+    glNormal3f (p2[0],p2[1],p2[2]);
+    glVertex3f (p2[0],p2[1],p2[2]);
+    glNormal3f (p3[0],p3[1],p3[2]);
+    glVertex3f (p3[0],p3[1],p3[2]);
+  }
+}
+
+
+// draw a sphere of radius 1
+
+static int sphere_quality = 1;
+
+static void drawSphere()
+{
+  // icosahedron data for an icosahedron of radius 1.0
+# define ICX 0.525731112119133606f
+# define ICZ 0.850650808352039932f
+  static GLfloat idata[12][3] = {
+    {-ICX, 0, ICZ},
+    {ICX, 0, ICZ},
+    {-ICX, 0, -ICZ},
+    {ICX, 0, -ICZ},
+    {0, ICZ, ICX},
+    {0, ICZ, -ICX},
+    {0, -ICZ, ICX},
+    {0, -ICZ, -ICX},
+    {ICZ, ICX, 0},
+    {-ICZ, ICX, 0},
+    {ICZ, -ICX, 0},
+    {-ICZ, -ICX, 0}
+  };
+
+  static int index[20][3] = {
+    {0, 4, 1},	  {0, 9, 4},
+    {9, 5, 4},	  {4, 5, 8},
+    {4, 8, 1},	  {8, 10, 1},
+    {8, 3, 10},   {5, 3, 8},
+    {5, 2, 3},	  {2, 7, 3},
+    {7, 10, 3},   {7, 6, 10},
+    {7, 11, 6},   {11, 0, 6},
+    {0, 1, 6},	  {6, 1, 10},
+    {9, 0, 11},   {9, 11, 2},
+    {9, 2, 5},	  {7, 2, 11},
+  };
+
+  static GLuint listnum = 0;
+  if (listnum==0) {
+    listnum = glGenLists (1);
+    glNewList (listnum,GL_COMPILE);
+    glBegin (GL_TRIANGLES);
+    for (int i=0; i<20; i++) {
+      drawPatch (&idata[index[i][2]][0],&idata[index[i][1]][0],
+		 &idata[index[i][0]][0],sphere_quality);
+    }
+    glEnd();
+    glEndList();
+  }
+  glCallList (listnum);
+}
+
+
+static void drawSphereShadow (float px, float py, float pz, float radius)
+{
+  // calculate shadow constants based on light vector
+  static int init=0;
+  static float len2,len1,scale;
+  if (!init) {
+    len2 = LIGHTX*LIGHTX + LIGHTY*LIGHTY;
+    len1 = 1.0f/(float)sqrt(len2);
+    scale = (float) sqrt(len2 + 1);
+    init = 1;
+  }
+
+  // map sphere center to ground plane based on light vector
+  px -= LIGHTX*pz;
+  py -= LIGHTY*pz;
+
+  const float kx = 0.96592582628907f;
+  const float ky = 0.25881904510252f;
+  float x=radius, y=0;
+
+  glBegin (GL_TRIANGLE_FAN);
+  for (int i=0; i<24; i++) {
+    // for all points on circle, scale to elongated rotated shadow and draw
+    float x2 = (LIGHTX*x*scale - LIGHTY*y)*len1 + px;
+    float y2 = (LIGHTY*x*scale + LIGHTX*y)*len1 + py;
+    glTexCoord2f (x2*ground_scale+ground_ofsx,y2*ground_scale+ground_ofsy);
+    glVertex3f (x2,y2,0);
+
+    // rotate [x,y] vector
+    float xtmp = kx*x - ky*y;
+    y = ky*x + kx*y;
+    x = xtmp;
+  }
+  glEnd();
+}
+
+
+static void drawTriangle (const float *v0, const float *v1, const float *v2, int solid)
+{
+  float u[3],v[3],normal[3];
+  u[0] = v1[0] - v0[0];
+  u[1] = v1[1] - v0[1];
+  u[2] = v1[2] - v0[2];
+  v[0] = v2[0] - v0[0];
+  v[1] = v2[1] - v0[1];
+  v[2] = v2[2] - v0[2];
+  dCROSS (normal,=,u,v);
+  normalizeVector3 (normal);
+
+  glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
+  glNormal3fv (normal);
+  glVertex3fv (v0);
+  glVertex3fv (v1);
+  glVertex3fv (v2);
+  glEnd();
+}
+
+static void drawTriangleD (const double *v0, const double *v1, const double *v2, int solid)
+{
+  float u[3],v[3],normal[3];
+  u[0] = float( v1[0] - v0[0] );
+  u[1] = float( v1[1] - v0[1] );
+  u[2] = float( v1[2] - v0[2] );
+  v[0] = float( v2[0] - v0[0] );
+  v[1] = float( v2[1] - v0[1] );
+  v[2] = float( v2[2] - v0[2] );
+  dCROSS (normal,=,u,v);
+  normalizeVector3 (normal);
+
+  glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
+  glNormal3fv (normal);
+  glVertex3dv (v0);
+  glVertex3dv (v1);
+  glVertex3dv (v2);
+  glEnd();
+}
+
+
+// draw a capped cylinder of length l and radius r, aligned along the x axis
+
+static int capped_cylinder_quality = 3;
+
+static void drawCapsule (float l, float r)
+{
+  int i,j;
+  float tmp,nx,ny,nz,start_nx,start_ny,a,ca,sa;
+  // number of sides to the cylinder (divisible by 4):
+  const int n = capped_cylinder_quality*4;
+
+  l *= 0.5;
+  a = float(M_PI*2.0)/float(n);
+  sa = (float) sin(a);
+  ca = (float) cos(a);
+
+  // draw cylinder body
+  ny=1; nz=0;		  // normal vector = (0,ny,nz)
+  glBegin (GL_TRIANGLE_STRIP);
+  for (i=0; i<=n; i++) {
+    glNormal3d (ny,nz,0);
+    glVertex3d (ny*r,nz*r,l);
+    glNormal3d (ny,nz,0);
+    glVertex3d (ny*r,nz*r,-l);
+    // rotate ny,nz
+    tmp = ca*ny - sa*nz;
+    nz = sa*ny + ca*nz;
+    ny = tmp;
+  }
+  glEnd();
+
+  // draw first cylinder cap
+  start_nx = 0;
+  start_ny = 1;
+  for (j=0; j<(n/4); j++) {
+    // get start_n2 = rotated start_n
+    float start_nx2 =  ca*start_nx + sa*start_ny;
+    float start_ny2 = -sa*start_nx + ca*start_ny;
+    // get n=start_n and n2=start_n2
+    nx = start_nx; ny = start_ny; nz = 0;
+    float nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
+    glBegin (GL_TRIANGLE_STRIP);
+    for (i=0; i<=n; i++) {
+      glNormal3d (ny2,nz2,nx2);
+      glVertex3d (ny2*r,nz2*r,l+nx2*r);
+      glNormal3d (ny,nz,nx);
+      glVertex3d (ny*r,nz*r,l+nx*r);
+      // rotate n,n2
+      tmp = ca*ny - sa*nz;
+      nz = sa*ny + ca*nz;
+      ny = tmp;
+      tmp = ca*ny2- sa*nz2;
+      nz2 = sa*ny2 + ca*nz2;
+      ny2 = tmp;
+    }
+    glEnd();
+    start_nx = start_nx2;
+    start_ny = start_ny2;
+  }
+
+  // draw second cylinder cap
+  start_nx = 0;
+  start_ny = 1;
+  for (j=0; j<(n/4); j++) {
+    // get start_n2 = rotated start_n
+    float start_nx2 = ca*start_nx - sa*start_ny;
+    float start_ny2 = sa*start_nx + ca*start_ny;
+    // get n=start_n and n2=start_n2
+    nx = start_nx; ny = start_ny; nz = 0;
+    float nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
+    glBegin (GL_TRIANGLE_STRIP);
+    for (i=0; i<=n; i++) {
+      glNormal3d (ny,nz,nx);
+      glVertex3d (ny*r,nz*r,-l+nx*r);
+      glNormal3d (ny2,nz2,nx2);
+      glVertex3d (ny2*r,nz2*r,-l+nx2*r);
+      // rotate n,n2
+      tmp = ca*ny - sa*nz;
+      nz = sa*ny + ca*nz;
+      ny = tmp;
+      tmp = ca*ny2- sa*nz2;
+      nz2 = sa*ny2 + ca*nz2;
+      ny2 = tmp;
+    }
+    glEnd();
+    start_nx = start_nx2;
+    start_ny = start_ny2;
+  }
+
+  glPopMatrix();
+}
+
+
+// draw a cylinder of length l and radius r, aligned along the z axis
+
+static void drawCylinder (float l, float r, float zoffset)
+{
+  int i;
+  float tmp,ny,nz,a,ca,sa;
+  const int n = 24;	// number of sides to the cylinder (divisible by 4)
+
+  l *= 0.5;
+  a = float(M_PI*2.0)/float(n);
+  sa = (float) sin(a);
+  ca = (float) cos(a);
+
+  // draw cylinder body
+  ny=1; nz=0;		  // normal vector = (0,ny,nz)
+  glBegin (GL_TRIANGLE_STRIP);
+  for (i=0; i<=n; i++) {
+    glNormal3d (ny,nz,0);
+    glVertex3d (ny*r,nz*r,l+zoffset);
+    glNormal3d (ny,nz,0);
+    glVertex3d (ny*r,nz*r,-l+zoffset);
+    // rotate ny,nz
+    tmp = ca*ny - sa*nz;
+    nz = sa*ny + ca*nz;
+    ny = tmp;
+  }
+  glEnd();
+
+  // draw top cap
+  glShadeModel (GL_FLAT);
+  ny=1; nz=0;		  // normal vector = (0,ny,nz)
+  glBegin (GL_TRIANGLE_FAN);
+  glNormal3d (0,0,1);
+  glVertex3d (0,0,l+zoffset);
+  for (i=0; i<=n; i++) {
+    if (i==1 || i==n/2+1)
+      setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
+    glNormal3d (0,0,1);
+    glVertex3d (ny*r,nz*r,l+zoffset);
+    if (i==1 || i==n/2+1)
+      setColor (color[0],color[1],color[2],color[3]);
+
+    // rotate ny,nz
+    tmp = ca*ny - sa*nz;
+    nz = sa*ny + ca*nz;
+    ny = tmp;
+  }
+  glEnd();
+
+  // draw bottom cap
+  ny=1; nz=0;		  // normal vector = (0,ny,nz)
+  glBegin (GL_TRIANGLE_FAN);
+  glNormal3d (0,0,-1);
+  glVertex3d (0,0,-l+zoffset);
+  for (i=0; i<=n; i++) {
+    if (i==1 || i==n/2+1)
+      setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
+    glNormal3d (0,0,-1);
+    glVertex3d (ny*r,nz*r,-l+zoffset);
+    if (i==1 || i==n/2+1)
+      setColor (color[0],color[1],color[2],color[3]);
+
+    // rotate ny,nz
+    tmp = ca*ny + sa*nz;
+    nz = -sa*ny + ca*nz;
+    ny = tmp;
+  }
+  glEnd();
+}
+
+//***************************************************************************
+// motion model
+
+// current camera position and orientation
+static float view_xyz[3];	// position x,y,z
+static float view_hpr[3];	// heading, pitch, roll (degrees)
+
+
+// initialize the above variables
+
+static void initMotionModel()
+{
+  view_xyz[0] = 2;
+  view_xyz[1] = 0;
+  view_xyz[2] = 1;
+  view_hpr[0] = 180;
+  view_hpr[1] = 0;
+  view_hpr[2] = 0;
+}
+
+
+static void wrapCameraAngles()
+{
+  for (int i=0; i<3; i++) {
+    while (view_hpr[i] > 180) view_hpr[i] -= 360;
+    while (view_hpr[i] < -180) view_hpr[i] += 360;
+  }
+}
+
+
+// call this to update the current camera position. the bits in `mode' say
+// if the left (1), middle (2) or right (4) mouse button is pressed, and
+// (deltax,deltay) is the amount by which the mouse pointer has moved.
+
+void dsMotion (int mode, int deltax, int deltay)
+{
+  float side = 0.01f * float(deltax);
+  float fwd = (mode==4) ? (0.01f * float(deltay)) : 0.0f;
+  float s = (float) sin (view_hpr[0]*DEG_TO_RAD);
+  float c = (float) cos (view_hpr[0]*DEG_TO_RAD);
+
+  if (mode==1) {
+    view_hpr[0] += float (deltax) * 0.5f;
+    view_hpr[1] += float (deltay) * 0.5f;
+  }
+  else {
+    view_xyz[0] += -s*side + c*fwd;
+    view_xyz[1] += c*side + s*fwd;
+    if (mode==2 || mode==5) view_xyz[2] += 0.01f * float(deltay);
+  }
+  wrapCameraAngles();
+}
+
+//***************************************************************************
+// drawing loop stuff
+
+// the current state:
+//    0 = uninitialized
+//    1 = dsSimulationLoop() called
+//    2 = dsDrawFrame() called
+static int current_state = 0;
+
+// textures and shadows
+static int use_textures=1;		// 1 if textures to be drawn
+static int use_shadows=1;		// 1 if shadows to be drawn
+static Texture *sky_texture = 0;
+static Texture *ground_texture = 0;
+static Texture *wood_texture = 0;
+
+
+#ifndef macintosh
+
+void dsStartGraphics (int width, int height, dsFunctions *fn)
+{
+  char *prefix = DEFAULT_PATH_TO_TEXTURES;
+  if (fn->version >= 2 && fn->path_to_textures) prefix = fn->path_to_textures;
+  char *s = (char*) alloca (strlen(prefix) + 20);
+
+  strcpy (s,prefix);
+  strcat (s,"/sky.ppm");
+  sky_texture = new Texture (s);
+
+  strcpy (s,prefix);
+  strcat (s,"/ground.ppm");
+  ground_texture = new Texture (s);
+
+  strcpy (s,prefix);
+  strcat (s,"/wood.ppm");
+  wood_texture = new Texture (s);
+}
+
+#else // macintosh
+
+void dsStartGraphics (int width, int height, dsFunctions *fn)
+{
+   // All examples build into the same dir
+   char *prefix = "::::drawstuff:textures";
+   char *s = (char*) alloca (strlen(prefix) + 20);
+
+   strcpy (s,prefix);
+   strcat (s,":sky.ppm");
+   sky_texture = new Texture (s);
+
+   strcpy (s,prefix);
+   strcat (s,":ground.ppm");
+   ground_texture = new Texture (s);
+
+   strcpy (s,prefix);
+   strcat (s,":wood.ppm");
+   wood_texture = new Texture (s);
+}
+
+#endif
+
+
+void dsStopGraphics()
+{
+  delete sky_texture;
+  delete ground_texture;
+  delete wood_texture;
+  sky_texture = 0;
+  ground_texture = 0;
+  wood_texture = 0;
+}
+
+
+static void drawSky (float view_xyz[3])
+{
+  glDisable (GL_LIGHTING);
+  if (use_textures) {
+    glEnable (GL_TEXTURE_2D);
+    sky_texture->bind (0);
+  }
+  else {
+    glDisable (GL_TEXTURE_2D);
+    glColor3f (0,0.5,1.0);
+  }
+
+  // make sure sky depth is as far back as possible
+  glShadeModel (GL_FLAT);
+  glEnable (GL_DEPTH_TEST);
+  glDepthFunc (GL_LEQUAL);
+  glDepthRange (1,1);
+
+  const float ssize = 1000.0f;
+  static float offset = 0.0f;
+
+  float x = ssize*sky_scale;
+  float z = view_xyz[2] + sky_height;
+
+  glBegin (GL_QUADS);
+  glNormal3f (0,0,-1);
+  glTexCoord2f (-x+offset,-x+offset);
+  glVertex3f (-ssize+view_xyz[0],-ssize+view_xyz[1],z);
+  glTexCoord2f (-x+offset,x+offset);
+  glVertex3f (-ssize+view_xyz[0],ssize+view_xyz[1],z);
+  glTexCoord2f (x+offset,x+offset);
+  glVertex3f (ssize+view_xyz[0],ssize+view_xyz[1],z);
+  glTexCoord2f (x+offset,-x+offset);
+  glVertex3f (ssize+view_xyz[0],-ssize+view_xyz[1],z);
+  glEnd();
+
+  offset = offset + 0.002f;
+  if (offset > 1) offset -= 1;
+
+  glDepthFunc (GL_LESS);
+  glDepthRange (0,1);
+}
+
+
+static void drawGround()
+{
+  glDisable (GL_LIGHTING);
+  glShadeModel (GL_FLAT);
+  glEnable (GL_DEPTH_TEST);
+  glDepthFunc (GL_LESS);
+  // glDepthRange (1,1);
+
+  if (use_textures) {
+    glEnable (GL_TEXTURE_2D);
+    ground_texture->bind (0);
+  }
+  else {
+    glDisable (GL_TEXTURE_2D);
+    glColor3f (GROUND_R,GROUND_G,GROUND_B);
+  }
+
+  // ground fog seems to cause problems with TNT2 under windows
+  /*
+  GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1};
+  glEnable (GL_FOG);
+  glFogi (GL_FOG_MODE, GL_EXP2);
+  glFogfv (GL_FOG_COLOR, fogColor);
+  glFogf (GL_FOG_DENSITY, 0.05f);
+  glHint (GL_FOG_HINT, GL_NICEST); // GL_DONT_CARE);
+  glFogf (GL_FOG_START, 1.0);
+  glFogf (GL_FOG_END, 5.0);
+  */
+
+  const float gsize = 100.0f;
+  const float offset = 0; // -0.001f; ... polygon offsetting doesn't work well
+
+  glBegin (GL_QUADS);
+  glNormal3f (0,0,1);
+  glTexCoord2f (-gsize*ground_scale + ground_ofsx,
+		-gsize*ground_scale + ground_ofsy);
+  glVertex3f (-gsize,-gsize,offset);
+  glTexCoord2f (gsize*ground_scale + ground_ofsx,
+		-gsize*ground_scale + ground_ofsy);
+  glVertex3f (gsize,-gsize,offset);
+  glTexCoord2f (gsize*ground_scale + ground_ofsx,
+		gsize*ground_scale + ground_ofsy);
+  glVertex3f (gsize,gsize,offset);
+  glTexCoord2f (-gsize*ground_scale + ground_ofsx,
+		gsize*ground_scale + ground_ofsy);
+  glVertex3f (-gsize,gsize,offset);
+  glEnd();
+
+  glDisable (GL_FOG);
+}
+
+
+static void drawPyramidGrid()
+{
+  // setup stuff
+  glEnable (GL_LIGHTING);
+  glDisable (GL_TEXTURE_2D);
+  glShadeModel (GL_FLAT);
+  glEnable (GL_DEPTH_TEST);
+  glDepthFunc (GL_LESS);
+
+  // draw the pyramid grid
+  for (int i=-1; i<=1; i++) {
+    for (int j=-1; j<=1; j++) {
+      glPushMatrix();
+      glTranslatef ((float)i,(float)j,(float)0);
+      if (i==1 && j==0) setColor (1,0,0,1);
+      else if (i==0 && j==1) setColor (0,0,1,1);
+      else setColor (1,1,0,1);
+      const float k = 0.03f;
+      glBegin (GL_TRIANGLE_FAN);
+      glNormal3f (0,-1,1);
+      glVertex3f (0,0,k);
+      glVertex3f (-k,-k,0);
+      glVertex3f ( k,-k,0);
+      glNormal3f (1,0,1);
+      glVertex3f ( k, k,0);
+      glNormal3f (0,1,1);
+      glVertex3f (-k, k,0);
+      glNormal3f (-1,0,1);
+      glVertex3f (-k,-k,0);
+      glEnd();
+      glPopMatrix();
+    }
+  }
+}
+
+
+void dsDrawFrame (int width, int height, dsFunctions *fn, int pause)
+{
+  if (current_state < 1) dsDebug ("internal error");
+  current_state = 2;
+
+  // setup stuff
+  glEnable (GL_LIGHTING);
+  glEnable (GL_LIGHT0);
+  glDisable (GL_TEXTURE_2D);
+  glDisable (GL_TEXTURE_GEN_S);
+  glDisable (GL_TEXTURE_GEN_T);
+  glShadeModel (GL_FLAT);
+  glEnable (GL_DEPTH_TEST);
+  glDepthFunc (GL_LESS);
+  glEnable (GL_CULL_FACE);
+  glCullFace (GL_BACK);
+  glFrontFace (GL_CCW);
+
+  // setup viewport
+  glViewport (0,0,width,height);
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity();
+  const float vnear = 0.1f;
+  const float vfar = 100.0f;
+  const float k = 0.8f;     // view scale, 1 = +/- 45 degrees
+  if (width >= height) {
+    float k2 = float(height)/float(width);
+    glFrustum (-vnear*k,vnear*k,-vnear*k*k2,vnear*k*k2,vnear,vfar);
+  }
+  else {
+    float k2 = float(width)/float(height);
+    glFrustum (-vnear*k*k2,vnear*k*k2,-vnear*k,vnear*k,vnear,vfar);
+  }
+
+  // setup lights. it makes a difference whether this is done in the
+  // GL_PROJECTION matrix mode (lights are scene relative) or the
+  // GL_MODELVIEW matrix mode (lights are camera relative, bad!).
+  static GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
+  static GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
+  static GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+  glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
+  glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+  glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
+  glColor3f (1.0, 1.0, 1.0);
+
+  // clear the window
+  glClearColor (0.5,0.5,0.5,0);
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  // snapshot camera position (in MS Windows it is changed by the GUI thread)
+  float view2_xyz[3];
+  float view2_hpr[3];
+  memcpy (view2_xyz,view_xyz,sizeof(float)*3);
+  memcpy (view2_hpr,view_hpr,sizeof(float)*3);
+
+  // go to GL_MODELVIEW matrix mode and set the camera
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity();
+  setCamera (view2_xyz[0],view2_xyz[1],view2_xyz[2],
+	     view2_hpr[0],view2_hpr[1],view2_hpr[2]);
+
+  // set the light position (for some reason we have to do this in model view.
+  static GLfloat light_position[] = { LIGHTX, LIGHTY, 1.0, 0.0 };
+  glLightfv (GL_LIGHT0, GL_POSITION, light_position);
+
+  // draw the background (ground, sky etc)
+  drawSky (view2_xyz);
+  drawGround();
+
+  // draw the little markers on the ground
+  drawPyramidGrid();
+
+  // leave openGL in a known state - flat shaded white, no textures
+  glEnable (GL_LIGHTING);
+  glDisable (GL_TEXTURE_2D);
+  glShadeModel (GL_FLAT);
+  glEnable (GL_DEPTH_TEST);
+  glDepthFunc (GL_LESS);
+  glColor3f (1,1,1);
+  setColor (1,1,1,1);
+
+  // draw the rest of the objects. set drawing state first.
+  color[0] = 1;
+  color[1] = 1;
+  color[2] = 1;
+  color[3] = 1;
+  tnum = 0;
+  if (fn->step) fn->step (pause);
+}
+
+
+int dsGetShadows()
+{
+  return use_shadows;
+}
+
+
+void dsSetShadows (int a)
+{
+  use_shadows = (a != 0);
+}
+
+
+int dsGetTextures()
+{
+  return use_textures;
+}
+
+
+void dsSetTextures (int a)
+{
+  use_textures = (a != 0);
+}
+
+//***************************************************************************
+// C interface
+
+// sets lighting and texture modes, sets current color
+static void setupDrawingMode()
+{
+  glEnable (GL_LIGHTING);
+  if (tnum) {
+    if (use_textures) {
+      glEnable (GL_TEXTURE_2D);
+      wood_texture->bind (1);
+      glEnable (GL_TEXTURE_GEN_S);
+      glEnable (GL_TEXTURE_GEN_T);
+      glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
+      glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
+      static GLfloat s_params[4] = {1.0f,1.0f,0.0f,1};
+      static GLfloat t_params[4] = {0.817f,-0.817f,0.817f,1};
+      glTexGenfv (GL_S,GL_OBJECT_PLANE,s_params);
+      glTexGenfv (GL_T,GL_OBJECT_PLANE,t_params);
+    }
+    else {
+      glDisable (GL_TEXTURE_2D);
+    }
+  }
+  else {
+    glDisable (GL_TEXTURE_2D);
+  }
+  setColor (color[0],color[1],color[2],color[3]);
+
+  if (color[3] < 1) {
+    glEnable (GL_BLEND);
+    glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+  }
+  else {
+    glDisable (GL_BLEND);
+  }
+}
+
+
+static void setShadowDrawingMode()
+{
+  glDisable (GL_LIGHTING);
+  if (use_textures) {
+    glEnable (GL_TEXTURE_2D);
+    ground_texture->bind (1);
+    glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
+    glEnable (GL_TEXTURE_2D);
+    glEnable (GL_TEXTURE_GEN_S);
+    glEnable (GL_TEXTURE_GEN_T);
+    glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
+    glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
+    static GLfloat s_params[4] = {ground_scale,0,0,ground_ofsx};
+    static GLfloat t_params[4] = {0,ground_scale,0,ground_ofsy};
+    glTexGenfv (GL_S,GL_EYE_PLANE,s_params);
+    glTexGenfv (GL_T,GL_EYE_PLANE,t_params);
+  }
+  else {
+    glDisable (GL_TEXTURE_2D);
+    glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
+	       GROUND_B*SHADOW_INTENSITY);
+  }
+  glDepthRange (0,0.9999);
+}
+
+
+extern "C" void dsSimulationLoop (int argc, char **argv,
+				  int window_width, int window_height,
+				  dsFunctions *fn)
+{
+  if (current_state != 0) dsError ("dsSimulationLoop() called more than once");
+  current_state = 1;
+
+  // look for flags that apply to us
+  int initial_pause = 0;
+  for (int i=1; i<argc; i++) {
+    if (strcmp(argv[i],"-notex")==0) use_textures = 0;
+    if (strcmp(argv[i],"-noshadow")==0) use_shadows = 0;
+    if (strcmp(argv[i],"-noshadows")==0) use_shadows = 0;
+    if (strcmp(argv[i],"-pause")==0) initial_pause = 1;
+  }
+
+  if (fn->version > DS_VERSION)
+    dsDebug ("bad version number in dsFunctions structure");
+
+  initMotionModel();
+  dsPlatformSimLoop (window_width,window_height,fn,initial_pause);
+
+  current_state = 0;
+}
+
+
+extern "C" void dsSetViewpoint (float xyz[3], float hpr[3])
+{
+  if (current_state < 1) dsError ("dsSetViewpoint() called before simulation started");
+  if (xyz) {
+    view_xyz[0] = xyz[0];
+    view_xyz[1] = xyz[1];
+    view_xyz[2] = xyz[2];
+  }
+  if (hpr) {
+    view_hpr[0] = hpr[0];
+    view_hpr[1] = hpr[1];
+    view_hpr[2] = hpr[2];
+    wrapCameraAngles();
+  }
+}
+
+
+extern "C" void dsGetViewpoint (float xyz[3], float hpr[3])
+{
+  if (current_state < 1) dsError ("dsGetViewpoint() called before simulation started");
+  if (xyz) {
+    xyz[0] = view_xyz[0];
+    xyz[1] = view_xyz[1];
+    xyz[2] = view_xyz[2];
+  }
+  if (hpr) {
+    hpr[0] = view_hpr[0];
+    hpr[1] = view_hpr[1];
+    hpr[2] = view_hpr[2];
+  }
+}
+
+
+extern "C" void dsSetTexture (int texture_number)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  tnum = texture_number;
+}
+
+
+extern "C" void dsSetColor (float red, float green, float blue)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  color[0] = red;
+  color[1] = green;
+  color[2] = blue;
+  color[3] = 1;
+}
+
+
+extern "C" void dsSetColorAlpha (float red, float green, float blue,
+				 float alpha)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  color[0] = red;
+  color[1] = green;
+  color[2] = blue;
+  color[3] = alpha;
+}
+
+
+extern "C" void dsDrawBox (const float pos[3], const float R[12],
+			   const float sides[3])
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glShadeModel (GL_FLAT);
+  setTransform (pos,R);
+  drawBox (sides);
+  glPopMatrix();
+
+  if (use_shadows) {
+    setShadowDrawingMode();
+    setShadowTransform();
+    setTransform (pos,R);
+    drawBox (sides);
+    glPopMatrix();
+    glPopMatrix();
+    glDepthRange (0,1);
+  }
+}
+
+extern "C" void dsDrawConvex (const float pos[3], const float R[12],
+			      float *_planes,unsigned int _planecount,
+			      float *_points,
+			      unsigned int _pointcount,
+			      unsigned int *_polygons)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glShadeModel (GL_FLAT);
+  setTransform (pos,R);
+  drawConvex(_planes,_planecount,_points,_pointcount,_polygons);
+  glPopMatrix();
+  if (use_shadows) {
+    setShadowDrawingMode();
+    setShadowTransform();
+    setTransform (pos,R);
+    drawConvex(_planes,_planecount,_points,_pointcount,_polygons);
+    glPopMatrix();
+    glPopMatrix();
+    glDepthRange (0,1);
+  }
+}
+
+
+extern "C" void dsDrawSphere (const float pos[3], const float R[12],
+			      float radius)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glEnable (GL_NORMALIZE);
+  glShadeModel (GL_SMOOTH);
+  setTransform (pos,R);
+  glScaled (radius,radius,radius);
+  drawSphere();
+  glPopMatrix();
+  glDisable (GL_NORMALIZE);
+
+  // draw shadows
+  if (use_shadows) {
+    glDisable (GL_LIGHTING);
+    if (use_textures) {
+      ground_texture->bind (1);
+      glEnable (GL_TEXTURE_2D);
+      glDisable (GL_TEXTURE_GEN_S);
+      glDisable (GL_TEXTURE_GEN_T);
+      glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
+    }
+    else {
+      glDisable (GL_TEXTURE_2D);
+      glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
+		 GROUND_B*SHADOW_INTENSITY);
+    }
+    glShadeModel (GL_FLAT);
+    glDepthRange (0,0.9999);
+    drawSphereShadow (pos[0],pos[1],pos[2],radius);
+    glDepthRange (0,1);
+  }
+}
+
+
+extern "C" void dsDrawTriangle (const float pos[3], const float R[12],
+				const float *v0, const float *v1,
+				const float *v2, int solid)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glShadeModel (GL_FLAT);
+  setTransform (pos,R);
+  drawTriangle (v0, v1, v2, solid);
+  glPopMatrix();
+}
+
+
+extern "C" void dsDrawCylinder (const float pos[3], const float R[12],
+				float length, float radius)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glShadeModel (GL_SMOOTH);
+  setTransform (pos,R);
+  drawCylinder (length,radius,0);
+  glPopMatrix();
+
+  if (use_shadows) {
+    setShadowDrawingMode();
+    setShadowTransform();
+    setTransform (pos,R);
+    drawCylinder (length,radius,0);
+    glPopMatrix();
+    glPopMatrix();
+    glDepthRange (0,1);
+  }
+}
+
+
+extern "C" void dsDrawCapsule (const float pos[3], const float R[12],
+				      float length, float radius)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glShadeModel (GL_SMOOTH);
+  setTransform (pos,R);
+  drawCapsule (length,radius);
+  glPopMatrix();
+
+  if (use_shadows) {
+    setShadowDrawingMode();
+    setShadowTransform();
+    setTransform (pos,R);
+    drawCapsule (length,radius);
+    glPopMatrix();
+    glPopMatrix();
+    glDepthRange (0,1);
+  }
+}
+
+
+void dsDrawLine (const float pos1[3], const float pos2[3])
+{
+  setupDrawingMode();
+  glColor3f (color[0],color[1],color[2]);
+  glDisable (GL_LIGHTING);
+  glLineWidth (2);
+  glShadeModel (GL_FLAT);
+  glBegin (GL_LINES);
+  glVertex3f (pos1[0],pos1[1],pos1[2]);
+  glVertex3f (pos2[0],pos2[1],pos2[2]);
+  glEnd();
+}
+
+
+void dsDrawBoxD (const double pos[3], const double R[12],
+		 const double sides[3])
+{
+  int i;
+  float pos2[3],R2[12],fsides[3];
+  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
+  for (i=0; i<12; i++) R2[i]=(float)R[i];
+  for (i=0; i<3; i++) fsides[i]=(float)sides[i];
+  dsDrawBox (pos2,R2,fsides);
+}
+
+extern "C" void dsDrawConvexD (const double pos[3], const double R[12],
+			       double *_planes,unsigned int _planecount,
+			       double *_points,
+			       unsigned int _pointcount,
+			       unsigned int *_polygons)
+{
+  if (current_state != 2) dsError ("drawing function called outside simulation loop");
+  setupDrawingMode();
+  glShadeModel (GL_FLAT);
+  setTransformD (pos,R);
+  drawConvexD(_planes,_planecount,_points,_pointcount,_polygons);
+  glPopMatrix();
+  if (use_shadows) {
+    setShadowDrawingMode();
+    setShadowTransform();
+    setTransformD (pos,R);
+    drawConvexD(_planes,_planecount,_points,_pointcount,_polygons);
+    glPopMatrix();
+    glPopMatrix();
+    glDepthRange (0,1);
+  }
+}
+
+void dsDrawSphereD (const double pos[3], const double R[12], float radius)
+{
+  int i;
+  float pos2[3],R2[12];
+  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
+  for (i=0; i<12; i++) R2[i]=(float)R[i];
+  dsDrawSphere (pos2,R2,radius);
+}
+
+
+void dsDrawTriangleD (const double pos[3], const double R[12],
+				 const double *v0, const double *v1,
+				 const double *v2, int solid)
+{
+  int i;
+  float pos2[3],R2[12];
+  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
+  for (i=0; i<12; i++) R2[i]=(float)R[i];
+
+  setupDrawingMode();
+  glShadeModel (GL_FLAT);
+  setTransform (pos2,R2);
+  drawTriangleD (v0, v1, v2, solid);
+  glPopMatrix();
+}
+
+
+void dsDrawCylinderD (const double pos[3], const double R[12],
+		      float length, float radius)
+{
+  int i;
+  float pos2[3],R2[12];
+  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
+  for (i=0; i<12; i++) R2[i]=(float)R[i];
+  dsDrawCylinder (pos2,R2,length,radius);
+}
+
+
+void dsDrawCapsuleD (const double pos[3], const double R[12],
+			    float length, float radius)
+{
+  int i;
+  float pos2[3],R2[12];
+  for (i=0; i<3; i++) pos2[i]=(float)pos[i];
+  for (i=0; i<12; i++) R2[i]=(float)R[i];
+  dsDrawCapsule (pos2,R2,length,radius);
+}
+
+
+void dsDrawLineD (const double _pos1[3], const double _pos2[3])
+{
+  int i;
+  float pos1[3],pos2[3];
+  for (i=0; i<3; i++) pos1[i]=(float)_pos1[i];
+  for (i=0; i<3; i++) pos2[i]=(float)_pos2[i];
+  dsDrawLine (pos1,pos2);
+}
+
+
+void dsSetSphereQuality (int n)
+{
+  sphere_quality = n;
+}
+
+
+void dsSetCapsuleQuality (int n)
+{
+  capped_cylinder_quality = n;
+}
Index: /code/branches/ode/ode-0.9/drawstuff/src/internal.h
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/internal.h	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/internal.h	(revision 216)
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* functions supplied and used by the platform specific code */
+
+#ifndef __DS_INTERNAL_H
+#define __DS_INTERNAL_H
+
+#include "drawstuff/drawstuff.h"
+
+
+// supplied by platform specific code
+
+void dsPlatformSimLoop (int window_width, int window_height,
+			dsFunctions *fn, int initial_pause);
+
+
+// used by platform specific code
+
+void dsStartGraphics (int width, int height, dsFunctions *fn);
+void dsDrawFrame (int width, int height, dsFunctions *fn, int pause);
+void dsStopGraphics();
+void dsMotion (int mode, int deltax, int deltay);
+
+int dsGetShadows();
+void dsSetShadows (int a);
+
+int dsGetTextures();
+void dsSetTextures (int a);
+
+#endif
Index: /code/branches/ode/ode-0.9/drawstuff/src/osx.cpp
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/osx.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/osx.cpp	(revision 216)
@@ -0,0 +1,542 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// Platform-specific code for Mac OS X using Carbon+AGL
+//
+// Created using x11.cpp and the window-initialization -routines from GLFW
+// as reference.
+// Not thoroughly tested and is certain to contain deficiencies and bugs
+
+#include <ode/config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <drawstuff/drawstuff.h>
+#include <drawstuff/version.h>
+#include "internal.h"
+
+#include <Carbon/Carbon.h>
+#include <AGL/agl.h>
+
+// Global variables
+
+static bool running = true;			// 1 if simulation running
+static bool paused = false;			// 1 if in `pause' mode
+static bool singlestep = false;		// 1 if single step key pressed
+static bool writeframes = false;	// 1 if frame files to be written
+
+static int					   	windowWidth = -1;
+static int					   	windowHeight = -1;
+static UInt32 					modifierMask = 0;
+static int 						mouseButtonMode = 0;	
+static bool						mouseWithOption = false;	// Set if dragging the mouse with alt pressed
+static bool						mouseWithControl = false;	// Set if dragging the mouse with ctrl pressed
+
+static dsFunctions*			   	functions = NULL;
+static WindowRef               	windowReference;
+static AGLContext              	aglContext;
+
+static EventHandlerUPP         	mouseUPP = NULL;
+static EventHandlerUPP         	keyboardUPP = NULL;
+static EventHandlerUPP         	windowUPP = NULL;
+
+// Describes the window-events we are interested in
+EventTypeSpec OSX_WINDOW_EVENT_TYPES[] = {		
+	{ kEventClassWindow, kEventWindowBoundsChanged },
+	{ kEventClassWindow, kEventWindowClose },
+	{ kEventClassWindow, kEventWindowDrawContent }
+};
+
+// Describes the mouse-events we are interested in
+EventTypeSpec OSX_MOUSE_EVENT_TYPES[] = {		
+	{ kEventClassMouse, kEventMouseDown },
+	{ kEventClassMouse, kEventMouseUp },
+	{ kEventClassMouse, kEventMouseMoved },
+	{ kEventClassMouse, kEventMouseDragged }
+};
+
+// Describes the key-events we are interested in
+EventTypeSpec OSX_KEY_EVENT_TYPES[] = {		
+	{ kEventClassKeyboard, kEventRawKeyDown },
+//	{ kEventClassKeyboard, kEventRawKeyUp },
+	{ kEventClassKeyboard, kEventRawKeyModifiersChanged }
+};	
+
+//***************************************************************************
+// error handling for unix
+
+static void printMessage (char *msg1, char *msg2, va_list ap)
+{
+  fflush (stderr);
+  fflush (stdout);
+  fprintf (stderr,"\n%s: ",msg1);
+  vfprintf (stderr,msg2,ap);
+  fprintf (stderr,"\n");
+  fflush (stderr);
+}
+
+extern "C" void dsError (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  printMessage ("Error",msg,ap);
+  exit (1);
+}
+
+
+extern "C" void dsDebug (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  printMessage ("INTERNAL ERROR",msg,ap);
+  // *((char *)0) = 0;	 ... commit SEGVicide ?
+  abort();
+}
+
+extern "C" void dsPrint (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  vprintf (msg,ap);
+}
+
+static void captureFrame( int num ){
+
+  	fprintf( stderr,"\rcapturing frame %04d", num );
+	unsigned char buffer[windowWidth*windowHeight][3];
+	glReadPixels( 0, 0, windowWidth, windowHeight, GL_RGB, GL_UNSIGNED_BYTE, &buffer );
+	char s[100];
+	sprintf (s,"frame%04d.ppm",num);
+	FILE *f = fopen (s,"wb");
+	if( !f ){
+		dsError( "can't open \"%s\" for writing", s );
+	}
+	fprintf( f,"P6\n%d %d\n255\n", windowWidth, windowHeight );
+	for( int y=windowHeight-1; y>-1; y-- ){
+		fwrite( buffer[y*windowWidth], 3*windowWidth, 1, f );
+	}
+	fclose (f);	
+}
+
+extern "C" void dsStop(){
+	
+  running = false;
+}
+
+extern "C" double dsElapsedTime()
+{
+#if HAVE_GETTIMEOFDAY
+  static double prev=0.0;
+  timeval tv ;
+
+  gettimeofday(&tv, 0);
+  double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
+  if (!prev)
+    prev=curr;
+  double retval = curr-prev;
+  prev=curr;
+  if (retval>1.0) retval=1.0;
+  if (retval<dEpsilon) retval=dEpsilon;
+  return retval;
+#else
+  return 0.01666; // Assume 60 fps
+#endif
+}
+
+OSStatus osxKeyEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ){
+	
+	UInt32 keyCode;
+	UInt32 state = 0;
+	void* KCHR = NULL;
+	char charCode = 0;
+	char uppercase = 0;
+	
+    switch( GetEventKind( event ) ){
+        case kEventRawKeyDown:
+			if( GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof( UInt32 ), NULL, &keyCode ) != noErr ){
+				break;														
+			}
+			KCHR = (void *)GetScriptVariable( smCurrentScript, smKCHRCache );
+			charCode = (char)KeyTranslate( KCHR, keyCode, &state );
+			uppercase = charCode;			
+			UppercaseText( &uppercase, 1, smSystemScript );
+			//printf( "Character %d [%c] [%c] modifiers [%d]\n", charCode, charCode, uppercase, modifierMask );
+			
+			if( modifierMask == 0 ){
+				if( charCode >= ' ' && charCode <= 126 && functions -> command ){
+					functions -> command( charCode );	
+				}
+			}
+			else if( ( modifierMask & controlKey ) ){
+				// ctrl+key was pressed
+				switch(uppercase ){
+					case 'T':
+						dsSetTextures( !dsGetTextures() );
+					break;
+					case 'S':
+						dsSetShadows( !dsGetShadows() );
+					break;
+					case 'X':
+						running = false;
+					break;
+					case 'P':
+						paused = !paused;
+						singlestep = false;
+					break;
+					case 'O':
+						if( paused ){
+							singlestep = true;
+						}
+					break;
+					case 'V': {
+						float xyz[3],hpr[3];
+						dsGetViewpoint( xyz,hpr );
+						printf( "Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n", xyz[0], xyz[1], xyz[2], hpr[0], hpr[1], hpr[2] );
+					break;
+					}
+					case 'W':						
+						writeframes = !writeframes;
+						if( writeframes ){
+							printf( "Now writing frames to PPM files\n" );
+						}						 
+					break;
+				}
+				
+			}			
+		return noErr;
+        case kEventRawKeyModifiersChanged:
+			if( GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof( UInt32 ), NULL, &modifierMask ) == noErr ){
+				if( ( mouseWithOption && !( modifierMask & optionKey ) ) || ( mouseWithControl && !( modifierMask & controlKey ) ) ){
+					// The mouse was being dragged using either the command-key or the option-key modifier to emulate 
+					// the right button or both left + right.
+					// Now the modifier-key has been released so the mouseButtonMode must be changed accordingly
+					// The following releases the right-button.
+					mouseButtonMode &= (~4);
+					mouseWithOption = false;
+					mouseWithControl = false;
+				}
+				return noErr;
+			}
+		break;		
+    }	
+    return eventNotHandledErr;
+}
+
+OSStatus osxMouseEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ){
+	
+	bool buttonDown = false;	
+	HIPoint mouseLocation;
+
+    switch( GetEventKind( event ) ){
+		
+        case kEventMouseDown:
+			buttonDown = true;
+        case kEventMouseUp:
+			if( GetEventParameter( event, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof( HIPoint ), NULL, &mouseLocation ) != noErr ){
+				break;			
+			}				
+			EventMouseButton button;
+			if( GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof( EventMouseButton ), NULL, &button ) == noErr ){
+				
+				if( button == kEventMouseButtonPrimary ){					
+					if( modifierMask & controlKey ){
+						// Ctrl+button == right
+						button = kEventMouseButtonSecondary;
+						mouseWithControl = true;
+					}	
+					else if( modifierMask & optionKey ){
+						// Alt+button == left+right
+						mouseButtonMode = 5;
+						mouseWithOption = true;
+						return noErr;
+					}
+				}
+				if( buttonDown ){
+					if( button == kEventMouseButtonPrimary ) mouseButtonMode |= 1;		// Left
+					if( button == kEventMouseButtonTertiary ) mouseButtonMode |= 2;	// Middle				
+					if( button == kEventMouseButtonSecondary ) mouseButtonMode |= 4;	// Right
+				}
+				else{
+					if( button == kEventMouseButtonPrimary ) mouseButtonMode &= (~1);	// Left
+					if( button == kEventMouseButtonTertiary ) mouseButtonMode &= (~2);	// Middle									
+					if( button == kEventMouseButtonSecondary ) mouseButtonMode &= (~4);// Right
+				}		
+				return noErr;
+			}
+		break;
+        case kEventMouseMoved:
+			// NO-OP
+			return noErr;
+        case kEventMouseDragged:
+			// Carbon provides mouse-position deltas, so we don't have to store the old state ourselves
+			if( GetEventParameter( event, kEventParamMouseDelta, typeHIPoint, NULL, sizeof( HIPoint ), NULL, &mouseLocation ) == noErr ){
+				//printf( "Mode %d\n", mouseButtonMode );
+				dsMotion( mouseButtonMode, (int)mouseLocation.x, (int)mouseLocation.y );
+				return noErr;
+			}
+        break;
+        case kEventMouseWheelMoved:
+			// NO-OP
+		break;
+    }	
+    return eventNotHandledErr;
+}
+
+static void osxCloseMainWindow(){
+	
+	if( windowUPP != NULL ){
+		DisposeEventHandlerUPP( windowUPP );
+		windowUPP = NULL;
+	}
+	
+	if( aglContext != NULL ){
+		aglSetCurrentContext( NULL );
+		aglSetDrawable( aglContext, NULL );
+		aglDestroyContext( aglContext );
+		aglContext = NULL;
+	}
+	
+	if( windowReference != NULL ){
+		ReleaseWindow( windowReference );
+		windowReference = NULL;
+	}
+}
+
+OSStatus osxWindowEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ){
+	
+	//printf( "WindowEvent\n" );
+	switch( GetEventKind(event) ){
+    	case kEventWindowBoundsChanged:
+      		WindowRef window;
+      		GetEventParameter( event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window );
+      		Rect rect;
+      		GetWindowPortBounds( window, &rect );			
+			windowWidth = rect.right;
+			windowHeight = rect.bottom;
+			aglUpdateContext( aglContext );
+		break;			
+    	case kEventWindowClose:
+			osxCloseMainWindow();
+			exit( 0 );
+		return noErr;			
+    	case kEventWindowDrawContent:
+			// NO-OP
+		break;
+  	}
+	
+  	return eventNotHandledErr;
+}
+
+static void osxCreateMainWindow( int width, int height ){
+	
+	int redbits = 4;
+	int greenbits = 4;
+	int bluebits = 4;
+	int alphabits = 4;
+	int depthbits = 16;
+	
+    OSStatus error;
+		
+    // create pixel format attribute list
+	
+    GLint pixelFormatAttributes[256];
+    int numAttrs = 0;
+	
+    pixelFormatAttributes[numAttrs++] = AGL_RGBA;
+    pixelFormatAttributes[numAttrs++] = AGL_DOUBLEBUFFER;
+
+    pixelFormatAttributes[numAttrs++] = AGL_RED_SIZE;
+	pixelFormatAttributes[numAttrs++] = redbits;
+    pixelFormatAttributes[numAttrs++] = AGL_GREEN_SIZE;
+	pixelFormatAttributes[numAttrs++] = greenbits;
+    pixelFormatAttributes[numAttrs++] = AGL_BLUE_SIZE;        
+	pixelFormatAttributes[numAttrs++] = bluebits;
+	pixelFormatAttributes[numAttrs++] = AGL_ALPHA_SIZE;       
+	pixelFormatAttributes[numAttrs++] = alphabits;
+	pixelFormatAttributes[numAttrs++] = AGL_DEPTH_SIZE;       
+	pixelFormatAttributes[numAttrs++] = depthbits;
+
+    pixelFormatAttributes[numAttrs++] = AGL_NONE;
+	
+    // create pixel format.
+	
+    AGLDevice mainMonitor = GetMainDevice();
+    AGLPixelFormat pixelFormat = aglChoosePixelFormat( &mainMonitor, 1, pixelFormatAttributes );
+    if( pixelFormat == NULL ){
+        return;
+    }
+		
+    aglContext = aglCreateContext( pixelFormat, NULL );
+	
+    aglDestroyPixelFormat( pixelFormat );
+	
+    if( aglContext == NULL ){
+        osxCloseMainWindow();
+		return;
+    }
+	
+    Rect windowContentBounds;
+    windowContentBounds.left = 0;
+    windowContentBounds.top = 0;
+    windowContentBounds.right = width;
+    windowContentBounds.bottom = height;
+	
+	int windowAttributes = kWindowCloseBoxAttribute  
+		| kWindowFullZoomAttribute
+		| kWindowCollapseBoxAttribute 
+	 	| kWindowResizableAttribute 
+	 	| kWindowStandardHandlerAttribute
+		| kWindowLiveResizeAttribute;
+	
+    error = CreateNewWindow( kDocumentWindowClass, windowAttributes, &windowContentBounds, &windowReference );
+    if( ( error != noErr ) || ( windowReference == NULL ) ){
+        osxCloseMainWindow();
+		return;
+    }
+	
+	windowUPP = NewEventHandlerUPP( osxWindowEventHandler );
+		
+	error = InstallWindowEventHandler( windowReference, windowUPP,GetEventTypeCount( OSX_WINDOW_EVENT_TYPES ), OSX_WINDOW_EVENT_TYPES, NULL, NULL );
+	if( error != noErr ){
+		osxCloseMainWindow();
+		return;
+	}
+	
+	// The process-type must be changed for a ForegroundApplication
+	// Unless it is a foreground-process, the application will not show in the dock or expose and the window
+	// will not behave properly.
+	ProcessSerialNumber currentProcess;
+	GetCurrentProcess( &currentProcess );
+	TransformProcessType( &currentProcess, kProcessTransformToForegroundApplication );
+	SetFrontProcess( &currentProcess );
+	
+    SetWindowTitleWithCFString( windowReference, CFSTR( "ODE - Drawstuff" ) );
+    RepositionWindow( windowReference, NULL, kWindowCenterOnMainScreen );
+	
+    ShowWindow( windowReference );
+	
+	if( !aglSetDrawable( aglContext, GetWindowPort( windowReference ) ) ){
+		osxCloseMainWindow();
+		return;
+	}
+	
+    if( !aglSetCurrentContext( aglContext ) ){
+        osxCloseMainWindow();
+    }	
+	
+	windowWidth = width;
+	windowHeight = height;
+}
+
+int  osxInstallEventHandlers(){
+
+    OSStatus error;
+	
+    mouseUPP = NewEventHandlerUPP( osxMouseEventHandler );
+	
+    error = InstallEventHandler( GetApplicationEventTarget(), mouseUPP, GetEventTypeCount( OSX_MOUSE_EVENT_TYPES ), OSX_MOUSE_EVENT_TYPES, NULL, NULL );
+    if( error != noErr ){
+        return GL_FALSE;
+    }
+
+    keyboardUPP = NewEventHandlerUPP( osxKeyEventHandler );
+	
+    error = InstallEventHandler( GetApplicationEventTarget(), keyboardUPP, GetEventTypeCount( OSX_KEY_EVENT_TYPES ), OSX_KEY_EVENT_TYPES, NULL, NULL );
+    if( error != noErr ){
+        return GL_FALSE;
+    }
+	
+    return GL_TRUE;
+}
+
+extern void dsPlatformSimLoop( int givenWindowWidth, int givenWindowHeight, dsFunctions *fn, int givenPause ){
+	
+	functions = fn;
+	
+	paused = givenPause;
+	
+	osxCreateMainWindow( givenWindowWidth, givenWindowHeight );
+	osxInstallEventHandlers();
+	
+	dsStartGraphics( windowWidth, windowHeight, fn );
+	
+	static bool firsttime=true;
+	if( firsttime )
+	{
+		fprintf
+		(
+		 stderr,
+		 "\n"
+		 "Simulation test environment v%d.%02d\n"
+		 "   Ctrl-P : pause / unpause (or say `-pause' on command line).\n"
+		 "   Ctrl-O : single step when paused.\n"
+		 "   Ctrl-T : toggle textures (or say `-notex' on command line).\n"
+		 "   Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
+		 "   Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
+		 "   Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
+		 "   Ctrl-X : exit.\n"
+		 "\n"
+		 "Change the camera position by clicking + dragging in the window.\n"
+		 "   Left button - pan and tilt.\n"
+		 "   Right button (or Ctrl + button) - forward and sideways.\n"
+		 "   Left + Right button (or middle button, or Alt + button) - sideways and up.\n"
+		 "\n",DS_VERSION >> 8,DS_VERSION & 0xff
+		 );
+		firsttime = false;
+	}
+	
+	if( fn -> start ) fn->start();
+	
+	int frame = 1;
+	running = true;
+	while( running ){
+		// read in and process all pending events for the main window
+		EventRef event;
+		EventTargetRef eventDispatcher = GetEventDispatcherTarget();		
+		while( ReceiveNextEvent( 0, NULL, 0.0, TRUE, &event ) == noErr ){
+			SendEventToEventTarget( event, eventDispatcher );
+			ReleaseEvent( event );
+		}
+				
+		dsDrawFrame( windowWidth, windowHeight, fn, paused && !singlestep );
+		singlestep = false;
+		
+		glFlush();
+		aglSwapBuffers( aglContext );
+
+		// capture frames if necessary
+		if( !paused && writeframes ){
+			captureFrame( frame );
+			frame++;
+		}
+	}
+	
+	if( fn->stop ) fn->stop();
+	dsStopGraphics();
+	
+	osxCloseMainWindow();
+}
Index: /code/branches/ode/ode-0.9/drawstuff/src/resource.h
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/resource.h	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/resource.h	(revision 216)
@@ -0,0 +1,28 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resources.rc
+//
+#define IDD_MSGDLG                      101
+#define IDR_MENU1                       102
+#define IDD_ABOUT                       103
+#define IDR_ACCELERATOR1                104
+#define IDC_LIST1                       1000
+#define IDM_EXIT                        40001
+#define IDM_ABOUT                       40002
+#define IDM_PAUSE                       40003
+#define IDM_PERF_MONITOR                40004
+#define IDM_SHADOWS                     40005
+#define IDM_TEXTURES                    40006
+#define IDM_SAVE_SETTINGS               40007
+#define IDM_SINGLE_STEP                 40008
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        108
+#define _APS_NEXT_COMMAND_VALUE         40009
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
Index: /code/branches/ode/ode-0.9/drawstuff/src/resources.rc
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/resources.rc	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/resources.rc	(revision 216)
@@ -0,0 +1,153 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+//#include "afxres.h"
+
+// added by RLS to make this work with windres
+#include "winresrc.h"
+#define IDC_STATIC (-1)
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUT DIALOG DISCARDABLE  0, 0, 257, 105
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "OK",IDOK,200,84,50,14
+    LTEXT           "Simulation test environment",IDC_STATIC,7,7,243,8
+    LTEXT           "Change the camera position by clicking + dragging in the main window.",
+                    IDC_STATIC,7,24,243,8
+    LTEXT           "Left button - pan and tilt.",IDC_STATIC,25,37,225,8
+    LTEXT           "Right button - forward and sideways.",IDC_STATIC,25,48,
+                    225,8
+    LTEXT           "Left + Right button (or middle button) - sideways and up.",
+                    IDC_STATIC,25,59,225,8
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+    //"#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU DISCARDABLE
+BEGIN
+    POPUP "&File"
+    BEGIN
+        MENUITEM "&Exit\tCtrl+X",               IDM_EXIT
+    END
+    POPUP "&Simulation"
+    BEGIN
+        MENUITEM "&Pause\tCtrl+P",              IDM_PAUSE
+        MENUITEM "Single Step\tCtrl+O",         IDM_SINGLE_STEP
+        MENUITEM "Performance &Monitor",        IDM_PERF_MONITOR, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "&Shadows\tCtrl+S",            IDM_SHADOWS, CHECKED
+        MENUITEM "&Textures\tCtrl+T",           IDM_TEXTURES, CHECKED
+        MENUITEM SEPARATOR
+        MENUITEM "S&ave Settings",              IDM_SAVE_SETTINGS, GRAYED
+    END
+    POPUP "&Help"
+    BEGIN
+        MENUITEM "&About",                      IDM_ABOUT
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+    IDD_ABOUT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 250
+        VERTGUIDE, 25
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 98
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+    "O",            IDM_SINGLE_STEP,        VIRTKEY, CONTROL, NOINVERT
+    "P",            IDM_PAUSE,              VIRTKEY, CONTROL, NOINVERT
+    "S",            IDM_SHADOWS,            VIRTKEY, CONTROL, NOINVERT
+    "T",            IDM_TEXTURES,           VIRTKEY, CONTROL, NOINVERT
+    "X",            IDM_EXIT,               VIRTKEY, CONTROL, NOINVERT
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
Index: /code/branches/ode/ode-0.9/drawstuff/src/windows.cpp
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/windows.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/windows.cpp	(revision 216)
@@ -0,0 +1,527 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#if defined(WIN32) || defined(__CYGWIN__)// this prevents warnings when dependencies built
+#include <windows.h>
+#endif
+#include <ode/config.h>
+#include <GL/gl.h>
+
+#include "resource.h"
+#include "internal.h"
+
+//***************************************************************************
+// application globals
+
+static HINSTANCE ghInstance = 0;
+static int gnCmdShow = 0;
+static HACCEL accelerators = 0;
+static HWND main_window = 0;
+
+//***************************************************************************
+// error and message handling
+
+static void errorBox (char *title, char *msg, va_list ap)
+{
+  char s[1000];
+  vsprintf (s,msg,ap);
+  MessageBox (0,s,title,MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
+}
+
+
+static void dsWarning (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  errorBox ("Warning",msg,ap);
+}
+
+
+extern "C" void dsError (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  errorBox ("Error",msg,ap);
+  exit (1);
+}
+
+
+extern "C" void dsDebug (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  errorBox ("INTERNAL ERROR",msg,ap);
+  // *((char *)0) = 0;	 ... commit SEGVicide ?
+  abort();
+  exit (1);	  // should never get here, but just in case...
+}
+
+
+extern "C" void dsPrint (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  vprintf (msg,ap);
+}
+
+//***************************************************************************
+// rendering thread
+
+// globals used to communicate with rendering thread
+
+static volatile int renderer_run = 1;
+static volatile int renderer_pause = 0;	  // 0=run, 1=pause
+static volatile int renderer_ss = 0;	  // single step command
+static volatile int renderer_width = 1;
+static volatile int renderer_height = 1;
+static dsFunctions *renderer_fn = 0;
+static volatile HDC renderer_dc = 0;
+static volatile int keybuffer[16];	  // fifo ring buffer for keypresses
+static volatile int keybuffer_head = 0;	  // index of next key to put in (modified by GUI)
+static volatile int keybuffer_tail = 0;	  // index of next key to take out (modified by renderer)
+
+
+static void setupRendererGlobals()
+{
+  renderer_run = 1;
+  renderer_pause = 0;
+  renderer_ss = 0;
+  renderer_width = 1;
+  renderer_height = 1;
+  renderer_fn = 0;
+  renderer_dc = 0;
+  keybuffer[16];
+  keybuffer_head = 0;
+  keybuffer_tail = 0;
+}
+
+
+static DWORD WINAPI renderingThread (LPVOID lpParam)
+{
+  // create openGL context and make it current
+  HGLRC glc = wglCreateContext (renderer_dc);
+  if (glc==NULL) dsError ("could not create OpenGL context");
+  if (wglMakeCurrent (renderer_dc,glc) != TRUE)
+    dsError ("could not make OpenGL context current");
+
+  // test openGL capabilities
+  int maxtsize=0;
+  glGetIntegerv (GL_MAX_TEXTURE_SIZE,&maxtsize);
+  if (maxtsize < 128) dsWarning ("max texture size too small (%dx%d)",
+				 maxtsize,maxtsize);
+
+  dsStartGraphics (renderer_width,renderer_height,renderer_fn);
+  if (renderer_fn->start) renderer_fn->start();
+
+  while (renderer_run) {
+    // need to make local copy of renderer_ss to help prevent races
+    int ss = renderer_ss;
+    dsDrawFrame (renderer_width,renderer_height,renderer_fn,
+		 renderer_pause && !ss);
+    if (ss) renderer_ss = 0;
+
+    // read keys out of ring buffer and feed them to the command function
+    while (keybuffer_head != keybuffer_tail) {
+      if (renderer_fn->command) renderer_fn->command (keybuffer[keybuffer_tail]);
+      keybuffer_tail = (keybuffer_tail+1) & 15;
+    }
+
+    // swap buffers
+    SwapBuffers (renderer_dc);
+  }
+
+  if (renderer_fn->stop) renderer_fn->stop();
+  dsStopGraphics();
+
+  // delete openGL context
+  wglMakeCurrent (NULL,NULL);
+  wglDeleteContext (glc);
+
+  return 123;	    // magic value used to test for thread termination
+}
+
+//***************************************************************************
+// window handling
+
+// callback function for "about" dialog box
+
+static LRESULT CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam,
+				      LPARAM lParam)
+{
+  switch (uMsg) {
+  case WM_INITDIALOG:
+    return TRUE;
+  case WM_COMMAND:
+    switch (wParam) {
+    case IDOK:
+      EndDialog (hDlg, TRUE);
+      return TRUE;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+
+// callback function for the main window
+
+static LRESULT CALLBACK mainWndProc (HWND hWnd, UINT msg, WPARAM wParam,
+				     LPARAM lParam)
+{
+  static int button=0,lastx=0,lasty=0;
+  int ctrl = int(wParam & MK_CONTROL);
+
+  switch (msg) {
+  case WM_LBUTTONDOWN:
+  case WM_MBUTTONDOWN:
+  case WM_RBUTTONDOWN:
+    if (msg==WM_LBUTTONDOWN) button |= 1;
+    else if (msg==WM_MBUTTONDOWN) button |= 2;
+    else button |= 4;
+    lastx = SHORT(LOWORD(lParam));
+    lasty = SHORT(HIWORD(lParam));
+    SetCapture (hWnd);
+    break;
+
+  case WM_LBUTTONUP:
+  case WM_MBUTTONUP:
+  case WM_RBUTTONUP:
+    if (msg==WM_LBUTTONUP) button &= ~1;
+    else if (msg==WM_MBUTTONUP) button &= ~2;
+    else button &= ~4;
+    if (button==0) ReleaseCapture();
+    break;
+
+  case WM_MOUSEMOVE: {
+    int x = SHORT(LOWORD(lParam));
+    int y = SHORT(HIWORD(lParam));
+    if (button) dsMotion (button,x-lastx,y-lasty);
+    lastx = x;
+    lasty = y;
+    break;
+  }
+
+  case WM_CHAR: {
+    if (wParam >= ' ' && wParam <= 126) {
+      int nexth = (keybuffer_head+1) & 15;
+      if (nexth != keybuffer_tail) {
+	keybuffer[keybuffer_head] = int(wParam);
+	keybuffer_head = nexth;
+      }
+    }
+    break;
+  }
+
+  case WM_SIZE:
+    // lParam will contain the size of the *client* area!
+    renderer_width = LOWORD(lParam);
+    renderer_height = HIWORD(lParam);
+    break;
+
+  case WM_COMMAND:
+    switch (wParam & 0xffff) {
+    case IDM_ABOUT:
+      DialogBox (ghInstance,MAKEINTRESOURCE(IDD_ABOUT),hWnd,
+	(DLGPROC) AboutDlgProc);
+      break;
+    case IDM_PAUSE: {
+      renderer_pause ^= 1;
+      CheckMenuItem (GetMenu(hWnd),IDM_PAUSE,
+		     renderer_pause ? MF_CHECKED : MF_UNCHECKED);
+      if (renderer_pause) renderer_ss = 0;
+      break;
+    }
+    case IDM_SINGLE_STEP: {
+		if (renderer_pause)
+			renderer_ss = 1;
+		else
+			SendMessage( hWnd, WM_COMMAND, IDM_PAUSE, 0 );
+      break;
+    }
+    case IDM_PERF_MONITOR: {
+      dsWarning ("Performance monitor not yet implemented.");
+      break;
+    }
+    case IDM_TEXTURES: {
+      static int tex = 1;
+      tex ^= 1;
+      CheckMenuItem (GetMenu(hWnd),IDM_TEXTURES,
+		     tex ? MF_CHECKED : MF_UNCHECKED);
+      dsSetTextures (tex);
+      break;
+    }
+    case IDM_SHADOWS: {
+      static int shadows = 1;
+      shadows ^= 1;
+      CheckMenuItem (GetMenu(hWnd),IDM_SHADOWS,
+		     shadows ? MF_CHECKED : MF_UNCHECKED);
+      dsSetShadows (shadows);
+      break;
+    }
+    case IDM_SAVE_SETTINGS: {
+      dsWarning ("\"Save Settings\" not yet implemented.");
+      break;
+    }
+    case IDM_EXIT:
+      PostQuitMessage (0);
+      break;
+    }
+    break;
+
+  case WM_CLOSE:
+    PostQuitMessage (0);
+    break;
+
+  default:
+    return (DefWindowProc (hWnd, msg, wParam, lParam));
+  }
+
+  return 0;
+}
+
+
+// this comes from an MSDN example. believe it or not, this is the recommended
+// way to get the console window handle.
+
+static HWND GetConsoleHwnd()
+{
+  // the console window title to a "unique" value, then find the window
+  // that has this title.
+  char title[1024];
+  wsprintf (title,"DrawStuff:%d/%d",GetTickCount(),GetCurrentProcessId());
+  SetConsoleTitle (title);
+  Sleep(40);			// ensure window title has been updated
+  return FindWindow (NULL,title);
+}
+
+
+static void drawStuffStartup()
+{
+  static int startup_called = 0;
+  if (startup_called) return;
+  startup_called = 1;
+  if (!ghInstance)
+    ghInstance = GetModuleHandleA (NULL);
+  gnCmdShow = SW_SHOWNORMAL;		// @@@ fix this later
+
+  // redirect standard I/O to a new console (except on cygwin)
+#ifndef __CYGWIN__
+  FreeConsole();
+  if (AllocConsole()==0) dsError ("AllocConsole() failed");
+  if (freopen ("CONIN$","rt",stdin)==0) dsError ("could not open stdin");
+  if (freopen ("CONOUT$","wt",stdout)==0) dsError ("could not open stdout");
+  if (freopen ("CONOUT$","wt",stderr)==0) dsError ("could not open stderr");
+  BringWindowToTop (GetConsoleHwnd());
+  SetConsoleTitle ("DrawStuff Messages");
+#endif
+
+  // register the window class
+  WNDCLASS wc;
+  wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
+  wc.lpfnWndProc = mainWndProc;
+  wc.cbClsExtra = 0;
+  wc.cbWndExtra = 0;
+  wc.hInstance = ghInstance;
+  wc.hIcon = LoadIcon (NULL,IDI_APPLICATION);
+  wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
+  wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
+  wc.lpszClassName = "SimAppClass";
+  if (RegisterClass (&wc)==0) dsError ("could not register window class");
+
+  // load accelerators
+  accelerators = LoadAccelerators (ghInstance,
+				   MAKEINTRESOURCE(IDR_ACCELERATOR1));
+  if (accelerators==NULL) dsError ("could not load accelerators");
+}
+
+
+void dsPlatformSimLoop (int window_width, int window_height,
+			dsFunctions *fn, int initial_pause)
+{
+  drawStuffStartup();
+  setupRendererGlobals();
+  renderer_pause = initial_pause;
+
+  // create window - but first get window size for desired size of client area.
+  // if this adjustment isn't made then the openGL area will be shifted into
+  // the nonclient area and determining the frame buffer coordinate from the
+  // client area coordinate will be hard.
+  RECT winrect;
+  winrect.left = 50;
+  winrect.top = 80;
+  winrect.right = winrect.left + window_width;
+  winrect.bottom = winrect.top + window_height;
+  DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+  AdjustWindowRect (&winrect,style,1);
+  char title[100];
+  sprintf (title,"Simulation test environment v%d.%02d",
+	   DS_VERSION >> 8,DS_VERSION & 0xff);
+  main_window = CreateWindow ("SimAppClass",title,style,
+    winrect.left,winrect.top,winrect.right-winrect.left,winrect.bottom-winrect.top,
+    NULL,NULL,ghInstance,NULL);
+  if (main_window==NULL) dsError ("could not create main window");
+  ShowWindow (main_window, gnCmdShow);
+
+  HDC dc = GetDC (main_window);			// get DC for this window
+  if (dc==NULL) dsError ("could not get window DC");
+
+  // set pixel format for DC
+
+  PIXELFORMATDESCRIPTOR pfd = {
+    sizeof(PIXELFORMATDESCRIPTOR),   // size of this pfd
+    1,				     // version number
+    PFD_DRAW_TO_WINDOW |	     // support window
+    PFD_SUPPORT_OPENGL |	     // support OpenGL
+    PFD_DOUBLEBUFFER,		     // double buffered
+    PFD_TYPE_RGBA,		     // RGBA type
+    24, 			     // 24-bit color depth
+    0, 0, 0, 0, 0, 0,		     // color bits ignored
+    0,				     // no alpha buffer
+    0,				     // shift bit ignored
+    0,				     // no accumulation buffer
+    0, 0, 0, 0, 		     // accum bits ignored
+    32, 			     // 32-bit z-buffer
+    0,				     // no stencil buffer
+    0,				     // no auxiliary buffer
+    PFD_MAIN_PLANE,		     // main layer
+    0,				     // reserved
+    0, 0, 0			     // layer masks ignored
+  };
+  // get the best available match of pixel format for the device context
+  int iPixelFormat = ChoosePixelFormat (dc,&pfd);
+  if (iPixelFormat==0)
+    dsError ("could not find a good OpenGL pixel format");
+  // set the pixel format of the device context
+  if (SetPixelFormat (dc,iPixelFormat,&pfd)==FALSE)
+    dsError ("could not set DC pixel format for OpenGL");
+
+  // **********
+  // start the rendering thread
+
+  // set renderer globals
+  renderer_dc = dc;
+  renderer_width = window_width;
+  renderer_height = window_height;
+  renderer_fn = fn;
+
+  DWORD threadId, thirdParam = 0;
+  HANDLE hThread;
+
+  hThread = CreateThread(
+	NULL,			     // no security attributes
+	0,			     // use default stack size
+	renderingThread,	     // thread function
+	&thirdParam,		     // argument to thread function
+	0,			     // use default creation flags
+	&threadId);		     // returns the thread identifier
+
+  if (hThread==NULL) dsError ("Could not create rendering thread");
+
+  // **********
+  // start GUI message processing
+
+  MSG msg;
+  while (GetMessage (&msg,main_window,0,0)) {
+    if (!TranslateAccelerator (main_window,accelerators,&msg)) {
+      TranslateMessage (&msg);
+      DispatchMessage (&msg);
+    }
+  }
+
+  // terminate rendering thread
+  renderer_run = 0;
+  DWORD ret = WaitForSingleObject (hThread,2000);
+  if (ret==WAIT_TIMEOUT) dsWarning ("Could not kill rendering thread (1)");
+  DWORD exitcode=0;
+  if (!(GetExitCodeThread (hThread,&exitcode) && exitcode == 123))
+    dsWarning ("Could not kill rendering thread (2)");
+  CloseHandle (hThread);	     // dont need thread handle anymore
+
+  // destroy window
+  DestroyWindow (main_window);
+}
+
+
+extern "C" void dsStop()
+{
+  // just calling PostQuitMessage() here wont work, as this function is
+  // typically called from the rendering thread, not the GUI thread.
+  // instead we must post the message to the GUI window explicitly.
+
+  if (main_window) PostMessage (main_window,WM_QUIT,0,0);
+}
+
+
+extern "C" double dsElapsedTime()
+{
+  static double prev=0.0;
+  double curr = timeGetTime()/1000.0;
+  if (!prev)
+    prev=curr;
+  double retval = curr-prev;
+  prev=curr;
+  if (retval>1.0) retval=1.0;
+  if (retval<dEpsilon) retval=dEpsilon;
+  return retval;
+}
+
+
+// JPerkins: if running as a DLL, grab my module handle at load time so
+// I can find the accelerators table later
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+  switch (fdwReason)
+  {
+  case DLL_PROCESS_ATTACH:
+    ghInstance = hinstDLL;
+    break;
+  }
+  return TRUE;
+}
+
+
+// JPerkins: the new build system can set the entry point of the tests to
+// main(); this code is no longer necessary
+/*
+
+//***************************************************************************
+// windows entry point
+//
+// NOTE: WinMain is not guaranteed to be called with MinGW, because MinGW
+// always calls main if it is defined and most users of this library will
+// define their own main. So the startup functionality is kept in
+// zDriverStartup(), which is also called when dsSimulationLoop() is called.
+
+extern "C" int main (int argc, char **argv);
+
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+		   LPSTR lpCmdLine, int nCmdShow)
+{
+  drawStuffStartup();
+  return main (0,0);	// @@@ should really pass cmd line arguments
+}
+
+*/
+
Index: /code/branches/ode/ode-0.9/drawstuff/src/x11.cpp
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/src/x11.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/src/x11.cpp	(revision 216)
@@ -0,0 +1,418 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// main window and event handling for X11
+
+#include <ode/config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <GL/glx.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <drawstuff/drawstuff.h>
+#include <drawstuff/version.h>
+#include "internal.h"
+
+//***************************************************************************
+// error handling for unix
+
+static void printMessage (char *msg1, char *msg2, va_list ap)
+{
+  fflush (stderr);
+  fflush (stdout);
+  fprintf (stderr,"\n%s: ",msg1);
+  vfprintf (stderr,msg2,ap);
+  fprintf (stderr,"\n");
+  fflush (stderr);
+}
+
+
+extern "C" void dsError (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  printMessage ("Error",msg,ap);
+  exit (1);
+}
+
+
+extern "C" void dsDebug (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  printMessage ("INTERNAL ERROR",msg,ap);
+  // *((char *)0) = 0;	 ... commit SEGVicide ?
+  abort();
+}
+
+
+extern "C" void dsPrint (char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  vprintf (msg,ap);
+}
+
+//***************************************************************************
+// openGL window
+
+// X11 display info
+static Display *display=0;
+static int screen=0;
+static XVisualInfo *visual=0;		// best visual for openGL
+static Colormap colormap=0;		// window's colormap
+static Atom wm_protocols_atom = 0;
+static Atom wm_delete_window_atom = 0;
+
+// window and openGL
+static Window win=0;			// X11 window, 0 if not initialized
+static int width=0,height=0;		// window size
+static GLXContext glx_context=0;	// openGL rendering context
+static int last_key_pressed=0;		// last key pressed in the window
+static int run=1;			// 1 if simulation running
+static int pause=0;			// 1 if in `pause' mode
+static int singlestep=0;		// 1 if single step key pressed
+static int writeframes=0;		// 1 if frame files to be written
+
+
+static void createMainWindow (int _width, int _height)
+{
+  // create X11 display connection
+  display = XOpenDisplay (NULL);
+  if (!display) dsError ("can not open X11 display");
+  screen = DefaultScreen(display);
+
+  // get GL visual
+  static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
+			     GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
+			     GLX_BLUE_SIZE,4, None};
+  visual = glXChooseVisual (display,screen,attribList);
+  if (!visual) dsError ("no good X11 visual found for OpenGL");
+
+  // create colormap
+  colormap = XCreateColormap (display,RootWindow(display,screen),
+			      visual->visual,AllocNone);
+
+  // initialize variables
+  win = 0;
+  width = _width;
+  height = _height;
+  glx_context = 0;
+  last_key_pressed = 0;
+
+  if (width < 1 || height < 1) dsDebug (0,"bad window width or height");
+
+  // create the window
+  XSetWindowAttributes attributes;
+  attributes.background_pixel = BlackPixel(display,screen);
+  attributes.colormap = colormap;
+  attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
+    KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
+    StructureNotifyMask;
+  win = XCreateWindow (display,RootWindow(display,screen),50,50,width,height,
+		       0,visual->depth, InputOutput,visual->visual,
+		       CWBackPixel | CWColormap | CWEventMask,&attributes);
+
+  // associate a GLX context with the window
+  glx_context = glXCreateContext (display,visual,0,GL_TRUE);
+  if (!glx_context) dsError ("can't make an OpenGL context");
+
+  // set the window title
+  XTextProperty window_name;
+  window_name.value = (unsigned char *) "Simulation";
+  window_name.encoding = XA_STRING;
+  window_name.format = 8;
+  window_name.nitems = strlen((char *) window_name.value);
+  XSetWMName (display,win,&window_name);
+
+  // participate in the window manager 'delete yourself' protocol
+  wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
+  wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
+  if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0)
+    dsError ("XSetWMProtocols() call failed");
+
+  // pop up the window
+  XMapWindow (display,win);
+  XSync (display,win);
+}
+
+
+static void destroyMainWindow()
+{
+  glXDestroyContext (display,glx_context);
+  XDestroyWindow (display,win);
+  XSync (display,0);
+  XCloseDisplay(display);
+  display = 0;
+  win = 0;
+  glx_context = 0;
+}
+
+
+static void handleEvent (XEvent &event, dsFunctions *fn)
+{
+  static int mx=0,my=0; 	// mouse position
+  static int mode = 0;		// mouse button bits
+
+  switch (event.type) {
+
+  case ButtonPress: {
+    if (event.xbutton.button == Button1) mode |= 1;
+    if (event.xbutton.button == Button2) mode |= 2;
+    if (event.xbutton.button == Button3) mode |= 4;
+    mx = event.xbutton.x;
+    my = event.xbutton.y;
+  }
+  return;
+
+  case ButtonRelease: {
+    if (event.xbutton.button == Button1) mode &= (~1);
+    if (event.xbutton.button == Button2) mode &= (~2);
+    if (event.xbutton.button == Button3) mode &= (~4);
+    mx = event.xbutton.x;
+    my = event.xbutton.x;
+  }
+  return;
+
+  case MotionNotify: {
+    if (event.xmotion.is_hint) {
+      Window root,child;
+      unsigned int mask;
+      XQueryPointer (display,win,&root,&child,&event.xbutton.x_root,
+		     &event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y,
+		     &mask);
+    }
+    dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
+    mx = event.xmotion.x;
+    my = event.xmotion.y;
+  }
+  return;
+
+  case KeyPress: {
+    KeySym key;
+    XLookupString (&event.xkey,NULL,0,&key,0);
+    if ((event.xkey.state & ControlMask) == 0) {
+      if (key >= ' ' && key <= 126 && fn->command) fn->command (key);
+    }
+    else if (event.xkey.state & ControlMask) {
+      switch (key) {
+      case 't': case 'T':
+	dsSetTextures (dsGetTextures() ^ 1);
+	break;
+      case 's': case 'S':
+	dsSetShadows (dsGetShadows() ^ 1);
+	break;
+      case 'x': case 'X':
+	run = 0;
+	break;
+      case 'p': case 'P':
+	pause ^= 1;
+	singlestep = 0;
+	break;
+      case 'o': case 'O':
+	if (pause) singlestep = 1;
+	break;
+      case 'v': case 'V': {
+	float xyz[3],hpr[3];
+	dsGetViewpoint (xyz,hpr);
+	printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
+		xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
+	break;
+      }
+      case 'w': case 'W':
+	writeframes ^= 1;
+	if (writeframes) printf ("Now writing frames to PPM files\n");
+	break;
+      }
+    }
+    last_key_pressed = key;		// a kludgy place to put this...
+  }
+  return;
+
+  case KeyRelease: {
+    // hmmmm...
+  }
+  return;
+
+  case ClientMessage:
+    if (event.xclient.message_type == wm_protocols_atom &&
+	event.xclient.format == 32 &&
+	Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
+      run = 0;
+      return;
+    }
+    return;
+
+  case ConfigureNotify:
+    width = event.xconfigure.width;
+    height = event.xconfigure.height;
+    return;
+  }
+}
+
+
+// return the index of the highest bit
+static int getHighBitIndex (unsigned int x)
+{
+  int i = 0;
+  while (x) {
+    i++;
+    x >>= 1;
+  }
+  return i-1;
+}
+
+
+// shift x left by i, where i can be positive or negative
+#define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))
+
+
+static void captureFrame (int num)
+{
+  fprintf (stderr,"capturing frame %04d\n",num);
+
+  char s[100];
+  sprintf (s,"frame/frame%04d.ppm",num);
+  FILE *f = fopen (s,"wb");
+  if (!f) dsError ("can't open \"%s\" for writing",s);
+  fprintf (f,"P6\n%d %d\n255\n",width,height);
+  XImage *image = XGetImage (display,win,0,0,width,height,~0,ZPixmap);
+
+  int rshift = 7 - getHighBitIndex (image->red_mask);
+  int gshift = 7 - getHighBitIndex (image->green_mask);
+  int bshift = 7 - getHighBitIndex (image->blue_mask);
+
+  for (int y=0; y<height; y++) {
+    for (int x=0; x<width; x++) {
+      unsigned long pixel = XGetPixel (image,x,y);
+      unsigned char b[3];
+      b[0] = SHIFTL(pixel & image->red_mask,rshift);
+      b[1] = SHIFTL(pixel & image->green_mask,gshift);
+      b[2] = SHIFTL(pixel & image->blue_mask,bshift);
+      fwrite (b,3,1,f);
+    }
+  }
+  fclose (f);
+  XDestroyImage (image);
+}
+
+
+void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
+			int initial_pause)
+{
+  pause = initial_pause;
+  createMainWindow (window_width, window_height);
+  glXMakeCurrent (display,win,glx_context);
+
+  dsStartGraphics (window_width,window_height,fn);
+
+  static bool firsttime=true;
+  if (firsttime)
+  {
+    fprintf
+    (
+      stderr,
+      "\n"
+      "Simulation test environment v%d.%02d\n"
+      "   Ctrl-P : pause / unpause (or say `-pause' on command line).\n"
+      "   Ctrl-O : single step when paused.\n"
+      "   Ctrl-T : toggle textures (or say `-notex' on command line).\n"
+      "   Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
+      "   Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
+      "   Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
+      "   Ctrl-X : exit.\n"
+      "\n"
+      "Change the camera position by clicking + dragging in the window.\n"
+      "   Left button - pan and tilt.\n"
+      "   Right button - forward and sideways.\n"
+      "   Left + Right button (or middle button) - sideways and up.\n"
+      "\n",DS_VERSION >> 8,DS_VERSION & 0xff
+    );
+    firsttime = false;
+  }
+
+  if (fn->start) fn->start();
+
+  int frame = 1;
+  run = 1;
+  while (run) {
+    // read in and process all pending events for the main window
+    XEvent event;
+    while (run && XPending (display)) {
+      XNextEvent (display,&event);
+      handleEvent (event,fn);
+    }
+
+    dsDrawFrame (width,height,fn,pause && !singlestep);
+    singlestep = 0;
+
+    glFlush();
+    glXSwapBuffers (display,win);
+    XSync (display,0);
+
+    // capture frames if necessary
+    if (pause==0 && writeframes) {
+      captureFrame (frame);
+      frame++;
+    }
+  };
+
+  if (fn->stop) fn->stop();
+  dsStopGraphics();
+
+  destroyMainWindow();
+}
+
+
+extern "C" void dsStop()
+{
+  run = 0;
+}
+
+
+extern "C" double dsElapsedTime()
+{
+#if HAVE_GETTIMEOFDAY
+  static double prev=0.0;
+  timeval tv ;
+
+  gettimeofday(&tv, 0);
+  double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
+  if (!prev)
+    prev=curr;
+  double retval = curr-prev;
+  prev=curr;
+  if (retval>1.0) retval=1.0;
+  if (retval<dEpsilon) retval=dEpsilon;
+  return retval;
+#else
+  return 0.01666; // Assume 60 fps
+#endif
+}
+
Index: /code/branches/ode/ode-0.9/drawstuff/textures/ground.ppm
===================================================================
--- /code/branches/ode/ode-0.9/drawstuff/textures/ground.ppm	(revision 216)
+++ /code/branches/ode/ode-0.9/drawstuff/textures/ground.ppm	(revision 216)
@@ -0,0 +1,3112 @@
+P6
+# Created by Paint Shop Pro
+256 256
+255
+¦§¨¤¦¤¦¤¦¤¦¦§¨¦§¨mtt
+v{¤¦}{{tdc\}dc\
+}¦§¨||UTSu{{bVU{{t|
+lritt{zllf]cSKJ¤
+|
+{ttlekzll|z[[Ttsl|uzt¤¦lri||u||}}¨©´mttttslks}|leklld|z|zSKJ]bZ}ttsddc{tt[TTult{tttllv{tll}cbVdc\lrijcVsre[TTsleSKJj]\\[[¦§¨:97*)(ztlJHFlddJHFVTL
+bVUVTLddcb[U
+lrib[Uultmttlldllklld|
+dc\|zmtttsl||uttsddc{{tmtt\UZlj
+||}ttslldkd\lddult|z|zu{{ek]|lri|zztltsltslztl[[T{u{]bZldd]cddc\mttUMRldd}VZTSKJD;9mttlld\[[JHFUTSJHF[TT||¤¦tzlmtt|
+lksddc|
+
+{{}|
+§²}|¤|
+}||
+{{²¤¤²{{{{}
+¬¶Ã¤¤¬¶Ã§²
+ttsllk{{t{||||{||
+}¤¤¦§¨¢¦§¨«²«mttd\\tllultVTL|cbV{tt}{ttµ¶·ultr]gultf]cbVU}}tlltlllekztl{{t{ttmttult{u{tllult}{||{{ldd
+{{¤]cd}£¥ª³·
+¦§¨ª³·{{|
+u{{
+{{lksª³·
+UUYldddc\}{{t
+ult}sre{zmttsj]\VTLSKJrg]iWUv{ekd¦§¨:97
+
+$kd\uztultultlddbVUVTLSKJkk]}
+}ztlVTLtzl{||lld|uttstsltsl
+dc\tzlsle|
+u{{ekdtyglri{||]cd{u{tzlv{ztl{{t|zv{|u||VTLddcb[UbVZ|z[TT[[Tlri{tt{u{rfklldttsd\\ult{tti\Vredtzlllk{{iq]{ttdc\ekddc\ztltzl]cd
+JHFjcVLKR}¤¦§¨uzt{{¢mttd\\\[[|
+|zuztnvmttlks{{¤¦}^^qmttddc{{nv}||
+lks}
+ylnv²ª³·
+ª³·nv}{{£ª³·¤¤¤edk{{f]c|z|u|{{t||
+}{||JHF|
+{{ultred}|z{||ª³·}zll¢
+|z}jcVtll}¤¤w{||}ttsmtt¤¦u{{tt{ttsu{{VTLlrimtt\[[|zlrilldmtttt{lks|
+tsl|
+¤
+\[bf]c
+lkslri|||
+
+lks}dc\ult}{u{tts
+u{{ddc|
+UUY}]bZtslddcslesrev{lddslecbVSKJ{{tdc\kd\tzltsl||v|j]\[[T:97:97cbVlrid\\tlltllldd[[T|zcbV}£}{||lkscbV}tzl{u{{tt}ekd{{tek]f]c{u{ddctll{u{lek}tlldc\{tt{||{||ultv|ultult]bZ
+{||tzledk]cd
+fkktllsle[[T\[[ttslriekdmtt|
+tsllri\[[b[U{{tuzt[[Tddc[[T|z{{d\\UTSult{tt{{tyllkstt{ult|
+|
+{{{{{{|
+{{t{{lks{{
+|
+nv{{|
+£fkk
+{{}|^fs¤£lkslksnv}¤£££|
+nv}¡¡»ÂÇ»ÂÇª³·¤¦ekd¦§¨
+uzt¦§¨utlld}¤¤{{¤¤¦ddcedkddclritsl{{lek|ulddztlred|u]bZtslSKJf]c}¤¦[[Tv|||{{}}ultf]c[TTlddd\\||\[b[TTUMRult|
+£¥¦§¨||¦§¨lld|
+lksd\\{tttt{{|||
+|{u{rfktt{ª³·|
+¢
+|
+uztf]clddrfk{{tsle
+tll|urfkzllb[Ukk]ztlztldc\cbV|z{{tbVZ[TTSKJutllk¦§¨LKR*)(rg]llklekult{u{VTLVTLllk|uztVTLVTLedk|z{{ttsl|z|zddcddcekdVTLlrif]cult
+tsl}¤{{ztl{{ttsl||sle]cdtll{{t{{tult}|z{{tult{||mttVZ[JHF]bZ|
+lksv{f]cekdtt{tll[[T}||{{{u{{{t]bZ{tt¤¤|uttslld]bZ\[bSKJlksd\\tll{{ttsu{{tslu{{{{mttek]}|
+{{u{{mtt|
+ttsmttylnv^^q\[b\[bnvtt{~u{{}\[bnvn
+§²£§²n
+¤¦{{t¨©´¤¦¤{||
+¤}utult¤lekddc
+{{tsl{{tleklks¦§¨{tt¨©´
+|
+£}|}²¬µbVZultlks£edktsl{{t
+lks|
+llkdc\ttsfkk|z|zuztuztztllld{tt¦§¨u{{|z|tt{
+¤uzt¤¦¤¦{u{dc\{u{|lldtt{£v{||j]\ut{{trg]PF=]bZ[TTlri{{t{{tddcSKJbVUlldUTS¦§¨JHF*)(d\\}{ttlddlldsref]cf]clritslslellku{{ekdlrilrimttlks{zm|zaWMlek
+|
+red\[[dc\ttsUTS~tslkk]ult{{t|ultd\\|uultf]cLKR:97MRK¢llk{||{{ttzllri\[[llktslu{{¦§¨|[[Tztlu{{[[Tlrirfk\[[VTLmtt{||v}{{t|
+uzt]cd|
+tt{fkk{{|
+{{{{|
+£~¡|
+|
+ttsnv
+}}{{nvlks{{
+¤}|
+}nvmk
+¤}{{t¤«²«¤¦¤
+¤¦§¨ttsllk¤{{}ult£¥{{lks|
+\UZ£¥¨©´£¥tts£¥|
+²¬µ£f]cred|zuzttts{{tJHF||
+lddldd{ttultSKJVZT{u{uzt
+{{|
+u}|z£¥¤¦uzt}|
+v{
+|
+
+tt{edk|
+lks{{mtt]cd|
+{{tt{tll{{tmtt}lldrfk}}ultrfk
+ztl}ztf{zmd\\|zdc\dc\]bZ}aWMtt{\UZFD;¤?;C?;Credlldj]\f]ctlllld{{llkekd||j]\ultlektt{\[[ldd
+tygek]ult\UZ]bZ||lridc\{ttult
+}{u{rfk
+lri|
+ult{||||tsl|
+u|{{tdc\cbV¦§¨MRK*)(UTSlldmttddcekdllkttsllk{u{]bZ\[[
+|u}|ddcleklld}kjVSKJUMR}¤£¥
+tts|
+|
+lks{{u{{mtt~£¡}}¤¨©´
+|
+^^q}n
+tt{£{{
+¤¤
+£¤|zu{{|ª³·¢{|||
+|z¦§¨²««¨©´¤llktt{¤¦§²
+
+|
+lksvttsllk¤
+
+||¢
+red£sre{{t{zmuztlddlldsle\UZtts¡tts|
+{u{{{
+{{tuzt¦§¨{tt|rg]kk]¤¨©´¨©´|
+{{t¤¦
+|
+|
+u{{fkkmtt|
+ª³·JHFv{¤tzli\VtslbVUv{rfkr]gyleSKJtsl\[[leklld|JHFztfb[U]bZ[[T¦§¨UUY:97lldsleuztrfkr]gekdVTLj]\d\\\[bdc\|u||{u{{||tsl|
+v[TTkk]lri|u|zu{{{tttsl{tt
+{||ultsle{u{\[[|
+
+¦§¨|{||ekdbVUlldtts{ttJHF:97owVTLuzttzl|lldrg]j]\usreJHFlrillkrg]dc\
+}ddc|z]bZ|
+mttSKJmwf]cf]clkslks|z|
+ult{{{{{||
+mtt£{{}n
+{{ylmtt|
+{{}|nv¤£^fs{{
+mtt¨©´¤£§²
+£}|lksedk¢¢¤¦··Ä¤}£²£¨©´¨©´
+tts{{mtt{{tllk
+ztl{{\[bbVZred{||ztl¤¤¦§¨u{{ekdlekmtt¤¦tsl¤¦lriu{{tts{||
+{u{\[b
+{u{{{|
+
+f]ctll|z]cd|
+edk|
+
+{{ttsu{{{{{{²¬µ¤lektts
+mttlkstt{lriddc|
+|
+uzt¤sreUMR|
+tllbVU||}SKJut}kd\wlultdc\llkPF=]bZSKJVTL¨©´f]c:97lekztl
+utzllek[TTf]clks]bZu{{{{tsltll{||}|}\[[u{{mttVTL}{tt{{srettsLKRmtt{||sletzl~ultttslksf]cbVZUTSVTL[TT]cd}||lddf]c{tt[TT[TT{u{d\\UMRJHFJHFlekekd}tzl]cdkd\ultu{{r]gf]cJHFddclrilriult
+v{u{\[blks|
+mtt|
+]cdmttmtt
+£}¤
+|
+|
+\[bmttOS`£lks£{{¤}¨©´¤¦¬¶Ã
+|
+{{£§²
+}
+£²¨©´¢¤¦tts¢slekk]|tt{tts{||uztultztlekdtll{tttsl||||£¥f]ctt{vlddJHFMRKfkkiq]uzttts¤lks¤\[b]bZlksult£]cdlri]cdSKJbVUMSS{{|
+\UZult|
+tt{u{{{u{lddmttlld{||lrilri|zlldtsldc\dc\|mtt|zuztSKJtllkd\{ttultzlliWUztlsleSKJzllslekd\v{ekdtslUTS]bZllkVTLd\\VTLek]
+\[b*)(f]credtllsre{{tekd[TTddcultdc\dc\tsltsl|zu{{}sreuztl}b[Ub[U\UZlekulttt{}|z{u{|¤sletslsre¤¦|{u{f]cedkUUYUMR|
+{{
+lriztl{u{|ztllUMRVTL\[[||zkd\slellk[TTult{ttkd\D;9edkJHFllkd\\sretts|
+}llklkslks\[b}ekd
+{{ow
+¦§¨|
+{{lks{||ult{{mttmtt^fsu{{}|}nvnv|
+|
+mtt¤¦}§²}¬¶Ã£|
+ª³·²¤¦··Ä¤uztlri¤¦|tzlb[U||~u{{{||lks¤lek
+¤ztl||¤¤¦§¨lri¨©´£|{{tdc\¦§¨ult}||z}lek]cd\[bUTStt{}{{tSKJ[TTtt{lldfkk£~{{
+ultttsult||\[bultf]c
+u{{{u{|
+¤tt{ttsldd}||zdc\j]\d\\VTLlri¤¤{ttf]ctsllddvztl{ttlddv{cbVuzt}tllVTLllktsl¦§¨\[b)+2mtt|utlltsllekb[Urg]u{||dc\ek]|z¨©´¤zllsre||
+{|||z|z|uulldztlttstt{ultttsulttt{rg]||{u{
+
+|ultvredldd}d\\[TT||}lek|
+lri{u{lld{||\[[ek]SKJtsl[TTb[Ulld|
+dc\usresle\UZldd{u{ztltsl[TT>B9owulttslnv£¥
+}{|||
+ultnv¤{{¤
+u{{u{{|
+lksmk
+£§²{{¡}{{¤£¤¤¤|z{||£red
+{u{lri|z||{tttsl||¤{ttslezl|uzt¦§¨{u{{u{ztl{{tlld¤¦uslesle}tt{j]\f]cf]cultult¤£lks{ttedk\[b{{llkddc]bZ{{tlld{tt}¦§¨]cd{u{tts
+UTS|zttsuztekdlld|
+¢ztl\[b£¥mtt¢lksSKJ{ttlrikk]dc\UUYsle[[TjcVmttkd\||rg]tts{||tllsleJHFddcdc\b[Uult{||\[[:97zll{{ttslztlsreUMRztltts\UZ{{t{{tttslek}|ult
+{{t}kk]d\\{u{vtzltslzlllrif]c|uutUTSulttzlf]c||ult{u{{u{|}ldd[TTSKJ{{t~ztl{tt{ttreddc\{tt
+{||uztSKJ{zmek]lrittslddvu{{UMRultD;9UTSLKRlri
+¢{u{{u{{{{{tt{lekttslri}tts]cd{{u{{{{lks£¡¦§¨ª³·mtt{{^fs¤¦
+
+
+|
+¤¦£mtt¤¦¤¦{{~¤tt{
+tll{{
+{|||zedk|
+|
+¦§¨{tt£SKJ{tt}|j]\tllJHF{{¤{{lri|zdc\tsl{||{{{{kd\ztl
+\UZ}|{||f]cv~f]c{{£¦§¨{tt||lek|u{ttuztult
+tts}||}}lld}{tt
+¤u{{ultlks
+{{tts|z\UZllk[TTddctsl]bZtzlSKJreduztu{{ldd}|{ttekdztfred[[T{{tek]redllk}¦§¨[TT:97zllkk]d\\kd\lldred\[bf]clldlri{u{{||tzlldd¤¦f]c|llkult{zmztl}v{kd\tts
+£¥lks}mttu{{mttuzt]cdultut|
+¤¤|[[T|
+{tt|{||||lri||
+ztlbVZ[[T||cbVlldMRKd\\ekd}SKJj]\SKJUMRult{zm|mw{{}}ult
+
+{{²|
+¤¦
+]cd]cd}lkslks
+tt{£{{\[b{{f]c
+mtt¤
+¤{zm}v{
+¤¦¤¦¤¨©´¨©´¬¶Ã¤¤¨©´ª³·¤¦¢{zmtts|
+]cdlek
+tsltt{ztltts|ztsl{zm££¥tslultu{{tll|v|tlltsl{{}b[U¡¤
+v{}v{ldd{{
+fkk}UTS}{|||
+llk{tt{{t££}tlllekv}ldd{u{||tt{|
+
+{u{cbV|
+lldiq]jV[}ztltslSKJutVTLlrivlriUTSlddJHFFD;llktts¢SKJ:97lld{u{
+£||rg]JHFlek[[T|zekdldd¤bVU|zVTLek]|zdc\
+|z}||tsl
+£¥tllut{||tt{llkekd
+tllu{{t[[T{{
+|z{{VTLtt{tlltts}tsl{tttts[TTyl{u{lddekdVTLUMRwlsre{u{kd\lksu{{\UZf]csleg\rred¤mttv{{||{u{}||lek{||{{{{¤{||
+}{{
+tt{
+|
+mttmtt^fs{{¡|
+{{{{{{¦§¨|
+¨©´¦§¨¤
+¤¨©´¢}¦§¨¨©´··Ä}lddv{¢¤tlluzttsl{{tf]cJHFf]cult¦§¨tt{¤¦u||
+¤¦¤[[Tsle[[Tkd\f]c||tt{\UZ{{|
+\[blkslri]bZ¦§¨ttssle{ttttszllkd\tllult}lekmttedk{{{{{{
+{{lld¨©´|zlld¦§¨¦§¨lri¦§¨tts
+cbVUTStt{|z\[[{{t\UZ{ttttssreslerfk|||u{ttfkkddc[[Tllkzlmttlriztl¦§¨UMR:97||ukd\ztlu{{ylekd\{tttllek]llk|
+{tt||{||wl}]bZlriuzt
+ldd}{{t|uuztult{{ult{||||||z{{f]czllult||SKJ{ttsleuzt||{{MRKUMRlek
+f]c{ttdc\tlld\\tsltllj]\VTLVTLu
+tt{vtsl|[[T[TT\UZultzllultedkldd|z{u{lddddc{{tts{{
+{{yl¤lks£|
+\UZmtt|
+{{nv{{
+¦§¨£¤|
+{{nv{{{{}¢£
+¦§¨¨©´ª³·u{{}¤
+lriuztllklek{||f]c\[[¤¤¢
+llk|z{ttultmwlekb[Ulri
+mtt
+f]csle¢{ttVZ[mtt]cdnv|
+lks]bZ£¦§¨
+ª³·zlltslldd{ttultfkku{{{{¤
+lddtsl\[[lri{{t¤¤tt{d\\VTL||ttslrikd\|SKJaWM[[Tf]c[TTVTLlldlri«²«JHFUUYsle||ldd||
+{ttultedkvlritsltts{{||{zmultntzlsretts|zztl{tt{{t{{|z£²tll£ut¨©´|]bZkd\{u{ztlldd{{d\\edktt{||UUY[[TLKR{{f]cultttslksultUMRlksddc\UZ\UZlek}rfk}|tsl|
+{{tulttts}{||tllf]cmtt{{tj]\f]c}mk
+{tt|zmttu{{lks{{|
+lksult\UZtlllek
+\[b|^^q\[[mtt|
+n
+{{MSSult§²¨©´²{{~{{¤¦^fs}£¤¦¡¦§¨¦§¨¤¦¢{||}¤|
+¢¤¦llk{tt|]bZ|}{{uttll¨©´|u||¦§¨¤¦{{t||
+lri|ztt{{||SKJekd{{t¤¦|
+{{lri|
+|{{tuzt¤¦¦§¨£¥{u{}£mttfkkult|uuztuztlks¨©´ultttsb[U|zultlek|||srerg]||d\\ddcztllldFD;f]clkskk]|z|zllk3+*ttsUMRf]cr]g{u{tsllek{zmsletzl
+lek
+£¥}}ttsldd|zztl{{t{u{{||}||}|}|kd\ult{{¢
+tsl|}{u{[[Tddclld{||VTLJHFVZTtsllks{u{{||{{t{{\[[\[[}f]c{ttlldttsf]c|uttskk]aWMVTLedklksmtt||f]clddtt{\[bult{||¤{{{u{|
+{{t¤}{{ttstts
+mtt¤\[bedk\[b¤¤¤
+mttª³·{{mttnv§²µ¶·£¥£²~{{t¦§¨¦§¨
+ttssre|tts{||
+¤¦|
+¢¦§¨|
+tts
+|z}¤¦|z}¦§¨¦§¨{{t|zwlu£²««{u{ulttt{lek¤\[[||{||llk{{\[blks}}VZ[UMRedk
+uzt¤}{{t¤¨©´ª³·¤¦¤¦¤¢¤¦¤¦fkk{{{{{{
+f]c}ultult[[Tmttfkk
+lek{tt{tt¨©´|ddckk]yfdtts£¥||kk]|
+ttsSKJtt{tzl[[T]cdlek}²««UTS*)(ultbVZlek{{t{u{||{{wluztlriu{{{||f]cu{{|z||£}|ultrg]wl£sleut||{tt|tt{
+{{t|z|uztf]c[TTddctlld\\tllkd\ldd\[[ultttsekdlkslks||UTSd\\llk
+VTLtt{tts|{||{||[[Tg\rLKRlksf]cek]dc\VTLkd\]cd]cdek]||
+¤
+}
+
+ult|
+llk¦§¨¤¦¤lksmtt{{{{|
+{{edk|
+\[[edk{{{{vuzt{{¤{{tt{¤¤¦¤¦§¨}{u{|z¤tsllksultult||¤¦tll|¨©´|
+{||
+]bZttstt{
+
+\[[lri|z¦§¨tzl]bZttsu{{tllwl}u|zedkuztu{{{{¤
+mttult{{t{{lri\[b]cdmtt|zz}lri|
+lks¤¦¨©´¤¦
+¤¦ª³·f]c|
+u{{\UZ}|ult}tll{tt|uUMRllk{{t£¥¤lksultlks
+{u{mtttts}}[[TSKJbVZ}tt{}[TTllktslkd\||sle|ztll{{t¦§¨llk74,SKJtll
+ddcmttldd{{tsle
+f]cslesle|
+lri|z|u{tt£¦§¨|u
+sre|¤lldmtt|ddctt{{u{tslr]Zu{{|uultllkfkkSKJ]bZ]bZF=CF=Cmttlri¤¦|
+{{t
+tsllkstlltts]bZlekuzt|
+ddclkslrid\\sleu{{slesred\\cbVtll}uztlritll{tt
+£¥§²{{¤¦¤llk¤{u{}lks|
+{{|
+tt{|
+|
+²nv|
+{{lks{||
+}£²£¥¤{{¤tlltts[TT{tt¦§¨¦§¨}
+v{ztl||mtt{u{
+{||¤¦¤SKJ|u{{t~
+{{|
+edk|
+tsltzl{{t¢¢{{lektt{
+{{mttldd]cdvlksu{{\[bUUY£mtt£|
+{{{{VZ[
+«²«¤¦§¨|
+mtt¤¤tt{lks¤lks
+ult\[[dc\||UMRyflreddc\j]\j]\{ttllkedkb[Uultult]cddc\[TTVTLtll[[Ttllr]g}{{tekdultbVZj]\UTSC8.JHFldd²««¢JHF!ekd{{{{tultllksle|zb[U{{£||
+|}{tt}v{
+|ttssleu¤¦f]c}mtt{{t
+lri|
+{||tt{¤dc\tllekdlldvmk
+mtt{|||
+rfkekd[TTekdlldmttek]
+}lek\UZVTLlks}redultd\\
+
+
+{{{||¦§¨}£\[[ddcult{||}¦§¨lks|
+tts|
+v
+
+|
+|
+¤~¤
+|
+¤¦¤£¥lks{u{£¥
+
+
+ldd{{mtt¤¦¤¦MSSUTStts~ztlv|]bZcbV¦§¨|z\UZddc\[[[TT{||¤|
+¤mtt\UZlksultJHF\[bUMR}|
+||ult{{tult¤¦¤¦
+¤µ¶·|
+|z
+~{{¤¦£¥}f]c[TTleksleztl{u{red{tt
+¤rfkult|ddcztl|||j]\u|cbVddcztlllk}kd\u{{t||{zmµ¶·MRK*)(|ztlltts[TTlriredtsl|}lld||n²¬µ||u}«²«{zmlri¤ztlbVU{tt|ztt{uzttts|z||tts
+mttUTS^^qlks{u{
+¤
+{{{||lddztldc\ult
+}
+||}{{
+£}\UZ{{||}µ¶·¦§¨¤~|
+{u{uzt
+{{|
+ult¤¦mtt¤
+¤¦
+
+¦§¨¤edk{tt
+¦§¨¤llkult|
+ult¢¨©´|z|{||£tzlsle{|||
+
+]bZult{||{zm||{{|z¢{{t}{{t{{t|£¢{{tdc\tsl[TTkk]f]cf]c{{tt{tt{lek|
+tt{fkkmtt]cd}
+¤£¥
+|
+£²¬¶Ã¤¤¡{{£¥¤¤ult|}{||tsl{||llkedk¨©´}||{u{ldd{tt||slesle{{tj]\}kd\ek]dc\ekdredVTLb[UVTL]bZSKJlksµ¶·VTL*)(|{u{{u{ztlttsutsre|u{{¤b[U|zultut|
+iq]{{t{||b[U{zm{{t|z{||{u{tt{tt{«²«tslmttuzt|z
+}tts¤¤uztlritsl]cdMRKllkmtttll\[[|
+ztl{{{{t{tt|utsl{tt|zbVZ}}{ttmtt
+lldSKJlddJHF|z}|
+}lri
+mtt£¥mtt{{|
+}wl~¨©´¦§¨¤¤¦mtt|z¤¦
+tt{|
+
+
+{||
+ultu{{mttmtt£
+lks¦§¨«²«¦§¨¦§¨¤¦{||
+¤¦lks
+|
+
+ddcf]cµ¶·{{{u{¦§¨
+lks[TT\[[dc\|ztsl«²«|z}}{{d\\llktsl¤{{t}ttsdc\ult[[TUUYlriuztMRKtllllkylddc{{£²ult{||}
+¤tt{¨©´ztl{||tsltt{u{{ddc¤¤¦\[blldlddedkdc\{{tlldj]\{ttSKJSKJ]bZlridc\d\\j]\j]\lddekdtts²««UTS*)({tti\Vldd{tt}£zllsre{{t{{tllktsllrid\\yle¦§¨||{u{lldyletts}|{||d\\
+|u|{|||
+lrikd\
+kd\¤¦uztu{{uzt]cdUMR]cdddcd\\]bZult\UZd\\nsleu{{||{ttf]c{{tdc\|}JHF{tt[TT|utsl|mwUMRttslksultlkstts{u{¤{{£¥|
+|
+{||£
+
+
+{{t¡¡|
+lks{{{{
+¨©´{{¡{{{{
+{{nvlks»ÂÇ
+
+¨©´¤¦ultu{{¦§¨ut£¥¤{{tts{{{||¦§¨
+¦§¨\UZult
+]cdult{ttult¤llk|
+ultedk
+tts\[bf]cult¨©´{u{{{ttsmtt|
+tt{mtt{{¢¤¦}lld|z
+dc\v{tts|zd\\lks
+|
+d\\red{{}\[[tslSKJ||tsl{ttultdkVSKJVTLVZTmtt\UZredtllztl\[[SKJ{{t²««JHF*)(dc\ultd\\i\V{tt
+|~
+sred\\v{lldek]f]c
+|z||£
+zlltll{tttt{|z|
+llk¤|
+||}ek]|
+cbVlldmttd\\lldllkedk{{llkulttts~
+bVU[[T|sreddcttsf]cv|||sleb[U|utt{d\\\[bLKR¤¤{{llku{{{||}rfk}¤{{{u{zll¤¦¦§¨u{{
+¤¤ult¤
+ult
+¤{{
+{{²²§²{{¤tsl
+}|
+{||lldmtt
+¢¡¤¦¦§¨lri¢tts
+slemtt\[bult}|zuzt¢
+lld
+ttslriurfk}dc\JHFf]cultlldult{u{f]c}
+{||mttlld¤¦{{}
+¤{u{ztl|z¤¤{{ttslsleudc\ztl|tzlslelksekd{{t¦§¨{||ultleksleUTS{||d\\slett{vldd{ttsle{{tUUYztlult|
+sremttSKJcbVF=C*)(d\\tts[TTv{{tt{{tu{zmultred{{t}ldd
+llk|z\[blld{{|uu£|
+µ¶·ult|zf]c|z}ttsu{{]cdJHF}[[Tf]c\[[tt{ulttlllri{{}lekedkllk|z|u|udc\llkb[Ui\VUTSlddUMRkd\VTLrg]f]cf]c¦§¨|u|
+
+
+v
+¤¦¤{{{||tll¦§¨}¤ª³·|uztlks{{{{¤
+|
+}{{^fs}|~¤¦¤¦}tll|tt{¤¦tsllriullk}lektt{¦§¨¨©´}lldf]ctts{tt|
+uztj]\¤|}tzl}µ¶·ukjV||ztltll\[[ddcult
+ult{u{{{tlluzt|utll{{£|
+
+
+{{{u{u{{¤¦{||]bZlriUTSd\\u{{f]c}ult{||¤d\\{ttsle|uztl}u{{|{||{u{||
+¦§¨¦§¨{|||||u}JHF[TTkd\¤¤VTL74,ulttslttsbVU|wl[TTsle{tt{ttultvleklldlriekd||tll|
+ut|u}|{|||z{tt{{t¤¤|zult
+tslult}{||ekdf]cUMRVZ[\[b}||u{{ek]¤[TTlri{{|ddclridc\j]\lriultlek}[TT}
+¨©´}¤£²
+
+¦§¨{{~|
+tt{}uztlri}¤|zu{{lriuzt{||lkstt{
+¤¨©´¤¨©´¨©´{{¤¨©´¤||lld|
+|z|||z¦§¨¦§¨¦§¨
+tts{tt¨©´£¥
+lekUTStts
+}}|£{zm¤¤¤¤¦§¨{{tv{ttsVTLlldlldSKJ¤lekedk¢«²«§²uzttts}}
+¤£¥¤{u{{ttult¨©´µ¶·~tts||mttf]c}lldv{
+}tt{ztlrfkultbVU¤u{{|ult
+slev{{}{||cbV{{tedk{||¤¤JHF*)({{lddttsztlultcbV||rfk{zm}tllj]\
+uztuztztflddd\\|tt{¦§¨¤u|{||lri{{t¤|llklek
+«²«£{||||tts
+|
+
+|
+}mtt}d\\{||srett{¢¤lekztltzlkd\|kk]kd\{zm}{ttu{{lrilldf]cztl~{{tddcv
+mttrfkUTStsl{{|
+lld
+
+tslylult¤{||
+mtt{||{{tleku{{}|
+¤¦¨©´{u{lri¤¦
+uzt{u{··Ä¨©´}bVZsle£ult¦§¨
+}¦§¨²¬µ¨©´¦§¨lek¢¢¢rg]sle}lri{zmtzl{{t[[Tllduztu¤{{mtt¤}]bZ
+ultu{u{£¥ult
+tsllksVZT{{u{{¤}{u{}
+
+{{}lldsle|z{{ttslkd\ultlksult}ddcu{{bVZ
+[TTd\\{tt{tttygtts{{tlektllkd\|ulkslldtsl£¥FD;*)(|vtt{rg]||utsltsltll{u{kd\|
+vztllriedk{{£|uultzllld{{}lldf]c}{{ttll¢tts¤¦¦§¨|
+\[[rfk||uzt|zu{{lri{{
+{{|z||}{tt}rg]{{t|z}}|zlriuzt}lek
+lldllk~u{{
+llk{u{||{||tts¤{||vtts{ttf]ctt{£|
+{{t{{t¢ddc}u{{¸Á¹§²¤¦§¨¦§¨tts{{|
+mtt¤¤¦tt{u{{{{|
+||²¬µ¤¦{u{edk{{
+u{{¦§¨
+£¤¤£¦§¨¨©´¨©´¦§¨redtll¢¦§¨}£¥VTLztl}¤¤usleztlVTL{u{}f]c¤£²£¥
+|
+u{{mtttt{lks¤¦¤¤¤¦||z|
+|
+u{{¨©´~bVUtsl~JHFek]lks\[[¦§¨lrilri\UZbVU
+ultkd\zll[TTd\\uzt|usred\\uztmw[[TSKJ|JHFd\\ultJHF*)(|uztlredulekrg]ztl¦§¨
+ult}sre£ult|z
+ttsfkk|z}£sre
+¤¦llk{u{¢¤¤¢{||¨©´¦§¨¦§¨{u{lldu{{
+|
+uztultLKRVTL\UZlekuzttts{u{
+¤¤¦[[T{{lldultllk||uztl}redvlddtsl{tt¨©´uzt
+lldlks||~lri[TTtslf]cuttsltllv{}||||lks|||zult{{¦§¨¤¦¤¡¡¤¦¤¦|
+|
+¦§¨{{£¥¤¤¨©´¦§¨{{¨©´¤¤}²««{u{llk
+
+··Ävyfd||¤¤rfk
+}¤{||ztluztlri|
+lrillktt{|
+{{]cd]cd¤¦mttfkkfkk{{£¬¶Ã¤|
+}¤
+
+|
+{{
+mtt{||¸Á¹lldlrikk]lld
+
+ddc|zlld||ddcldd{{{{JHFUUYu{{lddJHFf]cldd||ttsllklriv{ddclldj]\dc\}}lri|¦§¨JHFJHFuztlld{ttztlllkjV[|z|zkd\uzttsl
+}|zztl}tsltts{tt¦§¨¤¦{||ult|zlek£µ¶·ª³·¢
+¦§¨£¥¤¦uzt]bZMRKlld]bZ|
+tt{
+¤{{tllk
+||u{{
+||zbVUtsllldfkk|
+tslsred\\fkkldd}|{{t}¦§¨{||
+tts]bZ{u{¦§¨~¤¤|||{u{tts{||f]c|u|
+tts¤¦~ldduztu{{
+
+|
+
+£}|
+|
+mtt|
+¡
+¤{{|
+¤|
+£¥
+ttstt{²¬µ¨©´
+¤uzt{ttut¦§¨~}
+~f]cmw
+}ª³·llklektts{{lrilri
+
+¤edkultJHFlks{{
+{{lksedk|z|z£lks|zuzt¦§¨¦§¨¢}|}|uVTL|v}slerr]tzl|z|[TT|lri}|tslUTSd\\|
+ekd
+uztyl[[T}~VZTlekvlldultztlf]c{ttF=Ckk]rg]²««UTS*)(slej]\
+}||uldd}}ttsrg]sle|utt{VTLsleztl}zll¤¤|¤¦¦§¨}u{{{{¤¤
+tts¦§¨¦§¨£¥¤|zlriUTSJHF[TT{{{{}¤¦|uzt{{t{||fkk¤¦tslmttsre{ttu{{}b[U
+}{||tzlkd\74,{u{ztl}ztl¤||uztmtt{u{¤
+f]clrid\\lddttsultult²}[TTlks{{
+|z|
+fkk|
+|
+¦§¨{{
+ttsu{{¢]cdtts{u{||\[[}|kd\{zmttsekdttsf]ctlldc\tzlJHF{||lkstll
+¦§¨
+£¥
+{{¦§¨lkszlld\\dc\v{redv|{u{f]cedku{{ª³·~llkekduzt¢|z¢ttsmtt}£¢{||tllkk]{||tll¢llklri|zVTLek]dc\|z|dc\{{t{||lksmttult¤¦mtt{{}{{
+¤|[TTsresle{||lld]bZrr]JHFttsJHF{zm|uJHF:97tsllrilld|}|
+}}
+uukd\v{¤¤¦|¦§¨tt{}{u{u{{lks||lri¤¦|
+|
+{||llkmttf]c{{{||{{t|zuztlekdc\tt{kk]lek||d\\|z|z{||||||kd\VTL{||tll£¥sre¨©´¦§¨|
+||
+UMR~}{tt||kk]}{{¦§¨{u{{{|
+{tt|z|{||{||{{
+¤{||
+¤¦}ttsuztUTSUTSSKJSKJ|
+}ut£¥ultslelksddcd\\lek||uztddctsl}¦§¨{u{
+\[b}{{f]c]cdJHFultllktsl||lddD;9lldbVUuztekd|z{ttek]|z¢|z|z¢¤¦|z|z|
+|yle
+ekd}||||[[TbVU{||||{{t
+|
+¤dc\
+\[[mttlld[[TSKJVTL}tts|
+\[b{{tj]\JHF*)({tt|z|u}}|u{zmdc\leklld|
+
+{{tslellk||uzt{||}zl||||llk{u{|z~{{v{¦§¨mttleku¤¦§¨llk{{ldd|
+{{ekd§²{tt|z
+|ttsldd{u{|z
+|u|ztllztldc\¤¦b[U[[TddcVZTtlldc\ekdldduztlri||{ttlek}u{{ekd{||¤¤¤}zll{{ult¦§¨¦§¨£¥mtt{{¦§¨{{{{¤mttek]lri||z¤¦
+|z{{tlldultttsUUYdc\£v|£··Ä}|v{s_qred}VTL]cd¦§¨¢tzltzlmtt{||f]c[[T|
+lksedk\[[}tt{|u{{}b[U{{d\\tt{|
+¤mtt{{{{
+¤¦§¨£²}|¤¦||redslej]\ultbVU£¥r]ZcbVkd\slelddkd\{tttll
+\UZVZ[dc\edkuzt[[T[TT\UZlld[[Tzll
+kd\VTLj]\¤¦>EC:97ult|z{{tzll ztl
+VTL|}}|£}|red{tt{tttllttsuult¤
+
+|¤¦§¨|ultdc\{u{¦§¨}v
+edk{{{|||
+LKRtslmttu{{ttsd\\ttsuztldduztj]\|tt{llklddkk]tt{|uldd|
+¢¤{zm¤|zlrid\\||ekdlek¤¦|z|z{u{{zm[TT|zttsUTS|u{{t||¤¦¤£{{{ttfkklks{{
+ª³·
+|
+]cd
+tt{fkktt{|
+|
+mttulttts¤
+£¥f]c|z¦§¨|z{u{
+{u{ult
+kd\SKJkd\tll
+}{{t{{t}uttslSKJJHFb[U|tslvldd|]bZdc\mtt|
+ttsVZTult
+|
+{{
+}{u{}··Ä
+£¥||bVU~ult|z}dc\ldd|ztslUTSSKJlld[TTslej]\\[[MRK[[T{{tlksllk{||{||mttlrimttddc[TTj]\}kk]lddtsl£u{{{u{\[bVZ[}|JHF*)(tll|z|uyleutkd\sle||j]\{{tv¤¤¢ddc}kk]ztl
+||}tts}|{tt
+tt{£¥¤|ztts{tttsl{{t{u{tsllriuVTL\[b[[Tedk|u¦§¨|zlektt{{{lddtts||leklddlldtll}
+
+tll||tsl\[[{||ult{{tMSS|z|zu{{|lddu{{|
+{tt|sleSKJfkkVTL{ttztltzl|u}{{t{{{zmtllv{ult{{¦§¨|znvultmtt
+£¥¤¦ult|z
+ª³·²¬µ£¥¤¦§¨¦§¨¦§¨
+ttstt{|{{tkd\dc\{{kd\ult}{tt}
+kd\iq]|zUTS|{ttllk[TTedklksu{{]bZVZ[lri]cdlek|
+lekllkllkkk]{tt¤¦{{tllk||u|ulksllkb[Udc\VTLjcVcbV]bZlddVTL}dc\\[[uzt{{tlksttslddmtt|z¤]cdlld{u{[[TVTL{{tlrillk{{tuddc[[TedkmttUMR>EC74,|||z
+tsl|utllkd\{zmldd|z]bZ|u}}¤¤tt{{zm¤¦|ztl{u{lks|z}|}£¥u{{
+||{ttf]c[[Tsre{|||ztslldd]cdtt{{{lks|
+¤lksfkk||tllSKJlddSKJ[[Tlek}ultekdlld\[[||uMSS\[b\[[lldd\\edkf]ckd\|zult|||z¤¤ultult}|edkf]c{{¤¦
+lks|
+{{mttmtt|
+{u{
+¢¤¦|
+tsl{{{{¨©´¤£¥¦§¨£¥¦§¨µ¶·»ÂÇ¦§¨}sreutsre}{{t{u{¦§¨{tt¦§¨
+|z¦§¨wv{{tukd\|ulldtsl¢{{t¤¦
+tt{lek
+lks¤ult¢£¥
+}u{{ulttts{tt~ultllk|||£¥llk¤¦u{{¤tts|
+kd\||ult|zllk
+kd\usre}VZTekdlksJHFUMRlri|
+]cd
+¢bVZ|zlldUTS|ulld||dc\sleVTLJHFJHFJHFztlJHF3+*{u{u]bZtsl|u{ttut{{tjcVb[Ukd\ttssle£¢||{u{
+{u{rfkutfkk}llkult{||}
+|zf]c{u{zll\[[tt{
+lekdc\\[bf]cult{{tllkllkldd}uf]cv{|uultVTL¢uztttsslef]c||ddc\[[|z}u{{ldd
+
+||£ª³·|
+tllrfktts¤lek{||{||
+tzl{{t¦§¨|
+{u{|
+}lriedkllk}{{¦§¨|
+|
+
+|z¢|
+
+
+{{¦§¨¤||bVU¦§¨ª³·redtll£¥ÃÄÆ¨©´¦§¨
+|udc\}|uv¢~]bZuztkd\lek~\UZª³·|
+bVZultf]cf]c}}}¤fkk{{{{mttUTStzl}tllultult£
+{{tultdc\u{{uztekd[[Tlridc\|zlrisleddctzldc\VZ[lriUTS\[[ddcVZT|
+fkk}bVU¤tt{|tsllld{zmlriulldf]c{ttUTS|z¢JHF*)(lksuztuztzlluu{tt{tt£uzt}{u{|bVU|u}tll}{||ª³·¦§¨uzt¢¤¦{u{£¥lekvtts{||}v{{u{{||{{t{u{SKJlld{{t|
+{u{
+ult{u{lld{||{||{tt}j]\}s_qzll}tsl|ud\\zllcbVtslmtttsl\[[tll\UZ{zmuzt¢u{{ª³·u{{|
+{{t}¦§¨ttslek}uzt{{tult}{tt{{~ttstt{{{uzt
+¤¤
+tt{ldd¤|zu{{ª³·|z|
+¢tsl
+tt{tt{ddcddcSKJ{tttll¤v{
+}£¥¦§¨£¥¨©´¨©´¦§¨µ¶·||¤ztlmw{||uztfkkMRKlrilrillkddc
+}{||edk{{f]cleku{{u{{mtt{{tsl|mtt¤|z{||¤¦§¨tsl|dc\{u{edk|JHFVTLVTLiq]VTLu{{]bZlekllkuzt\UZttsJHF]bZvJHF]cd]bZSKJut}ub[UlldcbVzll|
+}|
+{{t|zmttmttJHF*)(ldd{zmvu{zm}|{{tut|v¤¤utv{{||tts
+|u¦§¨¤{tttts{zm}{u{tll
+tt{ztl|
+{||}v{||llktlllldlddlri£}{{f]cult||}mttf]c||ultrfkulttll~}{tt{||{ttddctzluzt£ttsuzt||edktts¢{||²¬µ¦§¨{{{{tmtt||{tt¦§¨¦§¨}|tts}d\\lekttstt{|
+}}¤£¥tts{tt¤¤¤ekd}|b[Uzll{tt¦§¨¤¦}lksult{u{~¤¤²¬µ}¤tll¨©´v{£¥v{tll£{{|z|zlld
+f]c}{{
+]cduzt¤ª³·¢¤¦¦§¨}£{{¤¦
+}v{[[Tuzt{||{{tVTLcbVllk|
+tzl[[TuztUTSuzt\UZVZ[ekdtll\[[uztUMRlri[[Ttts}£¥|z
+kk]ekd{zm||ztzl[[Tedkv{:973+*|zttslld{zm}||ztlldd¤¦¤¤|utsl||¦§¨
+¤¦§¨£¥
+¦§¨¤{ttµ¶·¤··Ä
+{{t{u{||lrif]c{{\UZ\[b¤f]c{{
+¤
+}||[TT}\UZ{u{sle~ut|z|lriuztSKJ{||ultlksMSS|
+{{}|zlks¦§¨{||||}µ¶·|uzt}{tttts||ult}v¦§¨uzt
+ª³·tts
+lddlddtsl¢
+£¦§¨¤µ¶·lks}ultlks¤ult¤lddldd~||¤}
+ult¤¦tll}¤¤¤|zlridc\|zekdlri|
+tslf]c¤||{{t{{
+uztµ¶·¦§¨|z|lldllduztkk]]bZ{ttllk[[T|
+mttddcVTL{{}f]cUTSlkslkslri{||lksttsultultlks£}|{{tdc\]bZ|z[[T[[T¦§¨LKR*)({{tll{zm|z
+{{t£
+}z}|{tttt{uzt£}{||}}|ddc
+{u{¤{{¨©´{||ttsleku{{ttslek\UZlddVZ[£¥}lkstt{{||tllttsrfk}|v|lddrg]v{
+utlddlldekdtzlekdtlllld~{{}\[[f]c|z{||llkllk{tt²««£¥
+|
+lldtts{u{{{{{¤
+ddc¨©´ttsult¤ult{{¦§¨|z{{¤}d\\{ttv{}tt{tll¤¦
+¤f]cut{{\UZrfk¤ult|||
+uzt¦§¨llk}sle{u{d\\]bZtsllrillkmtt{ttmttd\\|||
+¤
+
+¨©´v{
+ult|
+tsltzl{|||lriuztlksztl|
+|z{{t{{t[TTlldekd}d\\{u{d\\[TTJHFVZTuzt{||ekdf]c{{lek||
+lrizllztltzl|z{{t]bZ]cdu{{²²¬:97*)(kk][TTu|uzt
+}²²¬}}sle}|¦§¨¤¤¦
+ult¦§¨¦§¨}|²««¤£¥£{||edk|z}{{d\\]cd|z}£¤}~ylemttkd\ddcf]c{u{sre}ttskd\zlldc\llktslttsd\\|
+ultu{{ttslrilksddclksddc||lks}¦§¨}|
+|z{{
+{ttrfk{zmtsl{{tv{{¨©´¤}tts|
+{{t¦§¨|¤tts£¥¦§¨|{{t
+¤v|¦§¨}}}}
+\[b£²}ddc{{ttllf]culritsl}|{zm||}}]cdu{{u{{[TT{{mttv{|
+ztl
+{{tll{u{¦§¨¤¦
+
+{{|z¤
+|z|zlrikk]|z}tzl¤¤tllllk{tt|\[[kk]||tllVZT|
+u{{tt{|z]bZ}[TTtt{lri{||ultlld|zllkekd[TT{||mtttzltll{||²««F=C7-2utztl||{zmsrekd\{{t¤¤sle¢ult
+zlut{u{}}mtt£}¤{u{
+¤uzt
+|
+lksmtt{ttu{{{{tuztdc\tt{ult{||¢
+||tll[TT{{tddcut{||\[[{||ekdlld|{{t{||tts\[blks|¤lrilks}¤llklddllkllkf]c\[[
+tts|ulldu{{£¤¤¦
+edk
+¤}
+
+}
+ut}|u{||}|ttssre}}£¥£}¤u
+}{{f]c{u{zllldd£ztl{ttttslksedkFD;kd\zl[TT¤}UMR\UZ
+|
+lks
+edk
+UTS
+¤u{{u{{¤|zyl¦§¨{{t}{{tllkd\\||{{|
+ult{||]bZ{{tlddVTL¦§¨{||||{{t|
+mttf]cuztultlksllktt{{u{edkrfktll}lri{{{tt|u}ztl[[Tztl~|
+{{tlldlld²««JHF*)(tsld\\|zztlwl[[T}v{u{{
+}
+{tt}~zll£}~¤ttstts{u{|z¦§¨¤{||¤||tlllritt{\[b|
+}¤¦ekdldd|
+|llk{{t|z|ztsl}{{ult
+{{tcbV{tt}||cbV|u{||¢VTL\UZ|¤¦{{|
+|||uyle|
+{tt|
+tllllktts|ztts||~|
+f]c{{~|¨©´lld{u{{{lri{{
+
+£¥{{¤ztl¦§¨}tlltsl}f]c{u{tts{||[[T¢d\\zllj]\v
+SKJv{sre\[[}|
+
+{{mttf]c}tts}tzlVZT}\[[ultdc\lri|
+{{tu{{¤¦¤¦
+ult}ddc}|VZTVTLuztmttJHF|z|zlld¢}¢lld}tts|
+ultf]cddc[TTtslf]c{{trfk>EC{{tVTLlldllk{ttfkktsl|z]bZ¢£:97:97}||tll|u¦§¨{{t|
+ztl{{t¦§¨|u}u}¦§¨|
+ultdc\sle
+
+rfk|v{¦§¨{{t¨©´|
+{||vtt{¦§¨{{t]cd
+tt{uzt
+{tt¤¦ddclri]bZrfk|
+{{t|
+u{{ultlriredu{{|r]g{{t}ldd||lddredred¢¦§¨¤¦¢mttUMRu{{{tt{||srett{}{{ª³·£¥¢||rfk{||{||ttslri
+{||¦§¨}¢{tt
+~f]cv|¤¦\[[v
+tt{llk|u|z|
+¢
+||lldtt{ztf}¨©´
+{||dc\f]c}}|}kd\lekVZTlrisleredzlltllztlsreVTL{{t£
+v{{lks|zuztsle
+\[b]cd}~uztmttttsmttddc{|||z{||sleJHF|\[[[TTdc\}lri|z\[[¢]cdrg]ekdtsl||ddcuzttt{|lld|vdc\u{{SKJdc\tslVTLlld[TTsre||lriaWMSKJ|z£D;9*)(}tslu
+}£¦§¨£{{t¦§¨|lekaWMª³·
+ut£|
+}£²¬µµ¶·}|[[T[[T]bZmttd\\{zm
+tsl{{t||}lriztl}{ttldd}{u{}ult
+|
+|z|zekdu{{f]cztl
+¦§¨tts}ztfddc{{tsre||{tt{||¦§¨
+¢lksult¤tt{llk{{sle{{|
+¦§¨
+{{tult}v¤¦
+llktllcbV
+|z|ztltt{¦§¨{||mwsresleult{tt
+}uzllutylelritll£¥tlltzlkd\b[Uddc}lek¤edkut|||
+u{{|zllk{{|tsl¤u{{}lld}UTS|z[[Tultuzt¦§¨tt{mtt{{t{{tlld]bZbVUultultUMR}{||
+b[Uztlf]c{{
+ultult|
+{||{{{{kd\tt{fkkf]cd\\utzll{{tlrilridc\\[[ekduzt:97*)(tzlsre}{tttts¤¤£
+²««|
+{tttts||z«²«{tt¨©´£¥¤¤
+
+||¦§¨¦§¨¤¤¤ddcldd|
+]bZ\[b||tt{v}b[U|z|{||u{{ldd{u{}kd\zllkd\lekv{kd\edk}{{|
+£tts[[T{{mttdc\]cdSKJlek
+lkskk]{||tsllldllkslelld[[T{tt}£¥|
+£¥ddc|zldd}v{¦§¨ult¤¦uztttsldd
+mw{ttultv{{||¤|tlltsl{{t{||\UZ{{µ¶·¤¦|{tt£¥
+SKJttsjcVldd]bZ|¤}|lekf]cdc\tts¨©´{{}lri
+{{}yledkbVZj]\[[T|uekdd\\{{{ttddcttsf]c[[Tek]sleultlksFD;zllztl||tt{UMRfkkultu{{|uJHFred}}{{{||\UZztl{||||z]bZkk]dc\\[[UTS]bZ¦§¨:97*)({{t{ttlddred}¤¤{zm}²²¬
+ztfztl¦§¨|£¥µ¶·¦§¨¦§¨
+¦§¨£¥¢}¨©´{||{tt||{||ddc{{||lektlld\\lld¤¦}sredc\u{{{||sleSKJ|tlltllzllr]gmtt¤¤{||tsl}¤¦|z{{tuztd\\||ddc¢|ztllrittsztl|z|||{u{ut{{lld{{t}}|lekult}¤tt{tts{{UTSlksttslritts{u{||¢}|uek]¤|u²««{||tsl{{t||{||tts|z
+{{t£¥\UZ£ddcztldc\VTLVTLek]tllª³·{ttyfltt{\[[}[TTtt{leku{{VTL]cduzt
+u{{lksd\\|zf]c¦§¨lri{u{j]\edkttsllk]bZllk{{\[[SKJek]tll|vVZT[TT{||dc\ldd[[Tvlksf]c}ttsf]cJHF]cd{{lektt{fkk}v{|zsle\[b~lrisre]bZ[[TFD;||:97:97rfkkd\{tt£¥¢{{t£|¢²¬µ¤£¥¤¤²¬µ¤|
+µ¶·¦§¨¦§¨¤¦¦§¨|zult}¤¤¦§¨{{lektts{{tllk{u{
+¤¤¤{{{ttb[UbVZtsl|ult£ztfv{{u{llkztlUTS{{sre¤|mtt||
+mtt}ek]}{{\[[lrisle{u{}rfk}£¥lri||
+|
+¤}¤tslultmtt
+||
+llk|u}{u{}ttsllk}¦§¨{||dc\{||ult|z{{ttslult||£¢uzt¢£¥¬¶Ã£¥²¬µ|{||{||
+lldv}}ultbVUf]cldd}edk[[Tlriult¤ultlriek]{{tdkVmtt}ztlulttt{llkUMRLKR}{tttts{{\[[ttstts}|kk]llk|
+||£¥uztlek¤}{{f]cJHF{||VTLlri}|
+mttllk\[b{u{ultllkttssre{{trg]|zuztMRK\[[dc\¦§¨:97*)(dc\ztl}||¤¤{u{u}|¨©´¤¦{||¦§¨«²«µ¶·¤¦¤¦¦§¨}¤u¦§¨£¥²¬µuzt²««{{t¤¦{{{u{SKJ[TT|zkd\u{{
+UTS||j]\{zmldd}rfk{{tll{tt{tt¤£{||JHFtslv{{{tu{{uzttts|zlldd\\¤¤v{|z}|ullkf]cultult|u{tt|z{||¤¦v|
+ylult{u{|
+{u{{||ztl
+ult[TT{tt{{[TTtlltsl{u{tlltslred}{||¦§¨tts¤¦¨©´
+{tt|
+uzt{u{||¨©´
+||z{tt{{[TT]bZb[Ulriuztdc\{tt{{tredult|z{||{{t{zm{{t{{tVTL
+\UZttsd\\}ddc||\UZek]SKJ{{ttt{UMR{{td\\VZTUMRlri{ttddc
+||}
+d\\tsltts[TT|
+}|u{{zllri}ddcUTS[TTlektslFD;,55}yle}ut||}{{|}
+¢¤¤¤¤~¤¤
+
+£|sre|z|ulri|
+tll¤
+u{{|z
+}ult|v{||dc\£¥fkkleklks~£|{||j]\tll~{u{ututtts{u{}{||uztuztllklld\UZVTL{{|z|
+¢¤¦lrikk]{{t¤}tllrr]{{ttt{lddf]c
+v{¦§¨lri¤¦§¨¦§¨£²|~{{
+|
+]bZ}~fkk}|llkb[U
+{u{£¥||d\\||
+tzldc\cbV{{dc\
+j]\ddc
+}§²|zu{{tsl}¦§¨{||
+¤leklek}zll|zv²²¬
+sle
+}v{VZ[ultultbVZ
+}|tll
+SKJVZ[uztUUYUTS|
+ddctslllk¤¦§¨{{}{ttleku{{lri{{{{tztltll[TT¤{{{ttut}ddcUUYllklritt{ztlVTL|{{tlddtslmttlriztltslUTSJHF
+:97*)(}{||ut}tll¦§¨{{t¤¦¦§¨ztlµ¶·µ¶·ultuzt¤£¥{{t¢|
+{|||u|}|zlks{tt
+
+|tsl¤¦{tt¦§¨||v{ddcutJHF}tts}bVU{u{{{t{u{{{
+slerfk{{|
+{{tult\[[]cd[[TmttlriVTLlri|
+ztl||lld|{ttd\\{{}{{tll~
+¤||}£¥¤}
+¤¦lri{tt{||llkzll|
+slellk{u{sletll|u||}lkstzl||ulld|v~¤¤{tt{u{\[[}{||uzt[[Trfkd\\{u{
+¦§¨tsl|z|uult{u{UUY\[[ldd{{t{u{utult{{t}
+ultj]\lektt{ztllriddc{ttb[ULKRVZ[lks
+f]cttslddult||{u{ultut{{tbVU{||VZT\[[{{ttll¦§¨VZ[mtt{ttmtt{{tf]cSKJ{u{|\UZztldc\SKJv{tsl{{tuztuzt|
+\[[VZTUTS¤¤:97*)(||kd\¢{{t¤¤ztl
+¤¤||sretts£¦§¨tsl¤¦ª³·µ¶·¦§¨¤¦§¨ª³·¦§¨¦§¨tt{}|z{u{£¥UTSztl|z{||
+tts{||¤¦ekd¤bVZekdu|uVTL\UZ{||f]cult{u{}|
+lekv{{u{leklksf]clldUMR{{cbV
+ddcSKJuztddc|usle{u{}kd\ult}¢¤¦§¨¦§¨¤¦«²«£¤}£¥{{t{{¨©´{ttdc\
+zllztlut||zv{{tttsl|
+kd\}j]\~£
+
+¤¦{{{tttts[TTmttu{{kk]leku¢
+
+{ttuztlekedklrimttd\\\[[||{{ultwl{u{UTSedkd\\|UUYtllf]ctts}|z||UTS\[[llk¤¦UMRrededk{{|lek|
+sre||utddclrimtttt{{u{|lri\[b\[b[[Tlri{||lldf]c
+¤¨©´mtttlllekdc\uuttsmttv{[[Tekd£¥:97*)(ztlu¢tsl}£¢||¸Á¹¨©´£{tt£|¤¨©´|{{¢}tsl}{tt|zUTS]cdlritll|
+lkslldtsl
+mtt||uultwltslrfk}j]\\[[uztleksresre{||{u{£
+||{||d\\}{tttt{|z|ulks}²¬µ¢|u
+lld}ª³·¨©´|z¤
+|
+tllu{{
+|||¦§¨u{{
+|sle}£¥{u{}ldd¤
+¦§¨£¥¢v{|umwtll{{t}}ttsfkklri{{t{|||ztts{u{b[U{||i\Vv¤¤llk}tt{lriSKJb[U]bZ{u{llk{ttdc\uztfkkddc{u{||}tzl{zmtsl{ttztllldllktt{||lri{u{slef]c|
+{{tMRK
+sretzlsretslUUYUTS~ttsldd¦§¨{||{u{\[b[TTf]ctslcbVtlltt{b[UUUY{{kd\ultJHFleklld{ttfkk}UTSJHFVTL|z}JHF*)(}ut|z¦§¨
+¤¤||}£{ttµ¶·£}{||v{¤¦¨©´||¢uzt|ztts|
+lri|uedk]cd]cdf]ctsl{u{|z{{tt{ult¤¦|bVUlrif]cJHFbVZlek|ultvslezlltt{}fkkj]\}{ttult{zm{||||¦§¨}|
+~n|z¤
+tll{u{
+{{t|zddctll¨©´
+ztl{{|z|}
+}}¤¤
+}{||||||||~ult
+zll{||llkkd\lek£}sle{tt|ullkllkzll~[[Ttlltt{[TT\[[ddcSKJutredu{{tt{|z|zlridc\tt{lrif]c{u{{||{u{lkslektllylezlltslmttsleultJHF{{ek]lld
+zlllldekdztl|z]cd|
+ekd¤¦UTSultJHFVTLkd\v{sle|tt{tll{{ttts}lek{{tlks]bZ¤¤F=C*)(lld|z££¥µ¶·¦§¨
+¦§¨|
+tslv£tll~rfk{{tts{||ttstll||sremttu{{fkk|
+uzt{ttuztmtt}{|||
+|z{||uzt||
+tts}tt{f]cJHFfkk{||ddc{tt}ult¨©´
+ult|zddcsle
+}lrillk|£
+£sle||tll|{{||lrilks¦§¨|u{||
+||{u{tll|ztt{¨©´¦§¨v[[T|u¤¤¢|
+ztl|uwlzllsleuztut{u{yfdllklld¦§¨{||
+{u{cbV}¤¤||ttszllb[U}ttsrg]ultUMRrfk[TT{||ttslldllkJHFedk{zm]bZred||cbVlkslks}|ultrfk
+ulttts|
+ult¦§¨[TTztlVTL{{|ult[[T{zmfkklrilekJHFdc\tsl~lddlldlri|{{tztlSKJ||mttiWUd\\lritzl}ldd{||tzlfkk²««LKR*)(u{{¢£||²²¬¦§¨²««
+|¢£¤¤¦§¨v{££¥¤¦§¨|z{|||z
+}{||²««¨©´¤
+{||lkslddlrilri{{||u||ztl{|||uJHF|rfk{tt{{kd\lek
+lksf]cmttbVUult[TTtts]bZdc\tslv{ztlttsekd||uddc\UZsle{ttu{{tts
+
+|z{tt²««|z{u{¤¤tts
+||¤\UZztlwl|¦§¨¤mw||urfk
+
+}|f]cultsleu{{}{{£¦§¨uzt\[[{||
+ut}}zllztfVTLlekddc}lddultkd\mtt
+ekd]bZ||SKJuzt\UZdc\kk]{||zllv{
+£¥|
+tts{{t{{tUTSdc\tt{JHF]cdddcjcVlriyflu{{¢{{[[Tmtt|z¤lri|zlks{{tmttVTLredcbVlksdc\ttsuzt||tsl{||ddcfkk]bZJHF*)(|
+|z|u}|²²¬¢~}sre²««¨©´£¥£¨©´¦§¨}
+|z|
+tsl||tt{¤¤¦¨©´|
+u{{mttlekulttsltts{||lldslelldult¤f]c}fkktt{
+f]c{{tlritll|
+lddult
+ultttslld}{u{{zmtllultekd|£¥
+{zm|uultult£|
+ttsddc
+
+{{tedkred¦§¨{{}
+tts}¦§¨¤¦£¥|
+llk{{
+£}{||ultª³·£²¤|u|usle¤¤}sle£¥yfl[TT{||
+ddc{||lri¤¤{tttsllks£i\V|u{u{{tttll{u{¡{{rg]tll}v{ttsredtslztltslVZT\[[ekdu{{ek]ultbVZf]clek|ldduzt}rfk¤¤lksu{{ult|z|
+¢{||lld[TTf]clri|{||]bZddcllduzt|
+llduzt}bVUtlltlltlluv|zfkktzltslllkllklek\[b|zVTLsle¤¤\[b:97]bZrr]ut£¥²««¦§¨²²¬¦§¨¦§¨«²«¦§¨µ¶·«²«
+²¬µ¨©´}¤¦¤¦£¥ztl|\[[{tt|
+kd\lld{{t
+ultu{{tt{ultu{{lksmttedk{{||{||tll|zf]c||kd\tlllldlld}llk||{{|zultedkekd{u{||JHFtllUTSmttultuzt\UZ}|zd\\ult]bZd\\tts{zmtts¤¤|||[TT
+|
+|lld|||z|z{{|z||¤¦¤u{{dc\{u{llk}}¤|¦§¨||v{||||||lks}{tt
+|uultultleklek}¦§¨||ututfkkddc}wlj]\{yfj]\f]c|uekdllkv{ultd\\i\V[TTv{v{ttsut¤ek]ldd||\[[ult{{ttllfkk|
+f]c¤uztldd{u{uzt}u{{|
+UTS
+ult{{t]cdVZ[}¢uztJHFMRK{{t|zSKJ\UZlld}{{llduztllktll|JHFJHFVTLllk¦§¨\[[&&ek]{||¤¤}|¤¦§¨²««£¥£¦§¨¢¤¤||¦§¨¨©´¨©´{{¤ldd|
+|z}{||}|
+lriultlksmttlriUMR{{sle{{lriult}bVZtslfkk}{u{ddc{tt]cdUTS|
+mw{||d\\|dc\llk£¥{||lri||{ttu{{ultldd}{ttUTS
+VTL
+rfk{u{slelritllztllld{||}ddc{tt|ttsv|b[Uuzt|
+
+
+
+{||
+sle{{tttsult¨©´¤tsltllultred|ulddVTLcbV¢}||
+
+ldd||}v}||¦§¨¤¤ttsttsddctsl
+lekSKJd\\{{t\[[dc\}ult
+{||¦§¨llk||¤¦v{{u{mttlldf]cbVZf]c}ddcttslek}\UZv|uultredUUY{zmmtt«²«|z{{tult||||~lrilri¤tsltsl|z|zf]cu{{{tttll£¥llklddekd|ztzl|ztl}\UZlek\[[VTLslemtt¤¤MRK
+%&tsl¢lld{tt¦§¨¦§¨¦§¨µ¶·¤¤¤¦¨©´¦§¨||ult¦§¨¤¦uztuzt|z|UTS|
+{{|
+[[T\[[]cdlekd\\{ttleklrif]cldd{{}sle}mttSKJllklldsle{ttddc{ttj]\llklritlluzt|
+lld¤|¤}{ttbVU]cdVZTlldult£slef]cdc\ztl||{||||mtt
+tsl¤¦mtt{{tlltt{|tll{{sleztl¤¤{u{|||ukk]v{dc\¤¦§¨v|f]c¤}|v}f]c
+}|||u¦§¨kd\||kd\}\[[ztlsre{tt{{t{||sre[[Tlddkk]{||bVZ{{t{{tzllf]clek¦§¨¦§¨{tttsltt{ztllekult}{{tf]c
+|uddc{{j]\{u{f]c\[b¤£
+|zlek|mttlek¤¦]cdtts|z}[[T{ttlddlldlld}ekd\[[dc\lriu{{{u{}llkmttf]clddddcMRK*)(VZTmttztl¤¤|u}|¦§¨¦§¨¢}
+¨©´¢¤{{t¦§¨¦§¨£¥¢|zlek
+llktsl|z
+}[TTd\\{{{u{}f]cttstsl{tttslmttJHFlld[[T{{llkj]\VTL||ldd|z{ttllkult¤¤
+|z{||MRKutll|v|j]\}lldsle
+ulttts}|¤¦}|z
+}}tt{¤|z}{tt}utrfkb[Utll[[TlksbVZ}|{tt
+rg]}¤¤¢}ulttt{tts}}£
+lksrfk|j]\{{tllkllk}ut{u{lri}ddckk]|{u{ttstll|
+lekb[U{tttts{zmuzt{ttuztztlldd}{{}£¥¦§¨}|tsl[[T||}tllyl\UZ|
+§²}[TTVZTtlllri|
+
+tllztlrfkultd\\ult|zu{tt{{t{{tlld{||]bZtzl{{lekmttlldztl¦§¨dc\>ECtts¤¤{u{}|
+£¢¤¦§¨¦§¨|¦§¨¦§¨|z{{|zuzt}SKJ|
+]bZVTLkd\lld]cd\[blek{u{{tt{{ekdlldult
+
+{||{tt{{t{ttSKJlld|
+¤£lriuzt|
+{tt||u{{u{{{{|
+ulttt{lri¢²««
+|zllttstts¤¦tt{
+kk]¤¤£¥ut}{u{
+tlltts}
+¤¤tts}¤¦v{|u
+mttldd[[Tlldsleztlult¨©´£¥llk|lddztl{{tmtt{tt{u{zllut}{{t||}||tsl{||sle[[Tlldlri{{{{tt{{u{lksuzt{||sled\\SKJ[[Tuzt{|||}{u{|
+tsl|z{|||||
+lks]bZmttslemttedktsl¦§¨mttldd{{t{||ultttsj]\llklld{tt}lek{{ttstll[[Tmtt}lek{||{{tlldlld²¬µ]cd-1+tsl|{||··Ä¤¤£¦§¨ult²¬µ£¥|¤¤¦§¨¤¤|¨©´ª³·µ¶·¤¤|z
+}}¤¦|lddu{{uztllktt{£lek{u{
+|ztlu{||{||}}}kd\lld
+{||u{{£
+zll¦§¨lkstzlmtt
+tts{||ldd{||
+mtt|z|}}ddc
+{zm|z{ttlriddc}¤}tt{{{{{¦§¨{{tllttsfkktsl
+{||{tt{u{d\\SKJu{{rfkv{¤zll{{t||{{tu{||tts
+kd\tsl¦§¨||lekut|u{{ztlsre{||]bZtsl{||tlluztuztsle{ttedkzll|ztsltllj]\zllslelld|{tt||tsldc\tsltt{lrikd\slered{u{lddddc|u\[bllk
+mtt¦§¨SKJtsl
+lrib[Uedk{{ultedk}|ztll}zll\UZllktt{ttslksmtttt{[[Tultlri{{tlrisle\[b¦§¨LKR
+%&££¥£¥¤£²£¦§¨}£¦§¨¤¤{||¤¦¤¤··Ä¦§¨¦§¨£
+|{{{tt}{{{{t|
+|utll
+|zVTLlddmttmtt
+lks¦§¨ttsult|z\[[¦§¨ztld\\tlllld¤¤{{tsl{{sle¤
+|
+lld||{ttUTSlek{zm{{LKRekd|ukk]¤¤|z{ttttsuuzt}||{{t{|||u|fkktts{||{|||z£{||ttsu{{lddlddd\\
+tts~¤[[Ttsl||}}}|u{{t\[[¦§¨j]\lriSKJ£¥}||}||ztzl}{tt}ldd|{{ttll{||¤¤lddrg]{u{lrilri\[[|
+mtt{{t|z{{tVTLbVZztl{{ttsldc\]bZllk|ttsldd¤{u{|tt{u
+
+|u{||[[T§²{{\[b¦§¨tt{b[Umtt{{{ttrfk
+{u{UTSlritlltts}ult{||ddclri{||
+tsl|
+b[Uttsllk[TT\[[¦§¨ek]FD;¦§¨¤¦}¨©´¦§¨µ¶·¦§¨¤¤~£¥¦§¨¦§¨²²¬ª³·¤¦¤
+¤¦|
+¤¨©´¦§¨{{t||{tt|
+lri{u{llklri\[[{{{||{u{dc\£{tttslzll||{tt£¥}}||
+sreut{||ddc}
+ttslrikk]llkllklld{{t
+UMRttstslultuzt¤¤}{ttultlekekdlriddcu{{}lldtt{uzttts{{t|
+}lddult¢~|z}SKJ{u{v{sre|ztl}||||mttllk}{ttv{}ldd
+\[[¨©´lldjcV}]bZkk]bVZ{tt}u{zmVTL\[[|
+\[[f]clddekd|sle{ttutf]cVTL|UTS¤¦]bZztluztlridc\}rfk\UZ|z|
+u{{{{tts}¦§¨¦§¨u{{¦§¨tt{u{{|z}|lrilddf]cVZT{||UTSttsVTLtsl~dc\ultu{{ultllk¨©´UTS)+2||¨©´¦§¨«²«¢¤|¢¤¦§¨¨©´zl¦§¨
+{{t|||z{{ddc{||lks}
+uzt{{t}{u{{u{utlddf]ctllztluVTLult|d\\ultVTL}{{llkllk{tt
+£¥{u{u{{ztltts¦§¨kd\JHFlri|tll¦§¨¤¤|||¦§¨lld|tllsle|
+
+ztl\[[}{||tt{|
+|
+zll{{t}llkdc\yleutlltts}{tt}uzt¤¤}{tt{u{ttsdc\{||{{tllkztlztflddlrillkddcek]|zdc\|zdc\lddUTSf]clekred
+¤¤[[T{{|u{{t}edk}|¤¦
+srett{{u{lrimttuztddcekduzt]bZ¤edk|ziq]lks{||sletllutultµ¶·{||uztu{{dc\tts{{dc\
+tts\[[|zddc{ttuzt}{u{tll¦§¨\[bLKR|z
+ª³·u¢}¦§¨v¤¤|
+¦§¨||£¨©´£¥··Ä¤¦
+¨©´¦§¨¦§¨ª³·¤¤¤¤¤¦||||fkk{{{||{{£¥}ult{u{tsltt{}tslldd
+¦§¨dc\rg]llk{ttlldsleut
+ult}llk{||d\\|u¢¤|
+{{llkdc\]bZttslek|u
+ldd«²«{u{}cbV{||¤¤{ttu¦§¨¨©´{tt£¥{||{{
+||z{u{
+ttsult{||fkk\[[u{{{u{{tt|{tt{zm{tt|u|ldd\UZsled\\kd\{tt{{tlldmtt]bZekdtts}bVZ}
+llklldkd\SKJddc{u{ztlllktzlb[U{u{{tt{{tu{{lri||r]g¦§¨||¦§¨
+ucbV|z¢¤¦}|
+|zekd§²|z|zmttuzt||d\\UMR¢||lksf]c{{t¢]bZ|uuztmtt[[Tttslri|zdc\JHF}tll}[TT{ttultd\\¦§¨MSSLKR¤¦£¥v{||
+¦§¨¦§¨¤¤²¬µ¦§¨|tzlª³·¨©´£¥±¯¦§¨¦§¨
+¦§¨£¥¤
+¤
+
+edk
+\[b}µ¶·lks¤¤¦
+||¤¦||llkztl|z{{t||
+lld|utsl{||
+}sleu{{|z\[[ttsu}ekdllk¤¦tt{ddctzltsljcV||¤¤
+
+
+{||¢|zzll}||{tt
+u{{zll{{t||{tt|tt{tsltts¢tlltt{tt{\[[ultllk}lks¤¤u
+{{t|}tts{u{||tts
+||}|{ttsle{tt[TTkd\tsl{u{{{tkd\{u{v{JHF}|ztllri{ttultbVUdc\{u{lek}ttsttsut||{{ut«²«¢{||ztl|z£¥¦§¨sle|
+tzl£
+|
+]bZ|
+]bZu{{\[buztJHF\[b{tt]bZyle\UZ{||tllredVZTek]fkklddlekedk|
+ttsu{{]bZ]bZ|zv{ult|||sle\[b¦§¨MRKUTS|
+cbV£¥~}|znsle|
+{||¦§¨¢¦§¨¨©´£¢«²«lld«²«¤¦¡¡ª³·llklri|u{|||u{{ult{{}{{lkslldd\\ut}}ztlutv{lek|ured
+{u{{u{{tt}lddldddc\sle
+|¦§¨|z\[[{||ult{u{\UZllkf]cf]ctzlsreSKJ|tzl[TTut
+sle|u[[Tu¤¦§¨¦§¨{||
+tsltsltsluzttts
+}|u}uzt¤ldd{{tldd||ztl}f]cuztult|u|ztsl¤¦}¦§¨ult
+}}|ult{||d\\}ult|{{t||u
+yle{|||usle{{t¤¤||tsllldFD;uztllktzllld\[[lld}dc\bVZSKJtzlztllriultztlkd\¦§¨ª³·{{tkk]ztltsl
+uztu{{mttv{u{{{||lksddcllkMSSlldult
+}{{tUMRf]clektll{{tlld{||u{{tll\[[dc\]cd]bZlriutult}~UMRf]c£JHF?;C£|}}¸Á¹¦§¨¦§¨¢¦§¨¤¦¤¦¦§¨¤¦u
+¨©´¦§¨
+}|ztsl£¥uztUUY¦§¨}lksultlksmtt
+|||¤¦{u{}{{t|||z}ldd~{u{¤cbV{{tuu{zmj]\||¦§¨ttstts|ztllf]c}|lrilriulri{tt{||zllut|¤
+¦§¨|||||z{u{{{ulttll{u{u{{tsl{{t
+|tllf]c{{||{tt{{zll\[[||{||uu{{b[Usle
+jV[|uztl}¤¦ttsv{}j]\|v
+¤¤
+{tt{tt[TT|u£¥}|ylett{sre||tll
+lddiq]{u{
+|
+||kd\{{ttslf]ctll{u{b[Ulksztl|
+¤uzt{{tmtt{||\[b|
+lks
+UTS{||\[[|
+lkssle\[bllk\[bUMRttsuzt\[b{{lekdc\tt{u\[[{{t|[[T{{t|
+{{tultldd}tll¤lddbVZldd¦§¨\UZJHFlks|
+£¥¤|u}«²«¤¤¤¤¤¦¦§¨¨©´«²«µ¶·¢{{t¨©´¤¦¤¦§¨|z¤¦|uyleult¦§¨]cd{{tlekultedklksu{{|
+dc\lek{||¤¤{{tlri{tt¨©´ultlddUTS¦§¨|||sleddc\[[lri|lek[[T{tttll|u|
+uztJHFlkscbV|zllk|z}}|kd\|ztll}²««¤¤tll}{{||{tt|
+ddculttll[TT{u{}}²²¬|zn{||{{tlddmw}||
+}ylebVZ}|ekd}{ttkd\zll{tt
+{u{ult
+[TT}[TTlri{u{{tt}mtttt{ultllkztlUTS£tll
+{tt{tt[[Tllk\[[ttsLKR[TTtzl\[[SKJmtt|
+mtt¤¦ddcu{{lek¤¦dc\ultlks{u{ult[[T¢tzl{{t}fkkfkk|{||uztuzt{tt{{t}ult£kd\tll£JHF*)(
+|zzl£¢··Ä«²«ª³·¦§¨µ¶·«²«²²¬¤¦£¥¤¦¤¦}|¦§¨¤¦¤¦}lld}ult{u{llk|
+¢
+lri{tt||ut£ddc||{u{f]c[TTlldcbV}UTSn[[Tlrikd\{{lri{{tlri{zm{tt¢|zll{{t}|z||
+¦§¨{{t
+|¤¦}fkkuttslultu{{}}ddctt{||lddldd{{d\\ultv{{ttlriut|z}uztztlzll||tlltts¦§¨uzt|ulddztltts||lek|uttsek]||}}£}lek||ztlslewldc\uztztl{ttuzt|z¤¤llklddu{{|{{t]bZ{u{SKJUMRmttSKJ]cd]bZ|zmttlriMRK}f]clldJHFdc\UTSd\\mtt|
+tlllriekdlri|\[[tlltt{dc\lridc\{u{{{lddlektll}d\\ldd¦§¨JHF
+
+$¢|£¥¤
+¦§¨¦§¨¦§¨¦§¨¤¦ª³·¨©´¦§¨µ¶·£lek¤¦§¨ª³·
+tsl{{t£¥
+\UZUTS|{ttlri|
+lri|
+zltllutv£{||ttssle¦§¨bVUldd|zdc\|j]\dc\redzlluztttsJHFlek{{sretsl{||{zm{||}sleult|uzt}tts||ult¤¤tzl{||tt{|lri
+v{{u{|||zmttult
+ek]{u{ttszllv{lekutslcbV|zuztkd\}zll£¥}tsl|z|uv{
+red{{r]glrilld{u{{u{}|[[Tkd\}|u|zj]\lddf]ckd\{u{}[TTdc\|
+ek][TTlld{{t{||¦§¨{u{ult¦§¨¦§¨{||¢|
+mtt{{tUTSddc|z\[blrimtt¤uztlriu{{leku{{lksmttlri{{{||{{t{{|
+zllddcttsuztllkuzt|zlekdc\ztl{u{ult}}{tt{||ttsult¦§¨VZT*)(|utslwl}¤¤µ¶·££¦§¨£¤¤»ÂÇ¤¤¤¤¤¦|z··Ä¤¦||¤¦
+tzl¤¦|z|
+|z¤[TTVTL[TTlriu{{utv{tll
+||v{}}zll£}lld{{tlldlekyfd~}kd\tsl{tt
+{{t{tt||v|uztllklddcbV{u{SKJlri|ztzldc\
+
+{u{{zm{tt{tt}tsltsl|z|zutsl|utts||}ultult|
+ttsuzt{{t}|utsl{{tlltts{{t¤²««ult|zdc\tslv{||{{t¤¦|u£ut{{tuzttzl{zm}||u|uuzt||}|ztllztfb[Uekdttsj]\u|zllk{u{~{u{{||||[[T|]cdUTS|uf]cbVU
+b[U{{tj]\llk{||}{tt[[T[[Td\\llk|z{tt{{|
+lksª³·¤¦{{MSSlriVTLbVUf]cUMR>B9||ª³·|
+]cdtts]cd|
+ek]¤}
+{{t|z{ttb[U{u{ult{ttr]Z{ttMRK*)(²¬µ£¥ultmwÄÂ¿¤¤¢£²««£¥¦§¨¦§¨££¦§¨²²¬wl¢{||£¥¤¦¦§¨{ttllk¦§¨u|z¤¤
+FD;ultu{{u{{fkkUTS{ttzll
+}d\\{u{lld}|||}uzt{ttkk]UMRrfkutttsSKJztlrfktsl\UZ
+wlllkttsb[Uldd{||{||¦§¨kk]}ek]|
+ultlldllk{tt}slesle{tttsl{u{«²«¤¤}}|ut|uztu{{{{{{t}lri||ttslriult{tt{{tkk]{{tultttsllddc\{{t{zm{{tj]\zllv{{u{tll|tzlb[U{{t}|tll}|¤¦}ult£}lrilriVTL{zm|u|u¢ultlddzll
+ztlf]ctts|z{tt{||uztlldtsl{||fkkek]tts{zmddctllVTLultuztbVUlriuztekd¦§¨f]c
+
+¤¦ttstt{u{{UUYJHF]bZ}{{[[Ttsl{{mttv{{tldduztttslriuztuzt{zmllkf]ctllkd\lddv{rfkztlv{leklek«²«JHF,55llklks}£¤¤|z¤¤~µ¶·²²¬²««¦§¨¤¤v{uzt}¤¤£¦§¨|z¤¦{tt||ztl|v\[[lritlllld{{t{{t~
+tyguzttll|z}{||rg]kk]}|ult|
+tsllek}v{zll[[Tb[Uultrfk||u{u{}£{{}|{u{
+}tt{jcVi\Vu|||¢¦§¨{u{|sreztf{u{|u|z
+{zm|
+tsl|z
+|z|}¤¦|tll{{t}~{u{
+}fkku{{tll
+ult{tt\[b{{t|sle|lektll|zu{u{|u££¥}{||tsltslrg]|sle{{t|tsl
+kk]ult|||lld}ut{||bVUrg]kd\lek£||tsluzttts{u{zlmtt{zmztlj]\tts{{
+zlekdtll|
+yl]bZ|u{||¨©´fkk|
+\[bUTSD;9lksmtt|u{{lksmtt{{}{||ttsuttsltt{|ztlllekredf]cf]c}{tt}tlltll¦§¨MRK*)(||¦§¨¦§¨£²²¬¦§¨v¦§¨µ¶·ÃÄÆ¤¤µ¶·£¥¦§¨µ¶·tts¦§¨¤²²¬¤¤}ttsVTLttsuzt{tttts]bZ|¦§¨uztllk{{tztl|uztd\\ldd|||uztl}utedkttslldldd¤}}}f]c{{tldd¤uttts[TTSKJlriekdu}ttsv|²¬µ¤¤¤¤£}¤ukk]||ztlult|}}{|||{ttlrikk]{u{
+¨©´|tll{||}{||u{{{{tult|u}tsl¤¦v{{{trg]{{t
+||ut{{t
+d\\ttskk]~¦§¨tts|vsre|u{{tdc\kk]|||d\\{u{slered{tt{tttll\[[{u{lld{||VTL{tt|
+ttslldztllks{||lrittsuzt¤lddtll|zllk{||VZT\UZlrislef]cu{{{{
+tlldc\UTSlrilks
+|{|||
+¤¦{|||zddctsl}ekd{tt[TT|{tt{u{}{tt}dc\µ¶·JHF*)(}¤¦}£¥
+£»ÂÇ¦§¨²²¬²««²««¦§¨¦§¨¨©´£|||tzl¤
+}¤¤¦§¨£¥}u¦§¨uztuzt}tsltts}ddc|z}|zlridc\||ttsuzt||ldd{u{d\\zll£¤¦¦§¨¦§¨¦§¨|{{²¬µ£
+tll}tts
+yletll|mttVTLtt{|kd\uVTL|uwltt{|ullkdc\tslult||
+
+jcVmw{zm¦§¨£¥
+¤{u{{||{u{{||{{ttsl|||
+
+{||}tts|z{zm¤¤tll{u{|{{t¢{{t||||{{t|
+|u}yle||red||
+dc\uzt||slekd\mtttzl\[[ult||
+
+sle|||z{{tb[Utlllld
+|||
+ztl
+lddtts}|zmtt¤¢{tt{{mtt|
+tt{}redv{lksekdleklksztllekuztdc\[[Tekdlek}lld{||[TTtlllddlek{ttut}}|]bZ··ÄJHFF=C~²««²««£¥|~¢£|
+
+²««²¬µ··Ä¢llk{tt£}¦§¨}
+lritts
+tsldc\tts|\[[[[Tkd\VTL[[Tr]gek]{ttlldllkut|ttszlldc\{||rfk¤¤tsl|||tllllktzl||wl{||redsleSKJ{{t|zllsletsl{zmlekf]crg]vtts}{||¦§¨sle|z}u{{{tt¤¤ut}tt{}llkllk|lld{tt{ttultf]c¢|u¤¤}sre£¥{|||u{ttllk{ttJHFtts{zmrg]{{t{{t¦§¨£jcVdc\sre]cd{{t¤¤¦§¨utttsut[TTddcsref]clldult¤u{{kk]ª³·ztl}ultu{{|
+lri]bZlldfkkVZT]cdllk{tt|uVZ[mtt}
+llk{ttmtt]bZedkdc\{||fkk{u{lddzll{{tllultyfdredldd|||¤¤JHF*)(tsl²²¬¢~wl¦§¨
+£¤¤²¬µ¨©´²¬µ¤¦¦§¨£¥«²«¤¦§¨
+£¥¦§¨|v¤¤¤u{{}¦§¨{||dc\uzt]bZ{|||tzllri}|u{tt{tt|
+}kd\r]gztl¦§¨tsl{||llkVTLtt{}uzt{||sre{{tsletsl|lddtt{{{kd\sre|ztll||{zm}f]cVTLztl|vsle¤¦u|£}
+mtttslultd\\lksldd|z¤¤tts}tsl[TT|{zmdc\ztl{tt|u¦§¨}{{tult{ttlri}zllulttll|uf]cult}sre«²«
+|lddredSKJtslcbVtll||||sle£¥VTLb[Uddc|
+tll{{tllkuzt|zSKJlri{||£¥¦§¨{tt¢lri{{kd\¨©´¤uzt}JHF|
+lri}f]c\UZ]bZult|
+}}
+lkslrimtt|zttsSKJlriuztedklks|||ttsttsrfkd\\{u{}}{||£:97*)(¤¦}²««²««²««¦§¨}µ¶·²««²««²¬µ²¬µ¦§¨¤¤¤}¦§¨¤¦¦§¨£llk²²¬{{tuzt£¥tll£¥¦§¨|
+|ztzl
+lri{zm{tt{tt|utztltsl}
+{||{zm{||{{{u{|uzt{{tVTLf]c|z{||d\\££{zmdkV[[Tddc}|u[[T{{{ttsle||f]c{u{}{tt
+£¤¤¤¤|tsltt{ult
+zllddc{tt||{{tu{{ut|utll{zm|||wlv{yl
+}{ttsle}{{t{tt{ttlddekdut}{{tµ¶·¦§¨redkd\VTLsleldd{|||u{tt}|z{tt
+lldlriztl{{tVZ[tts]bZ{||}tll}{zm{tt{||ztlfkkrg]¤tt{mtttslddc
+MRKlkslri}tlltts{{{{}|{||ekduztttsedklrilks|lri[TT{{{u{||kd\{tttlltts{{t:97*)(£¦§¨
+£||£}}£²¬µ²¬µ²««£¥²¬µ¤£||µ¶·¦§¨}}}¦§¨}£}|u|z[[Tkk]|z¦§¨|z}¨©´{zm|
+¢£|uztlu|z{||f]cttstll{{tkd\tzlf]c\UZ
+{{tut{tt|zekd}ttszlrg]
+
+u||}{||utf]c{||lddkd\tll¦§¨sle|z||{||{tttts}||£²|{u{|z|z]cdtts{{|||ttsttsult{||ztlwlzll}{{t¤¦£\UZ{{t{{tn{||
+wlldd
+{zm{u{mwzllbVUkd\lddslef]c[[Tredtlluzt{zm\[bj]\VTL|z{{tVTLlri{tt
+\UZek]
+lld{{tt{ddclddUMRlld
+ztltt{ddcleklddf]cv{lksVZTf]ccbV{{lldddc{{ultvlksfkk
+|zuzt¤¦lld\[[mtt{||ldd|ztt{}llklddztftts|lriVTL:97*)(¨©´«²«²««
+}|²²¬²¬µ
+¦§¨£¥²««²««£¥µ¶·¨©´}
+¤}µ¶·~¦§¨¨©´}u||dc\llk||{{tiq]
+|zuzttzl{{t|u}
+
+sle}¤¤²²¬ttstlltsluzttzld\\{ttlddrfkkd\{{tdc\{ttutu{{tllrg]UTStllsleultred|u{{t|
+[[Trg]j]\tllldd{{ttsl{ttzll|u¢ddclld
+¦§¨{{
+{||{||lek{{lldultmtt{ttdc\
+{tt}{ttuzt¤¦£
+
+{u{}ztl£}tslulttts|zultutrg]{{t|uVTLSKJkd\|
+||{{tztlttsd\\ztltllzllkd\f]clld[TT\UZultVTLsrelri]bZ{ttd\\:97{ttekdntt{ztljV[{u{VTL[[Tdc\|lek|
+{ttultldd{||lld}|UMRbVU}mttFD;llkuztf]clri{{ult{tt[[TVZ[nv\[b]cdtsllkstsluztf]clddd\\lkstsllek}bVUzll||tll|ddcb[U
+:97*)(£¦§¨££¥¤¤»ÂÇ¤¦¢¤¤¤¤¤¤²««
+¤¦¦§¨u{zmzll}|{||VZT¢¨©´£|
+sleulttzlut|u{{|
+]bZ[TT{{ukd\sletsl
+{zm}{{ttts}{|||ddc{||SKJzllslesreUUY|u|UTS{ttVTLJHF|{u{{{taWMmtttsl{u{}|
+tzldc\uztut{||}
+{tt¦§¨}ultut}|
+¤|
+lek||{{llk\[[uzttlllldlks|u|z||}}||utll}u||z}VTLvek]tll{zmaWMlldVTLkk]rg]\[[{tttts{u{|u{{tult||[TTultbVUSKJ}dc\dc\{||ldd[TTlrildddc\|u||v{¤tzl{{t{{tutll{{t¦§¨{tt}v{¤~}edkVZ[\UZVZTfkklldUUY{|||z]cdekd|
+|
+mttlekVZTlksuzt|
+u{{lekf]clddultsleult||ztl{ttsreJHF74,}£££££}
+²««||¦§¨µ¶·¦§¨v{¤¦{{¤¨©´{{t¨©´tsl¦§¨||¤|{tttslddcMRKuztsre\UZ|||
+
+}
+ztlulldVTL||{u{}lddf]c{{rfk~rr]}v{||}||£tzl
+
+|z{||lks|{{|u||}z
+|{{t|tt{ut{tt¦§¨{{
+|z
+|z||tt{mtt||u{{tztl||lek}lrirg]|z{ttddcwl|z¤¦{tt}dc\|u}wlcbVkd\ztld\\tzl{{tlldkd\tllllk£¥{ttsred\\llklek}redkd\SKJekd\[[dc\\[[UTSsre\[b{{dc\rfkult¢¢ult}llk}UMR\[[lldddc{||{u{|{{t{ttulttll}|
+£¥|z|
+tt{}¤MRK{{mtt{||tsl{||mtt|
+tts}{{UMRSKJred|lddd\\ttsu>B9:97}|}}}|£¥¤¤|u¢£²²¬£¥££¤¦¦§¨£¥£¥||usre¦§¨|u{||}tlllri
+lritslultmtt|z|utsltslrfk{tt}|}¦§¨kd\[[T|zkk]}redUMRbVUrfk||VTLldd{ttut|uut[[TVTLb[Uztl£f]clksut}|zred|ulritsllekzll||z{tt}
+||¤|
+¢ekd}|tts|
+|
+tsl~¤¦{u{sle{{yleut}|f]cttslri¢¢UTSd\\lldtsltzlllk¢{yfslewltsltll|lek|uuiWUslettsslelek||ult
+ult|
+VTLztlkk]}{||]bZulddtt{tts{zmbVU}f]c|
+ttstsl{u{}lektll|zaWM£lks{{{||
+¦§¨
+}fkk|
+\[[VZ[ult\[bttsekdf]c{{{||srett{j]\|uj]\lddlddddclriJHF-1+sle£
+v|u¢}¤¤¤¤{zm¨©´²¬µ£¥¦§¨|ztf}{tt¢£¨©´[TT~|utll[[Tr]Zrfkult{||¤¦llk¦§¨||UMR}}}tllbVZ{zm}tslkk]uzttslUTSmw¤¤\UZ{{SKJkd\ztfdc\{u{|uut||}lld{tt|z}|zll{{t||
+
+ekd\UZ{{rg]{zmjcVlldult|||lri£¥||{zmu{{tsltt{llkmttUUY
+redu{{llk|z
+uzt{||}|dc\}
+£||lksf]credult{{tsle¦§¨{tt¤¦rr]tt{
+
+||||{zm{{t
+wltllztl|j]\VTL|}vd\\ulttllultf]cuztlri{||[[Tztlf]cutek]ekduzt{{ztltllult¦§¨|lri¢tt{ztllek{{t|z{tt}{{{{\[[|
+|lks
+|
+
+u{{{{VZTllkztlult{{t{{{{tts|tsl}lddbVUbVUtts{{tuzttslvMRK*)(wl
+{tt£¤¤¢}µ¶·¦§¨¦§¨²««²««
+}||||{{¦§¨}£¥|lj¦§¨sleutyfl||
+{{¦§¨
+}}}|
+}²««¤¤ultuztztl\[[v¦§¨lldddc{ttut}ttsb[U£lkstts£bVUUMRj]\zllztfiWU}d\\}|utult|lddtslSKJlddred||i\V}|zv{}¤¦lldedktsl|uzllddclksztl
+¢|}{u{llk¦§¨kd\~llktsltts}d\\{{tlld
+llk||||v{|u¦§¨££{{¤¤|sre¤¦kd\{u{¦§¨lek||uzt{{tddcttsfkkv{}UTS{{t||
+~
+uzt{||}kd\kd\rg]lritzluztzl¢tts{tttll|
+{{||f]cddcut
+|
+lrif]c}ddcuztu{{tts[TTllk{tt{u{bVUlek{ttldd{{t¦§¨JHF*)(zllwlÃ¼¿¤¤ÄÂ¿wl}|
+¦§¨££¦§¨
+}¦§¨¨©´£¥¨©´¦§¨
+}
+i\Vtslzllllk||tllekdlri}u«²«¦§¨{{tslelldlrilldaWM[[Tj]\}|zdc\ultutSKJ\[[VTLtllztlv{lekUMR{||\UZzllusledc\{{{u{ut{tt|ullkd\\|{tt}{tt|||
+ttsfkkv{tllleklks|z|
+||ult{{ult{||{ttlld}lddUTStsl}}{ttztff]cUTSd\\lri|tsllldVTL[[Tsre{u{lldtslddc{tt}slekd\llku}{tt¤¦{{t}tsl}|vkk]llkuztult}ultldd{ttttstts{zmtsl||¤¦|lkstzllkslekdc\utsleVTLlek|{||b[U{u{}|
+sle{||tll{{||vtll{{~tslldd{tt{{\[[mtt|
+lks¤|z{{\[[
+
+slered{u{|£:97*)(£¤¤¼À¯¤¤²²¬£²««£²¬µ¨©´²²¬µ¶·¢}}¦§¨¦§¨}£££¥}£ult{tt}{{tzll}slezllUTSVTLtsltts{||{u{¦§¨
+{tt¦§¨¦§¨}uttsl{|||u|uUTSredrfkuztdc\VTL}{tt£¥VTL}d\\uztyfd|udc\ut||}|f]c{tt|ttsUTSu{||kd\|sle}{tt}||||
+}}lektsldc\{zmtt{{{tt{|{{||¤bVZ{||{ttttsd\\[TT[[Tulttll~tll{u{||}VTL|ztl
+{||aWMbVUVTLSKJcbVlek[[TaWMMRKrg]{||}d\\v{}{tt{{tVTLu¦§¨b[U{tt\UZ{{tUTSkd\{||ult{{ttslb[Uult{{t¤|
+{{tbVU}lek\UZzll¢£¥|tll]bZ{{t¦§¨{u{tts|z}ttsf]c{{\[[\[b]cd]cd\[b
+{u{{{{{uzt|
+tslu{{{{utztlkd\ztllld[[T¦§¨D;9:97£wl
+¦§¨¤¤¦§¨¤¤²««£²««£¦§¨¦§¨|¦§¨£¥²««¨©´£¦§¨£utult{tt£}|ulld|ubVZuzt}{yf}lri£}}ttsu|
+|ztl¦§¨|usrelddkk]kd\[[T[[T{tt|ub[Ured}ultv{|
+}|||f]cr]ZultcbVjcV{||ultred{{tlldrfklrillk|zrfk}}|¦§¨|||}tllu{{edk|zlld|
+utddcmtt
+||~jV[edkzlllri
+u{{tt{sleuzt¤¤|uult{u{rg]¤¤mtt|zu{tt[TTbVUb[U[TT3+*kd\kd\ek]cbVlld}ztl}{tt|uttslVTLtsl|u|z{ttv{\[[dc\b[Uddcb[Ub[Ulld\[[{u{£lldultllddc\tsllekllk~sleuztlritslu{{ultlddv}}|}|£¥{u{f]cllk¢}lddlekmttmttdc\tt{mttedktll|
+}lri\[[{{tuztutslezllkd\red{ttdc\uztlldµ¶·UMR:97}ljlj}}sle}¢
+££²¬µµ¶·¦§¨¦§¨¢d\\|ztsltzl£¥£|uv|¦§¨|
+ztlttsv{{{uzt{{lld{tt²¬µdc\{{t²««|lldrfk{||||}||ulldlldbVU{ttv{yleek]{ttddc||]bZtsl{zmlddutdc\aWMddcttsredtll{{tzll{{tlddut
+£b[U}uzt}{ttsle\[[||llktts{||lri
+fkk|
+rg]ult|ullk{||llk|
+|ztllkd\llk¤¤£¥uzt
+f]c{{ttslsle|ztllultVTLj]\{ttrfk|ub[UvVTL|ulld{{tdc\|uzttslsledkVu|llk{ttv{tslrg]lldVTLlrivtts¦§¨llkb[Ullkttsrfk{u{£llk|z|{{d\\ldd|u
+lriuultf]cldd|
+tt{ddctt{{{edklri\[bu{{ultd\\lksek]lkslri\[[{tt}}|tlllddi\Vlriwlj]\||tzl¤¤VTLJHFwlv~}|
+µ¶·£¥¦§¨²²¬²««£¥Â¾Æ²««²««²¬µ
+tts}¢¢¦§¨¦§¨£¥¦§¨£¤¦¢}¢ttsldd
+tll{{utult
+lrileku£{{t||ttslriulttts}£¥u¢kk]SKJj]\
+ldd[TT}|ztt{||zllbVUVTLbVZ{tt{tt{{t]bZyle||d\\|
+{{t|u
+}sletsltlltll|
+ztllek{u{{tt{{t¤¦ttsttsu{{ultttstllulttt{ddc
+llkulttlltt{|ulttsl[TTtlltsl||ultztlkd\|ullk
+
+kk]
+UMR}srezll|uyle}SKJllk{ttsreVTLuuzt{{t£ztl\[[{tt{tt}|j]\{tt|sletllzll}}LKRuztutljedkv{|uttslridc\|u{tt|utsl¦§¨tsl~lksttsf]cztl]cd[TTtzl{||mtt{{u{{UUY]cdkd\uzt|lriUTS{||d\\{tt{u{yleyleyleJHFkd\red{{t{{t}¤¤JHF*)( £wl¦§¨¢¢²««Ã¼¿²¬µ²««£¥£¥Ã¼¿²¬µ||¦§¨¤¤¢¢|}|¤¤ult|rfk²««jcV{{tldd{|||zultj]\lldldd{{tcbV{ttwl{{tcbVSKJ|ukd\j]\lld{tttll}
+kd\tslut¤¤tyg|zdc\uttll}tll{{t¤¦}f]csleuzt}||rg]b[U{u{{u{lld{tt{tttts{|||}|ldd{u{u{{tlllek{{{tt
+|v{}|||ztl{{tsleVTL[[Tzll}¦§¨£¥}z¢¦§¨|}|redtsldc\]bZldd¤¤{||ek]mtt|
+rfkzllult}kd\tslcbV}edktll{ttuzt{{d\\VTLbVUlrib[Uldddc\dc\}}¨©´¨©´|uztl¤¤{tt{{tf]ctsl{tt|zmttVTLdc\|
+{{{{¤¦tt{ekdddc{{t{|||d\\uztlldtlltll||tllztlllkr]Z}}}kk]{{t²²¬FD;74,¤¤~~}£¦§¨££¤¤£¤¤¦§¨²¬µ¦§¨£¥£¥¤¦µ¶·|||u{{ttsl}sretts}bVUddc¤}lek
+|
+|||u¤{{ttsl£}|z|u
+¢[[Tj]\\[[tts|u|¦§¨mttultbVU}VTLcbV[TT}rfkekd\[[uztj]\MRKultrg]sle{{t{tt{||tll||tts|||zj]\yle|||z¨©´¤|
+llk|z{u{¦§¨d\\|ult{|||z
+}}|[TT||ztl{zmrg]d\\ekdztlwltsl}||}ut}utdc\£kk]¤¤}{{t|||ultlekkk]{ttsle}|yle||[[Tek]tzltllultultutb[Ulri\[[bVZwld\\sleultztl¤{u{}{zmuttll}¦§¨¤|u|tsl{{tMRK{||{||lri{||lddekdd\\f]cddc{tt
+}{ttcbV|u{{t|u|u¦§¨VTL-1+}
+£¥¦§¨¢£}¢££²««£¥²««£¥¦§¨¢uzt{{tµ¶·}¦§¨}
+llkdc\uztfsrerg]lddttsulturfk}{{t{tt
+{||u¨©´{{tzllddultsle}}ttsVTLrfkf]cv{|lri{||{||lld|uztlkd\ztl|u[TTdc\|utsltllbVZ||}|tslsre|z¦§¨|cbVkk]{||{tt¢{||tsl¤¤|utts{||{ttuzt\[[¢|lks¤£¥ztl|uekd{tt||f]c}dc\{||lldmttrfkldd{tt}|zll}|ztltll||{{t{tt{{t||ukd\kk]¤¤tslv|red}|utll¦§¨ztlddclri|z{||uzt}{ttzllztlddcllduzt{{ttll{tt}|zllultldd{u{lldr]g{{sleztl{{uzt£tsl|u¤¦¤{|||v|¨©´²««{u{{u{{u{rfklri|zulttts}VZ[|zlritts{|||z]bZtslsleztl}||vdc\llk}|ut{tt|z¦§¨[[T*)(tllwl
+}¦§¨£££Ã¼¿²««¦§¨£¥££¥£}}}ª³·
+|{tt}ztf¤¤{zmuultb[UlldVTLrg]ultzlltsltllult£slef]c}|zllk
+{{t£¥ztlbVU}tll\UZJHF[TTtllllk[TTldd{u{f]c{tt{||sleulti\VVTLVTLkd\ztlekdcbVcbVttstlllddtllut}ldd}}tts
+ult||{tt|f]c{{t{{}{{|znv{u{
+
+||ult¨©´{u{|}tts|rg]{tt|jcVSKJjcV{{tf]c£{zmtsltzltll\UZzll||
+}ultv{|u}|||}{||zllf]cdc\tsl{{|u|[[T}
+
+{||}|ek]~|
+slef]cmttzlltllbVZSKJ{||||{{{{t{||¢\UZv{{tt¨©´lekutztl{tt}VTL}
+{{tu{{ultult{ttuzt|z}
+{ttb[U|utllyle{ttutv}sre¦§¨D;9*)(}||v¦§¨}²¬µ¤¤²²¬£¤¤¦§¨~£
+sre}
+¦§¨¢}|||}|zltsl}tt{v{}VTLultult
+tt{|¢f]c{||kd\}srebVUbVUult{u{\[[sleultlld||b[UtslbVUSKJFD;]bZSKJsrekd\[[Tlddd\\ztltzlttskk]sleut|u{tt¤
+¦§¨v£ztl¤|||z|zlksf]ctt{fkklksUMR}tsl¤¦£{{lldleku||||lldsletslb[Uztfldd{tt
+{{t{{tlldultcbVut|u|u£ult}j]\{tttts|vrg]tll{ttd\\uzt{{tuztrg]bVZlddlddtts|u
+}MRK|
+tslrfkv{UMRbVZ}}|{{tll{tt}sretts}f]cut}|{{t¤dc\dc\}||||ddcf]cf]c{||
+{{ut}zlltllredj]\|utslj]\red||ztl¢JHF*)(¤~²««ut£²²¬££Ã¼¿Ã¼¿²««¢£¦§¨¤¤tsl||ztl
+uztztlutkd\rfkldd£utJHFuzt{||£{||uzttzl£¥{{t{{lrizllrg]{||lddlrijcVttsv{ultf]cSKJtll{||}|{{t{tt[[TUTSVTLj]\llklddlksttsv}{||r]Zekdddc|||ztl
+{||||}j]\{tt¤llkuzt{{|
+u{{{||{{lksedk{u{tsl|z|ztts¦§¨lks{{tkd\lksttsedk{tt{u{{{tultllddc\redredut{tttts¦§¨||ttstllkd\yfdzll£|uultdc\d\\{tt{u{}ldd{{tttsv|lddllk{tt}|usre{||tsllddlek|uUMRultbVZtts[[T{u{||tsl|tllult||ultbVU¤{{td\\[TT|
+tzlfkk}sre¤{||lri|uldd
+{||{||||}|{u{wl{zmtlld\\utwlv|rg]rg]¤¤FD;74,}z£j]\¤¤Ã¼¿£¥²««²¬µ£¥£|zv}¤¤¦§¨µ¶·||{{tslellk{{t¢||{tttt{{tttts{zmztl||£¥tll||}|||zlddtts[[T{{ttzlkd\{tt{u{[TTd\\[TT}{tt{{tddc¤[TTd\\ekdrg]kk]bVZllkldd[TTtzllritll[[Td\\b[U{{t{tt¢{{ttts}|}}|{u{||u{{{{tllktt{{{
+|
+}tts}|vtt{}|{u{tll{u{{u{}||llkdc\red}zf]c}{||ut{{tUTS|utllsre
+yletts}
+|yfd{{t||sleyfl}{{tut}{{||v{{u{}v{VTLv{{edktllf]c[[Tslelddllk{zmu{{¦§¨ultztlrg]{zm{{t|
+tll{{t|
+²««
+]bZ
+tt{|zlek|
+}ddclekd\\kd\llkddc{tt}|uztldd\UZf]c}|
+v>B93+*||
+££µ¶·Ã¼¿}¤¤¦§¨£²««ª³·}||z¤¤¢£¦§¨¦§¨¦§¨¤¦tt{u~
+
+lld{ttkd\tts
+{ttlldj]\tll£v{f]ctsl{tt{ttrg]ddctll|}|llkiWU]bZtlluzt¤¦tsl{{t{||ultlekdc\}|JHF{|||ttsrfktllJHF{||v{srellkddckd\b[Utslslekk]d\\{|||lekyleztl
+}ddctts}u{{uzt|z¤¦
+
+¤uztddc\[[|z|}\[bf]clksldd||}¤¦}
+¤¦
+}|j]\lldi\V{{tzllkd\ldd}|i\V||llktlllld{||llk}|b[UbVUutbVZ{ttsrettszll}ult||{tt}lek{{t}[[Tddcttstlledktll{{|¦§¨}srecbV{{tsre¤u{{kk]
+££¥tll|vzll|u||||ult{tt|µ¶·{||{||n{u{}ult|tsld\\rfk}|{zmtll{zm}|zllyleztlkd\kd\:97*)(}¦§¨¤¤²¬µ££¥²¬µ ¦§¨¦§¨£¥£
+¢u|£«²«¦§¨£||ztf{u{yfdut£{zmulddtslv{}}
+}llksle{{
+|uldd}tzl|uddclri|FD;d\\u{{]bZllkd\\rfklddlddsrezllSKJ}tsl|zsleVTLtsldc\|lddsleVTLzlllld
+rg]srelddultd\\{u{||{tt|uztl||mttllk|
+{{¤¦|
+
+}||¤¦ddclriuzt{ttlkslekUUY}||kk]ldddc\}
+
+tllsrekd\bVZultlldv{bVZbVZlddlri~kd\v}{{|}|f]clddultldd{||llkd\\kk]{u{v{|||||{||tsl{u{VTL{zmbVUddctts¤lriztltllUTSulttsl
+
+¦§¨|vttsrg]||tslv||¢kd\[[T¦§¨££¤¦{{tll|lek||{tt|vutztfzllsle||kd\wl¤¤:97*)(lddut£}¢}£¤¦§¨£µ¶·£¦§¨{{tu¦§¨
+ut¤¤|u||}¤¤ttswlv{{{t|u¢|u}|sle{||f]crfk{{t||}«²«zll
+{||¦§¨¢d\\rg]redldd
+ztlllkf]c}rfk[[Ttll}tt{j]\VTLkk]lldslettslridc\||tll}dc\tyg|
+ztllddj]\mtt{zmut{{t||f]cv{tlllddd\\}}ekd|
+
+{{tt{|z{u{tlllek{||~{{¤{{tllkleksle¢|zsle|u{ttllklriredkk]VZTzllredbVZ[[T{{t{tt}ultddc{tt|utredrfk
+{u{{{{||}lriztl]bZ\[[ut
+VTL|lldlriddctsl{zm[[Tf]ctsl{tt}v{£
+lek{||bVZ
+¤}{u{ztl{{tkd\uztuzt|z|{{|
+|z
+tt{ut{||{{t{zmlldlldd\\sletll|u
+zllldd
+}|yle|}>B9&&£¥£¥¢¦§¨~{tt¦§¨£¥²««£¢}
+u£¤¦«²«{{t|||¦§¨ut¤¤rr]redtsl{u{tsl£¥}ztl¤¤}|{{t}{{t{||zllsle|tll}}ult{tttllsleultllksrettskd\\[[tllf]csreztld\\ttstll}{{tVTLUTS[[Tlldztlkd\b[U{||}kk]ekduzt||kd\lddlkszll||{ttkd\
+u{{{{ddcek]lks|
+
+mtt|
+edk}|
+|{u{}£¥ddc{||
+||~cbVkk]tllkd\f]clrib[U||j]\ztf{||{u{{zm||ldd{tt|ud\\}||rfk}|utsltts{||tslkk]}ut{ttredsrej]\ttsUTStts{u{{||£¥¤¤{tt~ult}|uzttts¤zll{|||u~{zmztl|£¥zllsrelri}¨©´¦§¨|zekdekdslellkldd|u|u|tzl|u{zm|
+{tt}|vredkk]i\VD;9*)(¤¦{{t¦§¨|v£¥
+££¥£¥£|
+|¦§¨}u|uutztl}}yleb[U[[Tzllf]czll~{ttulttsl{u{kd\{tt|zkd\||£¥zll|ultlldzll|v}|sledkVv{dc\dc\{tt||}lridc\kk]mttSKJ{{trfkFD;sre{{ttll{{t|
+[TTb[Usle}b[U{{tsre||tll{||tll}~v{||tt{lldultuztmtt{{{{{{lrilks|z{u{uztult||}¤¦ttslddlks{u{{{tvu{{{u{|}
+yle{||tsl{{ztlkd\d\\f]cuzt}tzl{||¢¤¦bVUrg]}|v{tttslkd\}|||{u{{ttrg]kd\[[Tlldtsl]bZult{tt{{sleztlztfztlut}
+||²²¬|uztlsle}lek|zwl}tll}ek]{||¤{||tsl
+||{||{tt||JHF}i\Vutztl}|wlred²²¬FD;*)(v££¦§¨££
+²¬µ£¤¤²««²¬µ²¬µ¦§¨|}ut¢~v£ldd£{ttubVU{||tsltll{{t{||ultuztttsu}|{tt{|||u}lri}sleldd}FD;{||ult|z}lri{ttttsllkekdu{{lldb[UlriutUTStygtllsreuzt}ztlsre[TTaWM|zztlrfklld||}tll}£tll|||zlkslrilek]cd|
+|
+
+lkstt{}fkkllk{ttultleksle£{{£¥{{t{{t|z}{u{
+ultrfktsltt{rg]lldutUTSzllyleslekk]{{t{||lddutlekf]c{u{{u{r]g||||{|||}
+tllredtzlsleVTL|z{{ttllttsllk{ttv{||¦§¨££¦§¨]bZ{{v¤¤¤¤£ulttsl||}tsl{{t}}mttmtt£u{{{{tlddlldtzlllk{ttj]\lddsle|||uztlsletslrg]¦§¨JHF*)(~{{t}²¬µ£¥²««¦§¨£££¥¤¤
+²¬µ£}
+|uzll£}
+{{t¤}|v
+|z}{||srelri}}}|u
+|z{{}{{t¤yfl}slellkr]ZbVZllkred{ttddc[[Tlld}lldlld||tzltll[[Tddc{||rg]dc\b[Usresleslensre}{{ttll|lritzl²¬µzlltll}tts{{ult]cd|z{{|
+|
+u{{
+|
+mttlriultuzt{{ultf]clks\[bmttultlddztldc\kk]{ttut}llkddc|sre{ttutzllztl{{{u{kd\d\\¦§¨ut{u{¤¤utred{tt{||ztltllkk]\[[¤¤lri}ult}uztwl|zmtt}tt{
+£¥mtt]bZ}tts}
+
+sre¤µ¶·tts{u{{||¦§¨¤¦v{ztl[[T}zl
+}lldttscbVlldttssrerg]sle{{tutztl|ui\V
+zllutllJHF!²²¬¦§¨²¬µ£
+£
+Â¾Æ£¥£u£¤¦}£¥{{t}{tt{{tttsztl|u{||¤|lld}tsldc\dc\kk]tsl¢|ut£|||}zllllk{u{{ttb[U}{{ttsl{{lribVZlritlllriVZTUTStlluztf]c}mtttslkd\||vuztyle{zm{u{JHF|||
+|{zm¦§¨|
+}{{|
+|
+
+lkslksekd}¤|
+fkkdc\ulttt{|lddd\\tsl{u{¤¦tts|uVTLn}ult£f]cult|z
+lks{{||ztl|u{{tlekttsldd{||
+lddrfkbVZdc\{{tu{{tll{{t{tt|ut}||z}|u{zmkd\u{{ztlrg]||llk¢u}
+}|||}¤¤£{ttlri
+{tt}|²««}{||
+sre{{t|z{{t||sletsl}{{t{{tztl[[Tu[TTsleultb[Uztl}|{tt}v{ult>B9*)(¦§¨||²««²««£¦§¨¦§¨¦§¨¤¤¢¤¤¦§¨¦§¨¤¤¤¤v{v{zlltts
+£~dc\lekylev{{{{{ldd{||{{td\\[[Tuztllkn£
+}uldd¢sle|z£¥ztlu|u||tts|ztts¤¦{tt|u{{t[[T\[[|||ldd}|tts|||}|sleslejcV||kd\tzltts|u£|v
+}{tt{||{{{{
+}{{tslmttmttmttmttuzt\[b\[[{||lddlekultult|
+rfk¤¦{ttldddc\}tsllldttsldddc\[[Tlld
+lld{{t{{[[TbVUkd\ttslddedkzll\UZd\\tll{||uztlriultzll\UZ{{ttyg[TTMRK\[[llk\UZ{ttult¦§¨¦§¨}wlkk]
+µ¶·
+¤
+||££¤ttsztl
+dc\{{tulld||tzl|z{zmkd\|lriiq]lldtllsrebVU{zmztlztl}|utllyle}D;9*)(
+£²««££
+}wl¦§¨µ¶·££|«²«wl||kd\{{t{||{tt{{t£¤¤u{||{{trfkrg]}}{{t{u{wl|{tt{u{d\\|¤¤£µ¶·uztlu|ztl|SKJttssle}bVU[[Tultllkultlks|llk|u[[Td\\tts|
+u{{t|u|u|u{{tf]c
+sle||{{tsleztllldv{ztltsltll¤edklld{{{{|z
+¢tt{
+|
+mtt{{mttu{{{||{{llduztd\\\UZlks[[Tf]clld{u{llk{{tlddcbVultlddult||}dc\{{t{tt[TTUMR{ttb[UmwVTLrfk{u{VTLSKJ{tt{{tv{vredldd[TTtsldc\|
+utsle}z}ekdllkllkldd{||£{{uzt}sre}²««²²¬££|vlekllk}|zll}||tts|£¢{{t}|
+ztlb[U|{tt
+{||{{tlddtts|uutztl||ut||wl}:97*)(¤¤²««£¥µ¶·
+µ¶·µ¶·«²«²²¬£¦§¨¢||zu¦§¨£tll¤¦{||¢¤¤tts||
+f]cultttssleb[Uvu]bZ[TT|zddcb[U|z|u|tsl}kd\{zmv{ª³·||llklddsle}¢ultttsb[U}cbV}
+||tlli\VVTLSKJkd\tll{{t|uyletll|u}|utslsle{||b[U
+{tt
+tsltsldc\{u{{ttlks{{{||uzt{{¢mtt|
+£mtt|z|
+|z|
+{||llk{ttlek{||{{d\\bVZbVZ{u{£|z}|uzlulttlluztdc\redUTSztfkk]SKJ|lekkd\f]ctllVTLmttd\\tsl|||u\[[£kd\{||{ttsle}ldd{{v{}lksmtttllsleultztlultUMRldd
+utllkuzt¤tts£¥¤¤£¥zllsre|}|u}}lddztfsre
+||]bZred||u{{twlztlztl||tslwlJHF*)(£¦§¨ÃÄÆµ¶·¦§¨£
+£²²¬¸Á¹µ¶·£¥}¦§¨u|v£|u}yle}
+£||uuztmtt{{td\\||u£}{zm|u||u}|{||f]csresre
+}ultllksle{||ultultuztlldd\\{u{VTL]bZ{{tsre
+{zm}JHFSKJdc\dc\|uztf[[Ttllkd\|u||}}lldkd\ztlj]\
+{tt
+tsl{{t{ttttstllddclddlekmttu{{mtt¤¦|
+tt{{{{{ttslks²¬µtt{|
+}
+||ttsf]c}bVZylelri¤¤|zsre{||kk]{|||uldd|zkd\rg]
+¤¦|vsreztlrfk|}rfkztlkk]b[U|u}zlltlltllf]c{{trfkrg]rfkuzt|z}{u{leklektlllek||ttsmtt£ut}|vzllnllk}|ult¤f]c}|
+ldd£tsl{u{}}tll{||}¤¤wl}{{t[[Tdc\tlltsl}|u|||u}{tt~ztlD;9*)(£¢²¬µ¦§¨²««¦§¨²««²««£
+µ¶·²²¬£¥¤¤«²«u£ut}lld¦§¨wl{tt{u{zll{{ttts}MRKsre|z}|udc\¦§¨||{{tlriuut}|utsl}|||zll||||ztld\\ddcsre\UZ{{t|}|u{{t
+dc\j]\f]cVTLslelddttsuzt}}b[Utll|vyleztlkd\kd\wlf]ctsl
+}}d\\||}{ttllktts{{n
+{{mttlkslksultlek¤|
+mtttt{ult]cdv{bVZ{tttt{tsllld{{tzl{{tutsl
+f]cj]\llk{{t{{tut{{t
+u{{tlek{zm|urfklks
+||kd\}|SKJf]ccbV||sre¢ldd}slesletsl
+|uzllttsult
+lriekd|
+{tt||£¤¤{tt{||{ttrfk||}{u{}tll|ud\\|u[[Ttsl|usrekd\lld}lldrg]u|v{kd\||r]Zsle|uredredVTLcbV£FD;*)(¢¦§¨£¥£¥¼À¯µ¶·¦§¨¦§¨¦§¨¤¤²²¬|v£¦§¨¢{zm{{t}}{{tu|u{u{¦§¨£¥||{{taWMllk|{{tredllk{||ut¦§¨¢{tt}tzlSKJJHFVTL{tt{zmb[U|
+£ult{ttutldd[TTult{ttd\\slej]\kd\|zudc\slelddkd\f]ctslb[UJHF|tts{u{dc\{tt|u}llkvtts|lddtts{{ttslcbV||{{t}tts
+
+lks|
+|
+{{{{VZ[]bZfkklksleklkslrimtt|\[[\UZUUY{ttldd{u{{{tcbV
+[[Ttllultldd{||sretsltts{zmkk]lld}||{||ud\\tll|zv{kd\b[Utzlu{{tsl|ztsl||tll}{{tkd\|vVTLlldslelri{tt{u{lksmtttt{|z¨©´¤¦|¢}||{||tsl{tt
+ult}{||uztkd\||}|}bVU{ttd\\ttstsluuzttsl|{||{{tuztf]cult{zmzll
+uzt}ztlrg]d\\j]\tllrg]rg]}|||{{tztl¦§¨UTS*)(¤¤¤¤£¦§¨²««¤¤¦§¨¤¤¤¤¸Á¹¢²¬µ¤¢}|u{ttrfk{{t£ztl
+tll{{t{||rg]{{t{||zll|z||tts{||{{t\[[llk|u}||ztygv{ttsj]\¦§¨
+}||u{u{bVUztl}VTL]bZlddllk\[[UMRtll[[Ttsl{||dc\{zmlrij]\tll{zmtsltlldc\{{tztl}{ttkd\VTLlldbVUb[U{{t}|}rfk}|VTLsre{{|
+tt{|
+{{llk
+nv{||mttd\\{{fkk|
+ttsf]cUTSlks\[[bVZ}v|u
+}~sre|llk{{tttsllkd\\ztllri[[T||z}sre}}dc\tllf]c{tt}|tts{{{u{sle{{t|z}{{t{{{{t[TTtllVZT[[T||{|||bVU{u{llk
+¦§¨|zu{{||£¦§¨{||\UZ{{lrizllzll¦§¨sletts{ttv|z{{tlddj]\ztl{zmslesle|}ztltsl{ttSKJlldek]v||sleutsle²««SKJ*)(}²««ÃÄÆ¨©´£¢¤¤£¥¦§¨}{zm{zmtll}|||tll{u{lld[TTlrisle}|{{t¤¤¦§¨|z
+ek]{tt}|usle{{tldd
+¦§¨¦§¨£zll{tt||{ttkd\{u{{{tttstts}lldSKJ]bZuztkd\tsl}{{ttllVTLd\\[TTD;9{{tlldv{sre{||kd\ztldkVkd\|b[U{{t}¦§¨ztl|{{tlrisle¤¦lksmttmtt{{VZ[{{
+fkkmtt
+{u{ulttsllksd\\d\\£llk¤¤|ukk]sreuztttskd\tt{\[[lldredztl{{t}llksle|utll\UZ||
+ult{u{{tt{||dc\jcVtslult{{t|u{zm{{ttts{tt{u{j]\d\\edkekd|{{{||tts{{£}u{{
+{{ttts}uzt|{tt¦§¨£v{|{||{{t}ttslldttsult{{t
+¢}lridc\b[UcbV|
+llkkk]|utsl{ttutztlrg]ddc||red¤¤D;9:97££¦§¨²¬µ¤¤¦§¨£¥¤¤µ¶·¤¤¦§¨«²«¦§¨£wl}||}¦§¨}{tt¤¤||²««||{tt|uuztrg]llktts{zmultb[U\[[[TT{||kd\{||{ttsled\\|£|u
+v{tslj]\dc\sled\\||kd\lek{{ddcldd\[[dc\[[Td\\f]cslesle{ttb[U[TT]bZrfklddut|bVZj]\ztlztl}|kd\|z{zmztf|z}}rfktsl{|||zkd\tt{{{lri{ttlri\[[|
+
+mtt
+{{
+]cd\[bttsf]c{u{lks{{f]cddc\UZ{|||lld{{t|kk]kk]{{tlrildd{{ttllddcult]bZ~uzt{{tb[U}f]cf]c{ttj]\{ttsresle|ulddult{{ttts||u{|||u|zultUTS{ttttsttsf]c{{{u{ztl}ut{{{||}{||
+lrizll}
+uu{|||uuzttts||{{ttsluzt|||sre{{twl{{ttslztfkd\ztl}|sre||{{ttsl{||¦§¨FD;*)(v£¥¦§¨£¥²¬µ¦§¨¤¤¤¤µ¶·£¥vu||redredu{u{||}{ttztl}{||}¤¦lld{{tred[TTldd{ttslelekrg]sledc\tsl|||
+}
+tllv{[[Td\\|uztltll{||}uztf]c]bZlddb[Ulddd\\{u{{{tutulddvredVTLkk]lddbVZ|usleldd}|ldd{ttllk||u|u{{t}{||sleutztl||lri|
+{{{{tt{]cdult{{mtt{{|
+tt{edkf]clksllkekdmtt{{tlks{u{lek\[[d\\ek]lldllkkd\|tslsreldd\[[d\\sle}llktslsleddclddtt{utv{{ttultldd|u
+VTLkd\UTSu¤¦|}{tt{||uzt
+ldd
+]bZtsllks{{{u{lksult[[Tlektsl¤¦llkuzt|ztzl}¦§¨lek}|zlld{u{||b[USKJd\\mwFD;[TTllk|ttsudc\{tt{zmek]llkcbV[[T}{{t]bZtllsre{ttjcVyle
+}sle£SKJ*)(}¤¦£¥£¤¤£¥µ¶·|}«²«{ttlld{ttlld||}|z{||{{t
+|z{{ttts{||ult|u}|v{zmtyg
+rfk
+{{t}|{tttsl||zll||ztl}{ttldd[TT}{{tddc{||tsltlltsl{u{ek]lektllrfkztl{ttlddkk]kd\ddcf]ckd\b[Uekdd\\zllaWMMRK||{||lri{ttj]\{zm}{yf|zkk]}{tt¦§¨}
+uztddc|
+|zlksmtt
+uztllkmttf]c\[bultekdlksult||iq]b[U{u{}{u{\[[ldd{{t{{t[TT{{tlldtsl{zmlld}dc\sleddcd\\aWMlri|{{tVTLlldtllr]gtt{}
+lddd\\tslutddcztlddcb[U{||[[Tlld{{t]bZ|||u{{{||¤\UZ\UZSKJkd\ekdtll{tt|zf]c{||lksfkktslttsb[Uf]c{||v{{u{{ttllktsltllaWM|z{tt{||ztl{ttj]\tsl||dc\dc\lri{zm{{[[Tred|u||lldtslsre{zmtsltllcbV{ttkd\ztl{{t{ttmttldd
+D;9:97|¨©´
+²««£¥¦§¨µ¶·|¤¤¦§¨uzt¢¢
+
+
+{ttv{|{u{¤¤|u{zm|z||{ttultlri|z|¦§¨|z}
+||{zmtsldc\red{{t||{|||
+slered{u{{ttredlldslelddlekj]\dc\SKJslelritslb[U{||ddcuzt{{t{{tldd{{t[TT{tt{zmSKJ|
+utsle{{ttll{ttztlv[TTslelrilld{ttj]\}|kd\tslllkztlbVZtts}{{tdc\lkslksddc{{{{llkmttu{{ddc\[[UUYUMR{{{{uztmttlddlekdc\ddclekllkult}lrilddlriu{ttd\\lek{{t{||ztlldd|zkk]VTL{u{j]\b[U\[bd\\[TT|ub[Ured{||[TTllkVTLb[Uredb[Uj]\]cd{||j]\tllttsekd{u{{||{ttVTLlri{u{||
+tll{||tllkd\{||]cd|zdc\lks||ddcbVUSKJztlVTL[TTlrittscbV{||sletygtts|zrg]||||{u{lddztllri}|z}dc\ldd[[T|zttskd\[[Td\\tslb[Utzl[[T[TTkd\{||}red|||tslj]\£SKJ*)(£¥££¥¤¤¢ult}{tt|uztl||{zm|wl}{{tlks}{{t{|||zztlsredc\sre{tt}|ut}{{tzllekdttslddllktll{||kk]{{t|uultulttll\[b]bZbVU[TTtslf]c{||tsltlltll}lldkk]tlld\\kd\j]\|uFD;tll{ttsleVTLb[UlddVTLztl||ttsultkd\cbVdc\{zmusletts}tll
+[[T]cdslelks{{{{edkddc{||u{{mtt\UZ\[bJHFVZ[lkstt{ddclks}lks[[Td\\lekllkf]ctts}VTLtslttsbVZ[[T[TTzllkk]||mttzldc\lks||VTL\UZSKJd\\lekkd\zlllddlldddcSKJVTL[TTtsl}\[[dc\tslVTLVTLlrildd\UZlldd\\{u{llkllk{ttttstllbVZlkslridc\uztmtt}lektlluztlekj]\b[Uu{{d\\{tttts[TTVTLtslVTLkk]ddc|uddc}{{t}tll||ekd|[TTdc\lld|uultttsf]c{||kk]sredc\kd\lddztlddcb[Uutlld{tt||sle£JHF*)(}|u¨©´¦§¨£²««¢u|
+{tttsl{{tt{{ttsletsl{{tzllztlllk
+||UTSkk]dc\ekd{ttlddtslulttsltslkd\|z|zkk]{||d\\{||lddlri|utts}ttsSKJddctllult[[TVTLSKJllkJHFSKJ\UZdc\ldd|
+tsllldtslb[UUTS[TT]bZVTLj]\b[UVTL{tttslVTLzllztlztfldd{u{lrilddJHFb[UVTLkd\redtsltts||{ttllk{{tsllldUTSttsekd{{]cdf]cllktts{{
+\[bfkkVZ[}u{{lksddc|
+{u{{tttlledkuztlekutuzttsltslVTLtt{\[[d\\[TTekdj]\{{tlddkk]tzl[TT\[[d\\b[Umttllkllkldddc\\UZlekbVZlldtllzll}tslj]\[[Tdc\lldttslldllkuztkd\edk\UZVTLb[UJHFf]cUTS
+u{{ddcb[Ukd\
+UTSlriuzt]bZttslddMRK{ttUMR[TT{ttllk[[TlddcbV\[[{ttlldj]\[[Ttslsre||kd\ddcb[Uddctll]bZkd\|lldtlltsl||{||ult}d\\dc\ztldc\kd\tsl{u{sle|vsleddc{{tlld²««[TTD;9ztl
+¤¤
+
+||{||
+
+|{{t|zllk|z|tts{||llkd\\kd\{u{}lrilldlldztlkk]lldtsltslu{{sleedk[[TVTLrfkf]credkd\kd\]cd|zsle}lldtts{||ekdf]ctlllld|zslelldtts{tt{||tllcbVzll[TTdc\d\\{u{]bZbVU{tt\[[VTL[[Tkd\\[bb[U[TTtllslekd\|z[TTutztl\[[b[Usletsl{||tts[TT[TTlld|z
+d\\tsl{{t{{t{||lldtllttsd\\[[Td\\{{lrif]cfkklkslks|z{||mtttt{VZ[LKRVZ[mttmtt]cd\[[\[bd\\d\\lddlekmttedk\[[r]guztekdekdd\\lridc\{{t[TTlldd\\FD;[TTd\\kd\tslUTSlld\[[[TTkk]f]cj]\f]cf]c[TTtllf]cbVZUTSllkkd\ttslksllkd\\SKJmttUTSUMRd\\tllSKJ[TT\[br]gf]cUMRUTSztlddcslelkszlltll\UZtllVTL{||llddc\lldtt{VZTtt{}ultd\\d\\tt{mttekdlkssleVTLkd\{{tdc\dc\{{tldd[TTztl\[[dc\d\\b[Uddcd\\f]cb[UcbVlldlld{{ttslcbV[TTztlVTLkd\dc\lldtllb[Urg][TTUTSredkd\[TT:97{||²²¬}|ttsllk|tt{mtt|
+}{{{u{ztltts{u{{u{llk{{}{tt{ttkd\kd\dc\{u{tsldc\slelld|{{{||{|||tllttstlldc\{ttkd\{||
+{u{|zlld|zVZTSKJkd\lek|ztts\[[JHFf]clrildd{||sledc\ttsttsllddc\\[[JHFd\\UTSdc\ztfkd\\UZsleVTLd\\tslaWM[[Tllk{ttkd\lldlritsl||uzttts{||{{tlld{u{kk]ztf}{{tlridc\lddultekd]bZdc\llkSKJtlllksmttlksVZ[f]cllkUTSlks\[b\[btt{\[bult\[bVTL\[bJHFUUY[TTdc\UMR\[bd\\UTS[[T[[TVTLMRK\[[|ztllttsekdd\\b[USKJUTSSKJ\[[dc\lldttsllkj]\d\\leklddUMR[TT{tt\UZleklldtsld\\VTLkd\[TTuzt[[Tddcu{{{ttd\\JHFmtt[TTldddc\\UZtts{u{u{{SKJ\UZ[TTVTLUTSekdlldedkddc[TTllkddcddclridc\JHFedkttsult\[[[[Tllktslf]ccbV[TTkk][[TlldSKJSKJtlltlld\\fkkd\\sretslllkVTL{||{{t[[TVTLUTSd\\ldd[[Tdc\tllrg]]bZttskd\ldddc\d\\[TTztl²««JHF*)(||{{ttzl{||tll|
+llk|zttstll|tt{ldd}b[U{||ddcllk[[Tultlksultu{{{ttd\\JHFdc\VTLek]lld{{t{{tlddldd
+||sre|
+||lri||ddc{||{{t|
+u{{ddcddcedk{u{{u{tsl[[TJHF[[T\[[ddc{u{lddultkd\f]c[TTddcd\\dc\cbVlddultuztkk]b[U[TT[[TVTL\UZtllVTLb[Udc\kd\redlldVTLb[Ulldtzl{||tllekddc\lldtll{{tlddztltsl]bZlrilldlddttslld{||\[[UUY]cdedktt{mtt\[b]cd\[bUUY\[bmttlkslksUUYfkkUTS]bZUMRJHFUMR:97JHF:97UTSUTSJHFllkllkVTLSKJllk]cdcbVLKRb[Ub[U[[T\[[SKJVTL\[[dc\lriddcVTLdc\llkf]cllklddlldlddUMRUTStts\[bkd\VTLllkJHFtllbVZuztttslddddcbVU[TT[TTUTSJHFJHFddcUUYUMR\[bJHFJHF[TTdc\d\\ekd[TTUTSJHFVTL\[[]cdD;9f]clld]bZd\\VTLSKJVTLJHFllktt{|uekdUTS]bZdc\JHFkd\[TT[TTtll[[TVTL]cdb[U[[TSKJVTLdc\lldFD;[TTUTSSKJJHF[TT[TTdc\dc\b[Ulddd\\VTL\[[bVUd\\jcVkd\}JHF-1+{tt|u}{tttts{||{ttttsdc\uztllkttsu{{tts|zJHFedkleksle\[[sleek]llk\UZf]c{{tf]cedkSKJtts{ttlddlrillddc\\[[]bZ{{ttslUTSldd{u{llklksfkkllkultkd\[[TUTS]bZ[[Td\\tllUTSddctts\[[\[[dc\VZTJHFJHFJHFFD;UTSVZTVZTtllredd\\VTLVTLdc\kd\UTSd\\kk]dc\ddcUTS[TTdc\bVUcbVJHF[[T]bZtllb[UJHFd\\tllb[Umtt[TTUTS\[[VTLb[U[TTdc\VTLb[U[[Tddc[TTUTS\[[cbVVTLddcf]cf]cUTSlksllkVZ[]cdultmtt\[[edk\UZJHFLKRUMRJHFLKRUTSJHFJHF)+2:97F=CF=CJHF:97D;9d\\d\\VTLdc\VZTLKRJHFUTSJHFFD;JHFFD;UTSMSStllMRKUTS\[[UTS\[[\[[[TTf]cSKJSKJD;9JHFUTSUMRlddVZTUTSlekdc\lks\[[[TTddcF=CSKJFD;UMR:97JHF:97:97MSS:97\[[UUY\[bllkult{||JHFJHFFD;>B9>ECJHF:97JHFLKRUTS\UZ[TTUMRMRKd\\VTLJHFekdlldlddJHFF=CFD;MRKSKJSKJlldlddSKJllkUTS[[TJHFJHFD;9D;9:97:97>B9:97>EC:97D;9:97JHF[[TSKJSKJlddJHFFD;\UZJHFJHFSKJSKJ¦§¨SKJ*)(ztl{{t||{{t{tt{ttllkdc\lldldddc\[[TJHFedkdc\ddcmttlkstts]bZllklddtllultVTLMRKJHFUTS]bZ[[TUTSJHF\[[UTS\[[tslbVZllktsl[TT]bZ]bZFD;JHF>ECJHFJHFJHFVZ[UTSddc[[Td\\UTSVTLd\\SKJ\[[\[[UTSVZ[JHFJHFD;9dc\JHFJHFUTSSKJUTSJHFJHFd\\JHFJHFJHF:97UTSJHF:97FD;JHFVTLJHFJHFJHFdc\[[Tkd\JHFD;9JHFJHFJHFFD;FD;SKJ[TT[[Tldd\[[JHFddc\[[lldd\\[[Tddcllddc\VTLFD;JHF]cdllkddcldd\[[[TTd\\]cd\[[]cdJHFLKRJHF]cd*)(
+
+$:97*)(*)(?;C:97:97*)()+2:97:97:97:97UUY3+**)(74,!*)(*)(*)(*)(*)(74,*)(*)(*)(JHF*)(:97*)(:97*)(74,3+**)(*)(3+**)(*)(7-2*)(:97*)(*)(*)(:97*)(,55*)(*)(*)(*)(*)(*)(*)(:97&&
+%&*)(>EC-1+
+%&FD;)+2LKRLKRUTS?;CJHF*)(
+
+$*)(*)(,55*)(*)(F=C*)(*)(*)(*)(*)(74,:97-1+*)(*)(*)(:97:97JHF*)(74,-1+*)(*)(*)(74,3+**)(*)(&&*)(*)(*)(!*)(*)(*)(*)(*)(*)(*)(*)(:97*)(*)(:97*)(*)(D;9:97*)(-1+VTLSKJFD;\UZ[[TJHFSKJJHFLKRJHFSKJSKJ3+*:97:97JHFJHF74,:97LKRUTSMRKMRKJHF:97*)(:97*)(:973+*:97*)(:97:97JHFLKR>ECJHF,55:977-2*)(-1+74,:9774,-1+3+**)(*)()+2*)(*)(*)()+2:97JHF:97,55*)(*)(*)()+2*)(*)(?;C*)(74,:97*)(:977-2*)(JHF*)(&&*)(*)(3+*
+:97*)(3+**)(*)(*)(*)(74,3+*&&&&3+**)(
+*)(&&-1+*)(*)(*)(SKJ*)(*)(:97*)(D;9:97:9774,74,*)(*)(>EC*)(:97*)(*)(*)(*)(*)(*)(74,*)(-1+,55,55:97)+2*)(,55:97:97:97LKRJHF?;CUUYf]c\[b\[b\[[[TTSKJUMRJHFllkUTSllkJHFMRKVTLUTSJHFF=CVTLJHFFD;JHFJHFUTSJHFJHF>ECJHF>ECJHFJHFJHF:97LKR:97F=CJHF:97D;9:97:97:97:97FD;:97:97:97JHFF=CLKRJHF\[b\[[MRKMRKdc\]cdLKRek]UTS\[bMSSMRKJHF\UZJHFJHFVZTMRKJHFMRKJHFJHFJHF:97:97:97:97JHF>B9JHFMRKJHF:97D;9UMRVTLJHFFD;VTL[[TD;9JHFFD;>B9:97:97>B9D;9FD;JHFJHF>B9D;9:97JHFD;9FD;UTSSKJD;9FD;SKJD;9SKJJHF[TT[TTJHFJHFVTLVTL:97[[Tdc\VTLllkbVZf]cek]>B9VZ[\UZ>EC\[[VZ[UUY\[[\[bLKRVZTfkk]cd\[[[TTUTS>B9MRKMSSJHFSKJddc[TTVTLVZ[UUY\UZUMR\[[MRKllkVTLJHF:97SKJ[[TVZTJHFJHFVTL\[bJHFMSS[TTLKRJHF:97JHFD;9:97JHF:97JHF\[bf]cJHF:97VTLJHFJHF>EC:97>B9JHFSKJ:97:97SKJJHFJHFJHFJHFFD;SKJD;9MRKJHF74,JHF:97:97JHFFD;UMRD;9SKJbVUFD;MRKb[UJHF:97UMRMRKMSSLKRFD;:97FD;JHFekd:97JHFUMR]bZJHFUTS:97JHF\[[LKR\[bLKRMSSJHFLKRMSSOS`OS`JHF¦§¨¦§¨¦§¨¦§¨¤¦§¨¨©´
+¦§¨¦§¨¢¦§¨«²«²««¦§¨¢µ¶·µ¶·²««²««¤¤¤¤£¥¦§¨²««¤¦|ztl¢v{¦§¨²²¬²««²««££¦§¨¦§¨tsl
+¤¤£¥}¤¤²««¤¤¦§¨¤¤¦§¨²¬µ¦§¨¦§¨¨©´¦§¨¦§¨¦§¨£¦§¨£¦§¨¦§¨«²«¦§¨µ¶···Ä¤¤£
+v¦§¨£¦§¨µ¶·¤¤¤¤²²¬¦§¨¦§¨¦§¨¢¤¤¤¤}²²¬¦§¨ult}wlztl£¦§¨²««¤¤¦§¨£
+££²««²««}²²¬[[T\UZ²²¬²²¬¦§¨¢£¤¤¦§¨ª³·²²¬¦§¨µ¶·ÄÂ¿Â¾Æµ¶·µ¶·µ¶·¦§¨¦§¨µ¶·¦§¨¦§¨£}µ¶·µ¶·ÃÄÆ¦§¨µ¶·²««¤¤µ¶·¤¤µ¶·²««²««²²¬µ¶·¦§¨Ã¼¿¦§¨¦§¨«²«¦§¨¦§¨¦§¨²¬µ¤¤£¥£¥£¦§¨²²¬µ¶·¤¤¦§¨¢¤¤£²««££¢||¤¤²««££²²¬¦§¨²««¦§¨¦§¨¦§¨£}¦§¨²««¤¤£||µ¶·¦§¨²²¬¦§¨²²¬¦§¨¤¤¦§¨¦§¨¦§¨¤¦¦§¨¦§¨¦§¨¦§¨µ¶·¤¦¨©´lks)+2?;CLKRdc\ultd\\7-2>/Att{\[[f]c]bZ!:97%lrilridc\ddc:97SKJlddlldSKJ|:97*)(JHF[[TLKRJHF\[[JHFSKJVTLldd{u{f]ckd\]cdddcred{zmSKJVTL3+*:97%JHF\UZlld7-274,
+%&
+
+$VZTuzttll[[TUTSMSSVZTVTLVTLtlldc\tll[[Tddc[[TJHFJHFUMRekdddcUTS74,@/7	74,73FD;VTLRP:tslredbVUVTLD;9MRKFD;FD;D;9C8.]bZ&&&&3+*FD;D;93+*3)
+D;9dc\VTL3)
+FD;%&&0FD;SKJD;9D;9VTL²²¬dc\[[TVTLjcV||SKJ>R.
+VTLJHFGSu]cd|z|zlrityglldsreD;9SKJsre{{t|u{ttlddf]cMRK}{tttllek]f]c[[T]cdUMRD;9UUY"%VTLFD;JHF\[bf]cMRKfkktsllri[[T ,55-1+>B9VTLUMRD;9VTLVTLlldSKJ\[[sre{||VTLd\\{ttSKJfkkJHFD;9SKJsleVTLcbV>B9VTLVTLyledc\3+*"FD;FD;d\\D;9Q?@SKJ	>B9*)(:97*)(]bZ7-2SKJ3+*dc\zllUTScbVJHFlldtslJHFlldf]cJHF\[[LKR
+%&-1+,55{{VZ[llkUMRlks]bZJHFF=CLKRf]clddlek\UZf]cMSSSKJf]c>ECf]c74,[[T]bZVTLttstll|]bZedk{u{[TT{ttUTSLKR\[bUMRJHFVZTUTSJHFJHFVTLdc\lldultVTLtlldc\uzt{ttSKJSKJSKJ74,UTSf]cf]cJHFkk]JHFD;974,*)(>B9*)(JHF3+*fkkultUTSJHF\UZUMRVZ[[TTd\\lriowd\\uzt]bZtsl\UZLKRultuzttts\[[lddFD;-1+FD;>B9%)*)("*)(FD;SKJFD;j]\UMR[[TFD;SKJ:97C8.D;9D;9SKJFD;JHFFD;JHFtllUMR:97SKJb[UVTLFD;JHFVTLD;9F=CPF=JHFD;9D;9SKJJHF¦§¨VTLJHFvu|u|vlricbVJHFtsl\[bSKJ7-2[TTuzt|
+lldllk
+lrib[UJHFb[Uultult[[Tlek{{tlldSKJ\[b{{{{tj]\tllultekdSKJSKJ\UZD;9ldd\[[[[TekdF=CVZ[JHFdc\uztultlri:97]cdfkkMRKJHFttsddc\[bJHF[[Tdc\]bZlriUTSddcVTLSKJUTSf]clri[TTztlb[UVTLVTLlldVTLVTLlddd\\cbVSKJMRKVTLkd\{ttb[UUMR\UZFD;*)(:97[[TFD;[TT:97>EC:97[[TJHFFD;sle[[TMRKVZTSKJVZT\[[>EC\[[UUYUUY>EC>ECJHFJHFUUY]cdJHF\UZ]cdlksddc>ECedkJHFddcj]\UTS\UZ\[[edkbVZf]c\[b[TT:97D;9[[TMRKb[Uek]VZTUUYJHFUUYVTL]cdd\\f]c\[b\[bD;9lriMSSSKJd\\[[T[TTsle\UZ\[[UTSb[Ullk\[bSKJtll\[[SKJSKJ*)(UMRUMRSKJJHF&&3+*:97JHF74,:97JHFLKRSKJf]c]cdf]c]cdedkVTLb[UVZTmtt[[T[[T]bZ[[TUTSu{{ddc{{t{u{lksf]c]bZ]bZVTLlri&&&&
+SKJaWM[TT[[TVTL[TTb[UFD;3+*FD;FD;VTL74,D;9VTLSKJ[TTd\\[TTD;9SKJJHFdc\JHFJHF[[T[TTJHFbVUUTSaWM[TTVTLtll¢llkSKJtsl{{t{zm
+{u{kk]]bZ|zMRKdc\VTLJHF%UMR{||ttstts\[[|
+tzlrfklddult{||ekdlddldddc\
+ddcb[Umtttt{ldddc\{ttultlriUMRUUY|
+dc\lekmttVTL\[[F=CMRKVTLfkk{u{{ttMSSMRK\[b:97ekdb[Udc\ult\[[:97dc\JHF[TTMRKddcu{{dc\j]\d\\[TTllkSKJkd\j]\d\\tll[[TlddmttVTLlldVTLJHFFD;D;9SKJJHF[TTddcD;9D;9*)(FD;b[U:97SKJsle:97SKJVTLddcVTLlld{||VZTddc{||llkF=CultlrimttJHF]cd>ECLKR:97MSS\[bMSS]cdVTL\[bddc>ECSKJ\[b\[[{||}JHFddcbVUulttts\[[FD;:97VTL3+*JHFVTL:97d\\:97]bZdc\ekdddcUMRLKRD;9[[T[[TJHFf]cbVZkk]tlldc\zllSKJb[Ukk]edkf]c{u{lek]bZUTStt{f]clddUMRUTSSKJJHFVZTFD;VTL:97FD;FD;lddJHFv{fkkVZ[VZ[\[[slelldlkslriJHF[[Tkk]\UZdc\VZT{ttVTLlks]bZ[[TJHFJHF&&
+&&3)
+[TTSKJbVUkd\f]csleSKJ:97FD;&&FD;PF=FD;VTL[[T[TT[TTb[Ured:97[TT[[TVTLFD;VTLJHF[TTVTLf]cVTLSKJVTLD;9lldbVZJHF{zm}{ttlddMRKmttiq]zl|zUMRVZTJHFSKJ|tt{d\\lkstts[TTJHF
+{{tlrid\\[TT[TT]bZ[TTddclldlddlldSKJJHFedkUUYJHFlekJHFUMR[TT\[[{zmUTS\[bMSSVTL]cd{{
+UTSekdSKJLKRddcSKJllkJHF[[TFD;]bZlek]bZek]\UZVZ[UMRkd\lddztluzt[TTb[Ulekd\\{u{FD;VTLmttmttllkSKJMRK74,D;9VTLVTLb[USKJbVZ[TT&&PF=VTLVTL\UZek]>B9D;9tsl\[[ekdkk]mttdc\llk{ttllkSKJ\UZ{{llk\[b]cd>ECLKR:97LKR{{|z\[bf]ctt{MSS\[bVZ[LKRttslldj]\iWUUUYldd[TTf]cf]cJHFJHFJHFFD;JHF[TTtlldc\FD;JHFbVZlldlldddcJHFUMRSKJSKJSKJJHFSKJ{ttSKJkd\ulttll[TTSKJ{zm\[[ult{ttj]\cbV]cd\[bJHFf]cv\UZkk]jcVVTLMRKVTLsreUMRFD;UTSlekllkUMRUTS]cd{u{{{tddcu{{]bZuzt[TTsred\\b[UVTLVTL{ttVTLf]cFD;74,VTLVTL>B9	:97*)([[TD;9SKJVTLkd\d\\VTLredb[UPF=FD;sreVTLjcVek]UMRldd[TTUMRlddSKJkd\b[UFD;D;9SKJdc\JHFtll[[TSKJ74,SKJlld£f]cLKR
+uslev{JHFVTLsreFD;ZbNlldf]cmttUMR{{ekdttsttstll{|||
+{||ultsleek]llkdc\ddctlltllddcd\\\[[mtttt{\UZUTSJHFb[U\[[{{JHFUMRVZ[UTStslu{{{||\UZ\[b[TT]cd>B9FD;f]ctt{:97\[[VTLdc\[[TlritslMRKFD;[TT[[Tredtts{zmdc\UTSd\\SKJSKJD;9VTL]bZrfkttsFD;!D;9VTLJHF\[[SKJUMRVTLJHFSKJj]\d\\D;9i\VJHFD;9ztlUTSlek[[TekdVZTekdlddtsllekd\\]cd{{tbVZJHF\[b>ECLKR]cdlkstsl{{mtt{{f]cJHFUTSultlddVTLUMRf]c\UZf]cv{lekUTS]cd>B9MRKVTLVZT{{tlek¦§¨fkktlltts{||]bZF=C74,SKJddc|
+lldlekf]cdc\zlltll|ubVUb[Ulekd\\tllultddcSKJSKJf]cUMRldd\UZSKJD;9JHF[[TVTLSKJVTLVTLJHF}}{{llk]cd[TTd\\sleultleku{{¤¦|tslf]cVTLFD;[[Td\\UMRD;974,MSSVTLFD;%>B974,MRKJHFj]\kd\FD;UMRcbVjcVkd\ztfcbVC8.VTLFD;VTLek]VTL[TTkd\PF=JHFVTLjcV{zmd\\PF=FD;SKJ[TTSKJbVUVTLcbV]bZtsl¤¤ek]JHF
+
+zllf]clri]bZztl|g\rq^¬¶Ã¨©´¤¦µ¶·|
+¨©´~tllultuztddcf]c{u{{tt{{tuztutllultfkkf]cSKJv{dc\{u{ddc}JHF{{lrid\\|z\[[UTSUUYlksJHFddcD;9edk
+VTL:97lld||{||ttslldldd[TTUTSj]\b[UVTLSKJ:97{u{lddSKJrg]b[Ullkllk{{t{{D;9JHFMRKVTLUTSuzt[TTddcD;9:97sle[TTdc\SKJHR>SKJrfktslmttJHFdc\ttslrilri|z|lek{{t~MSSmtt^fsfkktt{mtt{{\[b{||[[T\[bultkd\\[bVZTmttlek~mtt{{mtt{u{JHF[[Tdc\|llktlltsluzt{u{ultllkJHFUMR]cdcbVVZTddcF=Cb[U||tlltlllddlld{{tdc\mtttll}zlldc\d\\SKJ[TTlekrfkbVZwlaWM74,JHFlriD;9ddctllekdttszllu{{u{{VTL{zmb[U{{u{{tllutll]bZ]bZztlcbVultUMRF=CSKJiq]MRK3+**)(	*)(JHFredsleb[Ub[Ukk]cbVtslVTLFD;ZbNdc\jcVztfFD;]bZbVUtslb[UVTL[TTtsl}VTLZbNkd\rg]j]\{tt|vcbVFD;tll|z¦§¨>B9SKJ}}]cdjcVmttkk]ekdult¨©´»ÂÇ¤¦¢¬¶Ã{{{u{{||}ztlª³·{{|uttsllk\[[b[U\[b]cd|z{u{\UZ]bZlkslld}{||llkVZTMRKF=C>ECrfk[TTMRKttsJHFlddllk|
+mtttllj]\redUMRJHFSKJcbVVTLFD;ek]dc\j]\lldJHFlekttsuzt]bZSKJ]bZult|u[TTUTS]cdVTL[[TsleVTLD;9aWMVTLtll{{tuzttsl¢{||lri¤¦¤¨©´|zzlllksOS`]bZlks]cdtts
+\[b~\[bddcUTS{||||{ttddcedkzllf]c{{fkkUMRttsJHFllkVTLlddztl{ttttsdc\lri]bZddcttsVZ[JHFrfkf]cllk[[TSKJ}lddrfkjcVslekk]lld
+|||
+SKJ{{UTSv{\[b[TTb[Uuzt[[T\UZkjVJHFD;9VTLllkbVZ{{ddc\[[\[[|¢lldddcrfktzl{||
+b[UFD;d\\VTL{ttd\\UTSFD;\[[FD;&&%74,>B9uzt{tt{yfztl{zmb[UaWMSKJVTLJHFVTLVTLVTL|zkk]VTLkd\lldbVUSKJ[TTkk]sleaWMVTLkd\SKJj]\tllutd\\ulektslª³·VZ[SKJzll£v}aWMtts]bZUTS|}}]bZdc\ª³·¦§¨|
+¤d\\ztl|tts{zmj]\f]c¦§¨«²«¦§¨{tt}\[[\[bf]cf]c}|||¤mtttyg{||UUYtt{ttsllkUMRUMRnv\[[}ddctt{{{t{{t\[[lddUMRredkd\lldaWMb[Urfklddsletllldddc\lldvUTSJHFuztv{tllkd\||LKRJHF]bZb[UuMRKUTSkk]JHFbVUdc\{{sleult|ztts{{t{{tult
+
+tts]cdMSS>ECMSSlddmttf]c}ult{{t]bZdc\f]cSKJf]c[TTleklrif]ctts]cdD;9MRKFD;[[TSKJbVU[[T{ttlld|\[bekdlritslUMRlld¤ttsbVUtts}|||ulldiq]
+{tt||lkslektll¤|vFD;JHF\[[dc\ultlri}llk{||tts{{{{b[UztflldddcUUYiq]zlluddctsl]bZf]cultf]ckk]\[bC8.D;9]bZJHF!FD;	74,VZTtllwllddwl[TTSKJrg]C8.dc\sreaWMaWMPF=JHFFD;{ttSKJSKJ[TTVTLek]i\VSKJVTLVTLSKJ|ukd\VTLsrellktsl²²¬\UZ3+*}||zrr]
+tzlrg]ekd|zlldvut!VTL{yf¦§¨ª³·¢u{{¦§¨|
+rfk[TTlri¤¤¦§¨¢¦§¨|uj]\|zLKR{||tt{|
+FD;}||
+lks}ultlri{||lrif]cuztedklksf]ctllttsllkUUYVTLdc\dc\
+SKJ[TTd\\llk{||||SKJsle\UZf]cylemwrg]ekdddc}VZ[JHFVTL{{tslekk]tll\[[ekdd\\VTLb[U{ttSKJkk]kd\{u{|uldd{zm{ttu|z{ttlldultyltzlddcMSS\[bMSSUUYddc\[bMSSlks{{mtt\UZlld{{tsl{tt||f]c]bZ~ultfkkztfMRKMRKtt{SKJr]ZVTLj]\sle{{tlkskk]ttsdc\JHF]cdlritll{tt||
+ztllldtts}|
+f]cf]culti\Vfkk]bZultkk]SKJ>B9VTL|tsl{{
+mtt]bZdc\{zm
+\[b|ztll|tt{f]clri}|tllek]JHFsleJHFaWMJHF*)(:97!JHFbVZd\\j]\sle|ubVUVTLsleaWMztfztfHI/VTLFD;jcVVTLVTLSKJSKJJHFkjV}VTLd\\d\\bVUSKJztl[TTkd\VTLult{tt¦§¨>EC:97{||vv²««¤u|v{{||}*)(&&n¨©´ddc|
+}||VTLD;9tll
+|u{{||SKJ
+tzl{zm¤\[[ztf}{||VTL[TTb[U{{tztl[TTSKJUTSMRKf]cUMRllklddultlekddcztld\\VTLwl\[[rfkkd\}|{||b[Ukd\red{u{iq]|u[TT|
+tslekd[TTJHFD;9[[Td\\|usle{||JHFVZTdc\kk]VTLVTLVTLjcVd\\{{t]bZ{{t{zm||z¢}||lek{{tsl{u{{u{>EC>EC]cd\[[\[bmtt\[b{{ultFD;d\\lkslld[TTlekUMR|
+¦§¨{u{ult~mtt[[TVTLllkSKJztlredlld[[TtsluztVZTJHFFD;lri}f]cbVZztftzl
+red~{zmsleFD;sletsl{u{ddcJHFUTSSKJf]crfk\[[d\\JHFJHFlldMRK|ult{{tll{u{{{ekdsletsl¢mtt}|||}|z|zzl||lks}UMR\UZlekb[U\UZJHFVZT?;C3+*:97SKJ|u}ztlrg]r]ZcbVd\\SKJi\VjcVcbVcbVVTLVTLaWMztl[TT[TTsre
+jcVredb[Utllred{ttredrg]cbV[[T|µ¶·\[[:97££{u{ÃÄÆ
+]bZ£{{|
+lks
+
+}|dc\iWUred||tslred
+cbV£f]cfkklri}|lri]bZldd
+\UZj]\lddllduttslekSKJUTS\[[{u{rfkbVZJHF[[Tllduztwld\\[[T\[[tll|u||{{tlldf]cutb[UUMRztlbVZ}JHF[TT\[[uztdc\|u}
+\[[srelddkjVnVTLaWMj]\VZTllkd\\ekd}{u{{u{[[T}{u{f]cMSSn
+{{~
+ttstt{\UZJHF\[[|z|zultlekf]cvddcekdJHFmtt
+{tt}|{tt{||SKJkd\|ztzluztkd\j]\F=C\UZSKJ{||{u{kd\uttlltllult{u{ztlwl\[[{zmu
+ztl[TT\[b\[[\[[llklri}UTS\[[tll}|mttiq]FD;]bZut}ddcVTLddckd\{tt\UZtsl||¢tyg|
+f]cUMR\[bd\\|VTLUTS>B9JHFUUY3)
+JHFj]\|u
+|uslecbVdc\jcV}aWMSKJb[Udc\rg]nrg]d\\rg]lldb[UztfaWMSKJlldd\\
+||VTLdc\j]\ÄÂ¿VZ[JHF£¥²¬µ
+¢tslu{{]bZ}~^~Y3+*¤¦¦§¨¤}|zVTLiWUyle¦§¨£|z}|slesle|
+}\UZ]bZ¢|z¦§¨tzl{{llkmttj]\dc\{{ttsltts\UZttsJHFSKJd\\lriult{u{{tt||UMRd\\ut{tt}lddldd[TTut}ultkd\lddttstllUTSSKJUTSddcb[Ulri|z}lrisresreJHFldd|£¥¢{zm\[b{u{f]clrilri{||uzt{{
+{{uzt}\[bJHFVTLfkk|z
+{{tult}lriwl{u{tsltyg¢mttlriVTLmw~sle|zbVU{zmVTLf]cbVZldd}|v{zllf]cSKJutult}zllllkcbVkd\{||b[U}}SKJSKJllk
+
+]bZekdd\\f]cFD;VTLaWMcbVj]\ddc{u{\[b~d\\ekdFD;|z}|}}tt{D;9lksJHF:C+MSSJHF	MRKttsi\Vlld{{tkd\f]crr]rr]ultzllkd\VTLrg]VTLrg]j]\|uj]\FD;sletllu\[[{yf[TTUMRaWM}|VTL|u|uÂ¾ÆUUYJHF£¥£¥£n£¤¤VTL}JHF{{LKRr]g|zª³·kk]¢¢kk]
+|{||d\\lld¤¦§¨{||{tttsl}{||]bZ{{redtts|ldd{{lek]bZbVZlks|{{tllk£¦§¨¦§¨|||z|u{tti\Vredd\\|j]\\[[tsl}[[T||lks\UZtt{slev}|z|uf]cuztek]ztlkk]tslSKJ\[[{zm
+ztl}{zmuztfkktt{{{tts[TTUTSlld[TTtts|
+mtt]bZtt{ekdtslllk}mttd\\UMRekdtlltllleku{{MRK]bZ|
+kd\|zkd\wlcbV|ztslekdlddttslldyleultzll
+{ttutSKJzll£¦§¨
+ttssle{tttslldd|
+{ttultlriuzt
+VTLJHF[[TUTSFD;JHFkk]rg]|ztsl|z|z¢{tt{{t£¥d\\tt{fkkVTLredtts[TT\UZ:97SKJVTLFD;
+:97%:97\[[dc\llkztlb[UjcV
+d\\kjVd\\aWMdc\VTLPF=SKJylelddVTLSKJVTLdc\{zmrg]{yfrg]bVZjV[zllwl{{t|u||µ¶·\[[74,¦§¨££¥ldd}rr]b[U}j]\lj}:97SKJztl¢»ÂÇwl||llk£¥~{||¦§¨¤¤v{
+kk]{{||¤¦{zm
+£¥}{ttmtt[[Tf]cldd}{u{tllmttllk}tts{{tsl|
+VTL¦§¨ut|z{||rg]}{||sleVZTFD;red|vztfsle\[btsltts{ttldd
+[[Ttll||¤¦u\UZultlldkd\cbVztlj]\bVU¤¤lriuzttsl|}
+{tt
+{{JHFiq]llk[[T{u{{{|
+mtt{{ttsekdVTLddc|ttsj]\~ddc{ttf]c{||]bZMRKmttu{{|z}{||tslllk|u
+tsltts{tt\UZ{tt|
+bVUllkredrg]}£¥ut|v¦§¨{ttutbVUd\\VTLtllttslks}}Â¾Æ¤¦¤¦|
+f]c{ttdkVkk]jV[llkf]c{zmfkkVTLzldkV¤¦}|
+UTSekd:97r]gUTS:97ultedkJHFD;9dc\,553+*[[TD;9JHF[TTUTS|u}{{t||zll{zmutrg]rg]kd\SKJVTLVTL[[TVTLVTLldd[TTVTLsreusreiq]VTLsleutred||lldwlztl|µ¶·\[b:97£¥
+wl{tt}|}zlJHF¤¦jcV.1
+SKJµ¶·ªÁÅ²¬µ
+ultf]clldv{||v{¤|tll|u¤¤|z¦§¨¤|wl
+¢{ttrfk}ultlritsl}tzllrilksSKJf]c{tt}UTS|zred{||v{tslutb[Uztl{||[[Tzllkd\i\Vldd}ultuzt||tllb[USKJ[[Tllkv{yleldd~[[TMRKkk]d\\SKJkk]j]\}{{tult}|tslu{{uzt{||¦§¨v{{u{{{|
+LKR\UZlddllk{{{{lksnvmttUTSVTL]bZtt{llktll}}|tslMRK]bZ]bZiq]]cdtzl[[Tsre{zm{{t|
+|ztts||rg]f]c|v{dc\llkSKJv{{tt£}llkztl|ztslztf}j]\rfk}sle\[[ultekd{{{{lri
+zlJHFtzltslyle|b[Uuztlrilrilld|ztt{¤]cdlrisreztlf]c{{tll*)(SKJkd\VTL3+**)(D;93+*JHFJHF{{tztl
+}ztfVTLSKJjcVVTLSKJb[UVTLkk]jcVwlj]\kd\i\V[[Tkk]u{{ttslZbNzllr]Zzllyle[TTkd\{{tµ¶·LKRLKR¢£¥f]c}¢}tt{j]\JHFUTS
+¦§¨¨©´²««ldd]bZ|u|z{{tred[TTsle£mttmttuzt{{t|z{{t|
+¤¤{{{{t}{||{||ult¤¤lld\UZllk{||lddb[Ud\\v{uztutlri{||dc\jcV{{llk||{tt\[[kd\{ttb[U|tsl||sleSKJr]glldf]c\UZVTL}|{{tVTL{ttlksSKJtsl[[TJHF
+{{tlri
+mttuztuzt|z|
+ultllk{{{{lks{{}|
+edk{{¤¦|
+{||sleddcddclld|f]c
+¤¤{tttslVTLVZ[tzl
+tsl{ttddc
+|
+|z}ut|mwUTS{{tslelekv{}}ttsutsre\[[b[U{tt}
+{{tslelksd\\ldduztmtt¤¦}[TT|zttsJHFz}llk|
+¤{{\UZek][[T||tlllks|mttSKJzllekd\[b?;CFD;"[TTslei\VsleutVTLrr]bVUPF=VTLjcVd\\lldVTLsrelddi\VVTLSKJwlzl}|lrirg]b[U{ttbVUut|v|ukk]|z¦§¨VZTUTSult}zrg]
+u¢j]\j]\bVUMRKSKJ{tt¨©´¤¦¢µ¶·£utztl{{t··Ä|z}|usleu{{{||{ttu{zm{tt|{||}¤{ttlri¦§¨¤|uv{d\\lek\[[]bZ[TTf]c}uztbVZ||wldc\lddd\\{zmtlltsl{ttj]\ztfkk]SKJ}|
+£{tt{ttJHF[TTd\\ult
+ekdJHF[[TSKJ\UZdc\dc\SKJVTLultult|uµ¶·u{{{u{
+|
+|z{tt£²
+\[b\UZult¤lksu{{{u{kjVu{{\UZJHFj]\]bZ]cd\UZ{tt}
+tzldc\¤{{t{||sre|z|uredf]cSKJ¤¦llkf]cVTLJHFSKJbVU~ylebVZFD;kd\{yfd\\{zmzll|rfku{{d\\r]g{{tf]cJHFultf]c]bZ]bZek]{{t\[[{{{{llkf]cslett{edk{{tldd|u|
+jcV{||ekd\[[VZT[TTF=CFD;74,lldf]ctllwl|utVTL[[TVTLb[UVTLb[Ulrikk]bVZddcSKJsle{ttVTL{zmu|ztsllldlddtllv{rr]wlztf{{twl¦§¨fkkMRKtts£}|tzl
+}jcVVTL|zF=C?;C¤¤¢
+}¢tslsle||z}¦§¨u]bZ
+|{{t||rfk²¬µ¤¤{u{tsl¦§¨¤lddekd£¥||d\\}lldllkbVUzll¤¤|z[[Tsreultulddtslwl|u{{t
+tslf]cekdPF=bVU}j]\[[T}lddtt{f]c{tt:97lldUMRultekd]cdVTLbVUbVZfkk|
+ztltslSKJ{tttsllri|u{{lrifkklkstt{JHFVZ[¢g\rmtt\[b{{tt{¤¦d\\[[TVTLVTL{zmcbVtts{u{bVU{u{uztVZTttsuztuztlddf]c}[TTtslMRK[[T{{v{d\\||tsl
+f]cutrg]VTLkd\
+{{tlek[[T}tygllkljVTL[TT\[[|zldd|dc\lriedkekd]cd{{\UZ[[T}|uzt{{tmttttslriVTLsle
+lldr]ZD;93+*|zkd\{yfFD;JHFSKJjcVMRK|u|dc\utkk]SKJtsl]bZbVUkjVsre[[TtllD;9aWMslesreultj]\sreusreredttsut£ultwlu{{t
+µ¶·]cdMRK££¤ª³·
+\[[{ttldd]bZ]bZzllwl|}||SKJFD;}u{tttll{{t}|tll||£|z¤¤red{||cbV]bZ{u{£¥¢¦§¨ztl\UZ}¨©´|z}
+{||tsldc\¤¤{tt||}slekd\ultsleztlult|vtll{ttllktllredUMRtslVTLtts{tt
+{ttekd]bZaWMredllk|kd\u¤¤|u{||ultlek{{ddc]cdf]ctsl{{lks{{
+j]\VTLFD;[[Tldd|ultllk{||lri|{{t{{t{|||zd\\
+tzl{{t|zu}[[T3+*lektllyfltsld\\ldd}|ut{ttwl{u{VTLcbV}||[TTVTLVZTuttsl
+{u{{yfmtt\[[{u{kjV}|¦§¨¤tzl|
+lkslldkd\llku{{|ztt{VTLusleJHFbVUUTS:97UTSD;9VTLiq]JHF%PF=b[Ulekrg]}|z|||utslkk]kjVVTLdc\llkdc\JHFb[Ukd\[[Tb[U{ttwlwlvtsl{zm
+red²««|v¤¤sle}}¦§¨\[[JHF¦§¨}ultdc\dc\kd\VTL}£¢«²«
+{{[[Tdc\b[U¦§¨kd\¢lri||}tzluzt|z¤sre¢tllr]gzllri¤¤|u}}|zttsVZT}|{{tsl[[T|u
+}||llktll|
+tsl}}lddredaWMtllcbVJHF[TTult{u{j]\UTSllkztl|
+tzlkd\ult{{t
+¢ztltslkk]|u{||lkscbVmtt}
+lksJHFuztmtt|
+ulttt{
+{||mtt\[[{zmSKJMRKlek
+ultult[TTlritsl|ztsllri
+{ttµ¶·||zdc\b[Uedkrfkred[TT}}v{[TTkk]|uutwv{lld||SKJd\\tll{||j]\mtt}tsl{zmztl|zª³·¤¤}f]c]bZu{{{tt||ztlred
+u{{tslu|z|UMR7-2SKJFD;MRKLKRtt{3+*73JHF[[TutsledkV[TTPF=VTLFD;bVZu|u{zmtsl]bZ{||i\VztlSKJedk¤¤wl|zr]Zljzll|vlj|u}|v{¦§¨[TT:97tsluuzt£\[[}|lld]cd~¢f]c[TTb[Uyletzl{{ztl[TTbVU|{{tddclrisreVTLtllultkd\u|z¤{zm}¢lritzl{tt¤¤{{ttslkk]}red
+tslutztllri{zmaWMujcVd\\SKJVTLkd\{u{\[[lri{{tf]cSKJ{{[TTrfktts||lriyfllek{{tult{ttsresre{zm}sretll{||lrikk]{||{{tultf]cVTLVZ[|z]cdmtt
+llk}ttsdc\MRKjcVtslztlultf]ctslult£}dc\|zVTLttsult||
+¢|uztliq]lriSKJu{{UMR|zSKJf]c}
+{||}f]csre{u{ldd}ultuzt\UZVTLlrilld{u{ddcek]lddkk]b[Usle}
+
+¤¦
+\[b{zm
+ztl{|||z}]bZu}|zttsmttlks[[TVTLFD;74,UTS3)
+:97iq]dc\|z{{tVTL
+|ucbV[TTVTL|zsle\[[VTL|uztl}|edktllwl|utsllldd\\d\\}|ztl||u{zmuv{£UTS*)(
+ztfVTL|vlriVTLllkr]Zb[U:973+*¦§¨rfkyfl|ubVUVTLFD;red|ultult¡¡¨©´{{ttsl£¥v{lri¦§¨
+lks¤¤uzt¢tt{}zedkaWMek]|uztfzll|tll{ttwlkd\rg]sle}|ztllrir]gSKJf]cb[Uekd|u{ttd\\UTSulttslsle|kd\uzt
+lkskd\SKJlld|zlld
+{{tzllldlld}ddcf]clksJHF]bZmtt\[[tt{}{{u{{
+bVZFD;tslddclld|uu{{lks{{t|{{tuztekdUTS~ztltt{£uzt{{tztl}kjVuztultjV[|vjV[v||utf]c{{tcbV|{||
+ztfultb[UttstllddcMRKlriVTLFD;lld|
+llk{u{llk¤mtt¤¦
+¤llktt{}¦§¨lriekd]cdf]cbVUVTL>B9FD;:97FD;&&C8.{{t}kk]ultsleulttslJHFVTLVTLsre]bZVTLbVZlldlddcbVlld}wlttskk]||||}|wlbVU|usrei\V|u}>B9:97
+jV[bVZu{{i\Vekdllkkd\aWMVTLJHF¤¤¤¤|
+tts{u{sle\[[tzlr]gtslldd|z||£¥||lri|z|¤SKJ}¤{|||zkk]tsl|
+}VZ[¤|
+{zm}ztflld{zm{||}SKJb[U|[TTredzllztlldduylelj{u{tll||llktllultb[U{{JHFtsl{||lriuv{]bZ}|
+}u{{ttswlsle|ulld¦§¨}ztl}|udc\ekd
+rfk{{mttF=C>EC]bZf]c
+
+dc\\[bVTLVTLUTS|ui\VF=Clldª³·iq]dc\[[T||{||u¢uztuzttsl¢]bZ¤redult|rg]f]c[TT|
+v{}|z|uv{}|{zm||redbVUUTS{u{lld|||
+lri|zkd\d\\kk]u{{ult\UZtts\UZtt{
+¨©´¤u{{{||¤¤lrilld>EC%FD;74,FD;SKJVZT3+*&&C8.yle|z|||z
+}JHFJHFlri]bZVTL:97VTL{u{tzl}lddrfkllk{zmlri|VTL
+rfk}|v{u{}utztfµ¶·MRK*)(ut|z}{zmJHF|zllkuztlekttsi\VD;9D;9«²«}{{cbV[TTedk||¤¤
+b[Ulri¦§¨ª³·kk]ddclldVTLekdSKJj]\F=Cj]\{{sle]bZlld{zmrg]ddcf]cj]\j]\ddcldd}tzlztlsle}ut{||~fkk}|
+tslmttf]ctslUMRSKJlksslef]clddddc{{tslttslriuzttslzl{||utsre||
+uztVTLtllultddcedkekdLKRu{{lkstts
+{tt{{j]\MRKVZTrfklektsluzt}ttstsllks
+tts|lld{||ldd~}mtt{{£¥lek||tts||
+wl£b[U\UZtllrfklddv{|z}j]\|uSKJ{{JHFddcredulttt{ult{zmµ¶·ultldd
+¤¤utlldllk]bZ:97aWM3+*C8.Q?@F=C
+%&&&tlllri{zm
+VTL||VTL|ztl{u{JHFVTLlldJHF\UZ[TTtsllddtlld\\tts[[Tsre[[TVTLkd\kd\}££rg]}sleutµ¶·MSS:97tsl|wlekdJHF|ztt{uztdc\|
+rg]74,bVU
+UTS{||ddcekdlritsl}slellkVZ[{tt\UZ{|||VTLSKJ]bZFD;[TT¤¤¤¤¤¦|z¤¤mttrg]tts
+d\\rg]}|{ttkk]tsllldtslv{{zmkd\lddmtt}}{u{f]cultUMRztlultj]\}kd\llk||lri{||ttsf]c[[Tsre{tt{||ttstsl{tt{||}lek{ttuztMSSmtt{u{ek]{u{{u{f]ckd\lddd\\SKJtslf]cdc\{{t[[Ttllf]c\[[u{{mtt{||ekd|vkd\|u¢²¬µ{ttVTL[[TVZTlri|u¤¦}|{u{tsl{u{{tt|u|zllkultlddslej]\{u{j]\}tzl}UMR[[Tj]\{ttultf]c\UZslerg]f]c{ttvfkkf]ctsl\UZ}{u{{{:97lldmttF=CFD;>B9FD;|zj]\|z|zwlsletzlaWMrfk[[T[TTlri{zm\UZlddcbVtsllldSKJttsttsVTL[[Ttllsre[[Td\\{zmrg]lldrg]||v{zmÃÄÆJHF3+*{{t¢rr][TT|
+|llk{{t|uC8.JHF{{tuzt{{t}lksdkVlld|¦§¨¤¦\[[|
+£¥ztltzl|zlri£¥}{u{utultª³·{{ttslkd\jcV
+||usle
+r]gyledc\d\\|ulld{{tsletllrfklddllkyle¤¦ekd{u{edktzl{zmlekf]c{{VTLrfk
+]bZ|z[TT{u{tzlfkk{{tredlriv{lld[[Ttslzll|z{{t}
+lek{||££
+{{{{{u{ttsttsfkkd\\\[[¤zll{u{||||¤¤]cd|
+
+|
+ut|tslJHFmtt{{t
+¤¦«²«
+uulttt{kd\{zm
+sre{u{\UZlekult|
+lrirg]iq]||ttsldd[TTult||lldredlldv{||¤¤kk]u{{VTLb[U
+\[bSKJ{{r]gUMRuVTL]bZJHF\[b{|||udc\kk]ultrg]\UZtsltzlddclddu{{tts{{tVTLredUTSUTS]bZdc\]bZrg]SKJrg]{yfkd\i\VSKJsreldd¦§¨SKJ:97{zm
+]bZttslriukd\dc\rg]PF=bVUv{¤¦ztl}tsl||¦§¨
+ut{||ddcb[Uttslddkd\lrilritzluµ¶·tts¨©´~£d\\dc\ldd
+jcVVTL{{t{ttztltsl|ztl{{t}|}rg]mw{zm{zmredrg]v{lddredultv{fkkd\\kk]|lek\[[kd\}tll|zek]uzt}uztlri|ufkk|{tttsl|{ttldd|¤ulttllb[Ukk]|
+¤¦¤£¥fkk|z{tt[[Tslelri|z¦§¨{||
+{{tVZTdc\\UZ|
+|
+llk£¥}¢||ekdttstts{u{{{tttsztluzt£v{tlld\\sre
+{ttd\\}{{tldd[TT
+lldbVUtllutllktzl|ubVZlekllkSKJlri[TTttsd\\{zm¨©´||tllbVZkd\}]cdu{{:97{{JHFD;9|
+]bZ:97dc\{||rg]wlekdtslztlllkultsretts}|mtt{{{tt|z{||||d\\slesrett{}b[Ub[UcbVrg]cbVjcVwlrg]µ¶·ddc*)(zll¢u{{lldsleUTScbV{zmHI/ultult¤¤red¤f]c{zmtts{{t£ult¦§¨ult
+dc\{||tts¨©´}
+||cbVtt{{{£¥ttsutvddc||f]cUTSkk]lldVTL{{t||ud\\ztlsre||
+vbVUutlrilldVTLVTLd\\kd\b[U]bZ
+{{JHFd\\ultek]tsl||}lri]bZdc\lek]cduzt{{kd\b[UUTSult}slelekek]tsl{{tred{{t{zmj]\lkscbV{{t|zult
+kd\lekUTS{{ekd{{{||¤¦{||tllek]tt{}{||lldlek{{tsl¢||zmttf]c]cd
+ddcztl|
+u|zuzt{{f]clks|¤¤«²«{u{zllultfkktlllldsle|u£{{||lrildd|ubVUttsultztf}tll
+rfk{{t
+cbV{||mtt|UTS]bZUMRD;9\[bekdzllVTL{ttedkSKJ>B9f]c{zmredVTL}}b[U\[[{{fkk{||lks{{[[Tllkdc\dc\u{{}dc\lri{zm¢ljsle~²««[TT:97¦§¨uztttsj]\f]cVTLbVU{{t{ttFD;JHFyfl
+zllmtttsldc\d\\kk]
+lks}llkµ¶·¤¦
+{|||z|
+{||uztultlritts¤¦{ttult{||sle}£{zmslesreVTLtllsre
+i\Vwlultlldztllldtllkd\VTLSKJ|}lektslzlllriVTLd\\{ttultuzt\[[VTLrfkttsttsuztkd\b[Ulri}{zmrfkJHFJHF74,b[U{{tVTLllktslsrelriutsl|zult
+bVU{u{ekdmttfkk£¥}¦§¨{{u{{f]c}JHFcbVllk}{||
+£{||lld}|
+|z
+
+}|{{u{{JHF]bZredyllksllksreztf|z¤¤{{t{u{
+f]cd\\lldsle|z\[[tllztlred{tt}tll
+ek]bVUtsl²««v{{}|ultekdlekylelldtzl{||slemttuztMRKVTLJHFFD;FD;tzlD;9lldsre]cdJHFJHFddcaWMrg]VTLtsl|edklddlek{{llkUTSddc{tttzlult{||llkult}|{{tSKJi\V{zm£¤¤{||}VTL:97
+v[TTjcVkk]kk]VTLbVU%UTStsl|
+{{tlrid\\lksuzt¤¦ldd{||¤¤}£¥zl¦§¨ekddc\||
+\UZultkd\v{VTLddcleklld¢ultkd\rg]|u{{tlddlrid\\}wlred\[[sref]c|uVTLSKJVTL|uultredfkkd\\|
+dc\lldlektlllld[[Tv{f]c{ttlrid\\zlllriultztl\[buztddclldrfkuztcbVllk}{||ldd}|z||}mttlks|
+tsl]bZ|
+tts}tts\UZtts]bZultlldlks|u||tllldd£¥llk
+¡}fkklld¢\[blldtt{d\\dc\}|v|uedk{||[[T{{t|¤r]g}|{{|zrg]llk|u}||rfktt{{u{zllkd\}|tt{sretll|\UZddcek]
+|z\[b>B9\[[ddc\UZVTLJHFC8.JHFFD;ddcylecbVztllriztlllkddclek{ttttsllkllkttsddclek{tt|
+tslsrerfkcbVv|v£|v|u¤¤VZ[JHF|u{{t}||{{¤~lldtllkk]vsleD;9UMRultsle{{tuztu{{¤
+ultutldd[[Tddctts¤¦}¦§¨b[Ullk£¥|ztsl¤¦llklldlldrg]cbV|uVTLj]\{{tztlztlredd\\u{ttFD;cbV{{t¤¤ultztlSKJ]bZMRKkk]}u{{tsl|zu{{}tts}ylef]c¢]cdlridc\{tt¤¦{zmultlld{||tllllk{u{[[Tdc\]cdlks
+lks{{tt{lksubVZldd\[[{tt\[[]cdut}tll}|
+lks··Äkk]ttsuztllk{{t{||edkJHF
+utuztlekv{~tlltsllri|||ultj]\|utts{ttldd||b[Uslelri{||||||{{tslemttjV[tslllkmttSKJMRK]cdJHFD;9JHFSKJD;9fkkaWMedkv{ddcrg]{zmlld{zmtts{u{bVU|ztll}|
+lddtts}lldtslrg]b[U|ztl||v}rg]µ¶·UUYLKRv¤¤}|[TT{ttuzt|ui\Vrg]FD;VTL[TT{||dc\|z||tts]bZ\UZ}¤¦
+|
+tt{dc\}}jcVzll
+lri¦§¨lksekd
+¦§¨¦§¨d\\lks¢tsl}srerfksre{{t
+utjV[}{||u||tzlek]cbVmtt[[TlekSKJlld|z
+ut|z[TT
+tsl|
+slelldFD;sre|||z{{t|u|£¥v{}{ttultuzt|
+MSSmttu{{ttsllklkstt{{||}lekuztuddculttts{{¤ldd¤··Ä|zfkk
+tslztl|uzt
+tlllekdc\
+
+¨©´||VTL}|||{ttttsu{{||
+
+wllks|zkk]}sle~v{¤¦redrfkn
+£tslcbVztlu{||||UTSFD;ZbN:97:97SKJ[TTcbVsreSKJVTL[[T{u{[TTsleultwlcbVdc\{ttlekztlnvmtt}tllf]clddcbVdc\kk]}||uwl|u£¤¤\UZ>ECztf¢rg]iq][[T}llkztlkd\ttsredFD;{tt{tt
+|
+|zekd{{|||¦§¨¨©´²¬µ£mtttll{{tekdkk]¤tt{utekd
+{{ttt{}|{{tjcV|||wl{{t\[[d\\lld{||iq]rfkvdc\d\\[TT\[[ttsllk|
+v{f]csle{u{|
+lldSKJd\\tll|u£¥ztfllduzt{{t|
+ztlbVZddctsllld}|z{{ddclks}ddc\[[{||tt{{{{tt||¨©´¤¢lkstt{
+{{t{u{
+¤lriztlrfkf]czllztltsl¢}ultldd|z||dc\£¥b[Ukd\{zmtsl}|||}lriSKJrfkultf]c}lks|u¤}}|||}{zm}|zttsb[Ullk\[bFD;%UMR[TTtzlJHFVTLVTLlri}|kd\}|llkttsllkddcllk|ult{{{u{u{{lksult{||u{tt¤¤|uv{¦§¨|vUMRJHF{{tj]\|uttsb[Ub[Ured|v|u{ttztlD;9FD;{{sle|z¤¦llk[TT|zvµ¶·|
+¤¦mtt
+|z|
+{{t{||{||lkskd\f]c{u{
+{tt}¨©´{ttrg]|uldd{u{}|tllkk]tsl
+[[TVTL|z
+~wtlllritsld\\JHF|tsl||{tttts\[bekdllktsl
+|ulritlllek|zdc\lldttsd\\bVUtlltts[[T[TT{{ttsVTL{u{¢lridc\}||||lddf]c{{t{{mttfkklldmttuzttt{lksVZ[{||ztlVZT|llkult\[bv{«²«||¤¦§¨¦§¨{{u{{¤|||
+µ¶·¢¤¤f]csretllllkkd\{||d\\llkulttts]bZlld[[TSKJultv{{||{||tzli\V{tt}fkk\UZ{u{tll||redvuztdc\{||ekdj]\tlllddVTLMRK[[T>B9\[[kd\tsl\[[MRK*)(u{{{||redj]\ttsekd[TT[TTddcedk\[[tts|ztts|
+lekldd}~v tllµ¶·\[[,55|jcVzl]bZttsztl|utFD;sref]cVTLd\\¤¦¤¦¤lek
+ttsª³·ª³·¨©´ÂÅÓ¢ª³·|z{{tf]cult|{ttd\\}tzl}tll|redu{{zllkd\wl|}i\Vw}{zm|||lldbVUttsb[U|tygredzllv{\UZ[[Tkk]{{lkskd\rr]llduztmw||d\\ddcultzll}|ylesle|ubVU{||SKJ}|[[Tult}||zllllkttsutuzt\UZMSSMSS|
+UTSUTS\[[ult\[b|
+{||{||ultedkddcv{{{t{||¤¦
+{||mttª³·¦§¨ª³·utt{llk{|||zf]ccbVtllmtt|z\UZv{jV[sle[[Tkd\{||ttstts{tt|uztlkd\ttskd\r]gtslsleut|
+|||zut|ztts£|£¤¤lrimttut|
+{ttek]JHFJHFFD;JHF{||MSSMRK}JHF|z
+dc\UTSyfllekf]cmttred
+llktts{tttll¤¦|v{zm}¢¢{tt}²««MRK:97£{tt|usreSKJsrezll{{t|u|ubVZsrekk]SKJrfk
+}}lks|zedkUTS||¤
+¦§¨¤¦¤¦|
+lri
+
+tllddcrfkf]cult£{u{{{t|zddcf]c|u
+lri|zrfk{{t{tttslzlluzll
+|ttsb[Ullkdc\uVTLd\\f]cddcekdf]cf]c|
+£}tsl{ttv{tt}lldSKJtllbVZztf}|ultdkV|zllv{{{tv{ttred{{t}ult{|||
+ultllk>ECMSSUTSllkddc
+{{mttfkk{tt{||ekd{||f]clksddctlltll{{tultult}¢ÌÖÐ¦§¨¦§¨¤|uuztsre||
+{{t||
+{{t{{t²««{tt{||ttsztl{ttkd\|ult{||lld
+||}{{
+|ulddult|ztzlztluztl{ttyfl
+lddtll{u{VTL\[[FD;F=CUMRd\\[[TZbNedkUTS¤µ¶·|u{{t{||rfk||z|ttstsl}lriu{{]cd¤{{t{{t
+kk]
+{{tut£tll{zm²««llk7-2}cbVkd\wl|tzlyfd{||SKJPF=kd\|z{{]bZztld\\|ztsl}
+v¤¦d\\lldf]c{{
+rfktlllkstts¦§¨{{}tslMRKlks{tt{zmtll{|||[TTredkd\}uddc||||u{{lldbVZ[[Tek]\[[{u{leklek}|zultsleekdtllkd\redllksleuztcbVlldFD;lekj]\ztl|v{tt|||}ult||i\Vredrfkult{ttultlrifkklld|z]cdmttultuztult^^qf]c||}fkk}||uztf]c{|||
+f]ctlltslddc¨©´¨©´¦§¨£lri}}{||{tttt{ultlddzlluzt£tzl{u{v|}ddclldlld|¤ut|utslekd\ult¦§¨|kd\{{twl
+£|u
+
+lriztllek|}£¥tll}lld}|kd\VZTVTL:97UMR{zmekdUTSFD;MRK]bZ|zsle{{t|z{{tztl{{tllkd\\sle|
+ttskk]llklddlektslztl{tt{zmv{}||}²²¬VTL*)(tzlljcbV|zzlltzlkd\sre}|74,D;9{{ttll}{||}ult¤¦¤¤
+jV[yfd|z|}~||tsl}}µ¶·µ¶·¦§¨{{|tt{¨©´[[Tddcek]sletts|ª³·{zmultsle\[[kd\tslVTL|{{tlddlddulttllJHFultredtsl{{bVZmttlriv|mttkd\kd\dc\|z}{{ttslUTS{{t{ttljtlltll{u{
+ttsultredlddkd\{ttult{||edkultJHFmtt\[bfkk{tt|z
+ult|
+{||vUTSdc\llk|vv{u{{mtt{{|{{
+£}v{{tt[[T|u|¤¤||}}|z}|{zm||{{tmttttszll|¢uztd\\{{ttslztf|ztsl}}tslsle}{u{kd\d\\}ekdrfkJHF||bVUlekb[USKJJHFFD;MRKSKJVTLJHF|\UZ|
+f]c||u}|llk
+ekd||lri{||kd\MRKred{|||ztts||ultu{{{||
+{||kd\|u«²«}}{{tsle|u}µ¶·JHF-1+|z
+rg]kk]jcVvb[Ub[UVTL3+*
+
+ttsVTL}tts|zmtt£¥tt{¦§¨}llktt{¦§¨¨©´£{tttslf]clkstsl
+{{||v¦§¨ultttsdc\f]cut||redi\Vkd\zllVTLldd{||[[Tllk||ttssredc\bVUttsSKJ}ultllklriredztltsl}d\\ztl{ttdc\d\\|uztl}|cbVkk]kd\||}|wlkd\ult{{ultlldfkk|
+JHF\[btlluzt{{}|{{t{u{ddctll
+{||lri{tt|
+|z||}edk
+|zsle
+lek¦§¨{||tsl}}{{t{{t{{t|zdc\rfk¤¦}{||
+llk
+ult|
+{{tslett{{{|}|bVZlldlekztluztkd\D;9VTLFD;[TTsleUTSf]c&&\[b|u
+}~sle|}}lldztlttsttsutlld|v{yletsl|¦§¨:9774,|u{{t|urr]rg]
+tslyle{u{||VTLSKJ}}¦§¨|}tt{lri£¥uzt
+£ult|z«²«|
+||
+¤¢
+dc\d\\[[TUTSrfkldd|
+}¤j]\b[U{{tkk]{tt|kk]uzt|zttsf]c{{tsletsl}d\\v{|z{{ult{||}uzt¦§¨{||jcV\[b||{u{
+ultut{{ttll}|}{u{f]c}lri|
+lri]cd\[[ekd
+tt{{{
+tsl{u{{||||ekdtll~llk
+wlultµ¶·
+wlult|z}|ultult{tt{{t{tt£||sletsldc\{||lek{{t{{t}£¥¦§¨¦§¨|tllmwmttd\\mttztl{u{
+{{t|
+redlldtll}|
+rg]uzttygC8.dc\[TTldd\[bmtt\[bkd\rfk
+{{t[[T|
+ttsv{{{tslellk¦§¨£|¤¤ztlutÃ¼¿SKJ:97kd\kjV}ztlkd\}d\\tsl|zuzt}{zm[TT{zmuzt£¥u£¥|b[U£¥{||{u{{{{{t
+{||£tts\[[ek]|
+u{{ulksult{{t{{uu{{ut}
+ª³·||b[Usre||sre}tt{|||uult{ttsretzld\\lrir]Z|zut
+¤¦tts{{t{{{ttek]tslkd\d\\tll£¦§¨tlllddf]c|llk}|||ldd£sre}{{|]bZ
+{||
+{u{|z|
+}mtt{||
+|zttstt{}tllultldd£¥¤¨©´¤¦¦§¨«²«u¦§¨
+f]cttsµ¶·
+tzl|z}ut{||ldd|
+{tt{{t{zmuzt£¥{u{||{tttts}lddldd{{t[TTllk|u¦§¨|}u{{~ztf{{tslekk]D;9ult{{|z
+mttUUYd\\fkkzll|u¢uzt}{u{\[[~ddc]bZ[[Tddctsltslb[U|{||¤¤£v{ztl¦§¨[[T74,{zm}}|z{zm|zllduzt|||zztlldd[TTddc|
+{u{{u{}}VZ[u{{
+¦§¨|ldduztdc\lkslriult
+{tttsluzt{{d\\}}ult}zll{ttldd}{{t{{lddtsl{||u||kd\|uultj]\tllllkrfk||{{t|{ttlld|zrfkj]\v{mtt}lekrg]}
+
+ztl¢
+tslldd{tt{{}reduztkd\b[Utts{||{{|
+{u{~mttlks[[T{||llkdc\rfkmtttt{|
+}f]c
+¤£~tsl{{tt{{zm£¦§¨}¤|u¤¦
+{||v{}|u}lld|lldut¤¤utttsut~mw{tt|ddc|lks{u{
+|z}||d\\sred\\|z|v¤tts\[b>B9f]cJHFtll{||uztkd\tsl{{}|z}¢{||lld{{t\UZmtt|llktslSKJVTLkk]kk]{{t}|tll¦§¨VZT-1+||
+|ukd\tzlVTL[TTllk}ulrilks{{t|zlks|sre[[TUTSUUY}zll£¥||lri|
+cbV
+
+slettslrikk]lddlkstts|
+|u[[Tttsekdlddtt{[TTztltts{u{ut|zuu
+tll{u{lddkk]vlddredbVUtlllld}tt{||||z|b[Utts{{t{u{sleSKJd\\d\\}sleldd[TTddc
+ek]utllk{u{{{t[TTkd\|
+slelrimttlek|
+||{{
+{{{||llk{|||z
+
+|
+{||||{u{}{{}¦§¨|zult¦§¨{||{{|zlld}{||¤¤}|{u{{u{||tsl¤¤|||{zmd\\f]csle{||}{u{£¥uztbVU|zkd\tsl
+|z]bZtll}}sletzl{{lddtzltt{SKJJHFFD;llk|ztsl|ztt{sleztl{u{kd\ekd{u{[[TbVUtts|ztsltt{lldlrib[UaWMcbVdc\tsl}tsl|vJHF3+*}|uwltsltslsletlllri|u{{sle{||ddclri
+\[[ttsf]cUTSzll~{u{¦§¨sre||mtt|zf]cttssle¦§¨ddctsl:97ek]VTL[[Tttslri{|||{||v|||z
+{u{zllv{}ult|uztlult
+sreyfdsleredd\\kd\bVUttssre|
+]cddc\{||ttsredredUMRd\\
+|ud\\yle~|u{tt}{u{ttsreduzt}tll{u{\[b]cdyllks|
+|
+}
+llk{{|}}|¦§¨|ztsllld|uult|z¢\[b}{tt|zsleult|uv{}tsl}{zmsle||u£¥{u{utlld{{t¦§¨ult||}||¤¤tts|udc\tt{¦§¨£zll|zj]\[[T}|SKJ}SKJVTL[TTlrimttddcwl{{tu{{tt{||{u{v{b[Utsl{{}lldlek|ultttstslv{{zm¤¤tsl{tt«²«JHF*)(}uzt||f]c|udc\|ulritllUTS|ulri}SKJvlldekd\[[UMR{tt££¢}¤lks}{{tredlldSKJ{||tsl~uztlri¤||z¤
+||¦§¨ult||zllztl}£dc\|}rg]£¥|zd\\tlltsl{ttrg]ultSKJ{|||{{tsre{{t}||tsld\\mtt{ttsleldddkVbVU{||{||mttuztllk{{
+}lld{||[[TbVU\[bd\\\[bedk|]bZ
+u{{|ztts|u{u{¦§¨|}{{¨©´¦§¨¨©´zll{u{|zleklld[[Tlld{{|
+|zztl¤¦utVZT}}£¥
+{tt[TTkd\ek]}}|
+}}|ttstsl||{u{}||||}|||||ubVU||rg]ztl|
+ult[TT{{tslelrif]c{{ldd{|||z{{t{||d\\f]ckd\VZTtts{u{¦§¨{ttv{lks¤¤¢¢«²«£¥¢¦§¨
+VTL*)(sre|lriztl|uVTL{{t
+}{tt[[T|zb[U£¥{tt]cd
+£¤¦ut||}|}
+zl}vsle[TTUTScbV|udc\¤{||u}¢u{{v{}tsl£¥}tllut|zek]zll{zmv{{tuzttll|v}bVUztlslered}ldd}sle|llddc\{ttllkd\\{ttkd\tll|zj]\}}
+{tt}llkllk||v{}tll{{ttstslmttf]c{{mttuzt{{|z|
+{ttVZ[{tt}uztv{~
+||tll{||ddcv{}¤¤¤dc\{||£rfk}}ztl}tslztf{{t{ttkd\sle|u|zult}··Ä£¥|j]\}red¤¦§¨|utsl¤¤{||utlldtzl
+{{tSKJutVTL{{t~f]cJHFlritts}ultj]\}llktsllks|{zm{{t}tsl¢~²¬µµ¶·µ¶·¤¤¦§¨\[b)+2}|}dkV|u}sreVTLsle|ulrimttztl|
+\[[lrizll|uuztVTL¤¤lld}lrif]ctsllri{{¤¨©´
+{{{u{¤tllsle}{u{}sle{ttj]\}ldd{zm|u||sledc\|vj]\]bZtll{{t{zm{u{|ukd\
+ttsedktlllddsleztf{u{||v{tttsldc\v{|u{u{uedk{u{ttslldult{{t{||¤|zuzt|
+|
+|
+|zlksu{{{zmlek}tt{}£ultlks|{||
+|
+tts}
+{{ult¦§¨yfl|u
+sre}yfdztl|u|u{tt|z|zrfklri{ttult¦§¨¦§¨|
+¢{tt{{tuzt}lldztfVTLSKJsleuzt[TT:97f]cmtt\[[lri¤{{tmtt}{u{¦§¨||}ek]tlltt{[TTu}¦§¨¤£¥¦§¨¦§¨JHF*)(lri
+ztliq]lld{u{VTLtsld\\|uzt¤||uztu{{u{{tll¤¦ulttts{||£¤¤
+rfkldd\[[{{t{tttt{u{{|zultred²««||{{tllb[U{||tts{zmslei\V}{ttutddcddckd\|ud\\}tll||zll
+UTStll|zusle{u{tts}}{||{ttf]ctllwllldsle|||z{u{ultttstts{tt||||lks||lriu{{|
+|
+VZT]cdu{{{{]bZ}¤{u{tlllri¤¦§¨}|sle|ulttts£¥
+«²«{{tJHFztl{{t}ult~tll££}|}lj²««lri{zm}|zllkd\|z||UTS{tt{||tll\[[}|{tt{u{¤¦¦§¨|z]cdztlVTLSKJ}
+MRKSKJuztd\\mtt
+|tt{|
+
+}}ttslkstlltsl¢{{t|ullk||tts|¦§¨MSS*)(cbV}{{t|cbVdc\sreztlekdldd|u¦§¨¦§¨¦§¨|zJHF¦§¨|[TTred[[T}²««~{zmllk{{tut
+}|
+¢{{lks}|z
+¤}wlv{yflf]clld{|||uddcdc\uztb[U||{||²««}|tllkd\lekut{tt}tt{|lektllztlrg]tts{u{lldv{{{tddcVTL||ult|sleiq]]bZlri¢}\[[v|sle||
+{tt¤¦{{tu{{u{{fkk}mtt{{\[btsl{{tkd\lekultddc{u{UMRuztuzt¦§¨u
+{{tllk¦§¨
+µ¶·{u{iq]tll}{{²««}{tttsl|ttsuzt}|||b[Utsluzt{u{||ult}{ttedkSKJsle¦§¨tt{u¤¤}¦§¨
+slecbVrr]SKJdkVMRKf]ctzlmwekd}ldd}tts}
+£¥{||tll|z{{ttslztl}ult²¬µ[TT*)({{t¤¤lks{zm{tt||{{tuzttslyle{{t|z¨©´²««ultuzt{||f]c{tt¦§¨mtttlltzlttssle]bZ}lri\[[¤\[[uzttt{tts{tt£|uzt¦§¨ttslddb[U|zddc{{tlriztl}ztlttsztllddb[U|uslekd\{{t}|z{||¢{{j]\|VTLtll|z¦§¨{u{ttsllk{{ttllztl|z£}¦§¨tlledku{{ddc|z|
+ekdmttmtt|
+|tllztlztlultult
+tts}£¦§¨v{|}¨©´¦§¨¢¦§¨¢¦§¨|{{t{zm¤¦{{ldd||~|u|udc\¢|||u||£}}ª³·u{{}}{||
+||tlltts£|lddedklldztlkd\£¥¤¤|ukk]b[U{tt
+~mtt}tts{||llkVZ[{tt||
+mwmttuzt{||¦§¨||}ddc||[[T{u{{zm£¥{{}}|LKR)+2ud\\}|usleuzttt{VZ[VTL}\UZ|u|
+u{{|z
+£lriuztcbV|u|}|tsl\[[|zu{{|ulks£²u{{tzl|z|ztl{u{{{tlrittsvtslsleylelrirg]¤¤ztl|uult}ztlcbVf]cd\\|u{zm}|{u{lldtslddc|zu|tsl{||d\\sle|u{||sre|u
+d\\|vkk]tlltsluzt}sre}|||{u{{{|
+tts|
+ztl}{||¦§¨¤¦¦§¨¦§¨£µ¶·²««}¤¤µ¶·ª³·¨©´tt{sre}ddctslult{{}
+tll|z|z¦§¨¤|u}}yle{||¦§¨llk}£¥f]cred
+lddldd|z¤¤uultdc\£ztl|zVTL{u{lek{{tv{llku{{v{lek}v{|{tt|
+llk¦§¨}¦§¨¤}kk]ult
+f]c[TT¤¤JHF:97sre|{tt|[[Tb[U||lldtlllrilld[[T|z}tzl{||mtt{{t~ult||u
+||}tsl¤¦|
+dc\\UZ\[[{{ddcztlVZ[ztl}}|z}lriddc}{{tsre}{|||z{ttdc\tts|lldkk]ztlSKJi\V[[T{{ek]||{ttzll{ttj]\|zllutztl¤¦llk{tt{|||ztl}zllllkdc\lldultUTS|ub[Usle}sre||{{t|z}
+{{t{||\[[{u{{|||
+]cd|
+{|||¨©´{{t{u{{zm}
+zllred|
+£¦§¨¦§¨¢¤¤²««{{t¨©´|µ¶·tzl{||{{¦§¨¦§¨£||{tt
+wllri|||uvut¤¦lri£¥{u{{tt{||{||{||ult}|||{tt{zmyle|uzt]bZ¤¤|z£¥u{{ult]cdf]c|ult
+dc\|lekredsrev{||{|||zbVUrfk¢{{tlld|uldd{ttzllut:97JHF{{t|
+sle|||||u|ekdlritsl|||tll|
+VZT{{t«²«||}
+{||b[U|
+sre}lekttslri\[[lkssleVZ[{u{
+£¥{tt{{t||lri{tttllVZ[|||f]c|{||sretsllddsre{{tsre{{td\\{||lldd\\|v||b[Ukd\ldd
+¤¦tsllldb[UUMRtllred[TTtsl{||}{||¦§¨¦§¨{ttut|ukd\tt{uztldd{tttt{fkkmtt{ttu{{{{
+ulddtt{¤ª³·«²«£¥¦§¨£{||¢£¥£|utsl«²«vrfk¤{||{u{tts{|||vvv{
+{{t
+{{{{t{{t¤¨©´¦§¨¤¤tzlzll||lld}µ¶·²²¬||\[[||ttsMRKztl|
+lkslks}bVZ
+¦§¨ult}}ut{u{{u{SKJlrifkkred|u|}||utlddJHF:97rg]|z|tzllri¦§¨
+}tll}{{t]bZVTL||§²¢llktts|
+d\\tt{d\\\[[£¥yle{tttlllksttslldVTLleku{{edkd\\UTSult{u{slelrilldu||}{ttztlldd|zttsv{lld}j]\jcVkd\VTLtzl~ult{zm|u[TT
+jcV¤¤ult¢¢{u{{{tdc\}bVUldddc\{{ztl|utslrg]}||}{{tlddztlkd\sle{|||zult|
+|{u{
+ttslriedkUMRtll{{t{u{£¦§¨¤¦µ¶·¢}|¦§¨£¥rfk¤¤}{{t}ultiWUzllrg]utztf}|ztl|ukd\|u}u{{ttsmttllk{||ulttsl¢uzt¨©´}|z¤¦ult£¥uztzlllddttsVTL[[Tsre¤¦f]cJHFultultzll{tttll{u{|z||{{tsledc\|zw{{ddc||tsl{||ztltll|v£lddultldduD;9,55|UTS{||lld\[[{u{tll|zuztult|u{tt
+v{lkslks]cdddc{{tcbV~d\\wlf]c
+||
+£¥utzl[[Tmttlld\[bttstt{lrittstsl|ztl|
+zlldc\{||sleVZTuztlri|tts{tt}|MRK£wl{{tsletllkd\tslsle£{u{lriwltt{}tlltll
+lldutb[Uredllk||}{tt{{t}
+}|ulttzlf]c{{tsled\\|u{u{\[[]cd}tts
+}{||edk{u{kd\|z}}kk]ª³·tts£¥
+£¢¨©´ut²²¬²««¤¦¤¦¦§¨[[Tztl|}{u{{{t}|b[Uztl
+|uek]¦§¨£¥}~utztf¤¤{||{||tll£¥ulttt{tsl¤£|¤¤¦|u¦§¨sreuu{{lld|
+JHFdc\tsl
+[[TUMRMSSUMRultlks{{t{{t{ttldd{||llkuzt{{ttts{ttlld[TTv{ut}lldldd~£¥:97*)(|}ztlu{{|d\\}|u|
+tts{{tUTS£
+ttsredldd{u{llkekdtt{¤¤{{tlld{||ttstllv{mttdc\||ekdlrikd\{tt¤lri|
+tts}|ztll}tzl}{u{LKRd\\rr]f]cd\\ddcf]cutdc\kk]ztl¢¤¤tt{srekd\[TT[TTj]\ultsle}ut}|tslult{{||
+|uulttsl}{yf|u
+
+zluzttllrg]|
+tsl{u{{ttvdc\{tt{{{u{{{{ttred
+¦§¨}¢£¤¤ztl|u{u{|u
+¤¤|rfk¤llk|u|¨©´tts¨©´utzllrg]}jcVsrev{red}ztlkd\}VTLtslv{kk]lriedktll{{t¤¦§¨¤¨©´«²«
+{{mttd\\VZT||||[TTJHFf]c{{f]ctslutlri|
+{||uzt¦§¨¤}|u|wlult{||
+ut}£¥JHF*)(|||mttztl|uut¤¤{{tlri{||d\\ldd]bZ}}|z|z¦§¨¤|u¦§¨uztlrillddc\{{tztlrfk
+kk]¤|
+[TT{||tts{||{ttlldllkmw\UZ{zm{u{||v{tslsreztfwlkk]ddcdc\ultzll{ttv{{{tkd\dc\d\\d\\[[Tkd\rfktslVTLut£tslb[U{ttulttllztltllut|zlrif]c}{zm}d\\f]clri{|||zlldtt{{{|
+||}|
+tts}¤¦uztsle}
+£¦§¨£ult}v{}¦§¨}|
+zlldc\
+dc\{||||mtttllv{{tt}|}|kk]slev{utztf}|zsreSKJllk{||kk]¢
+¢ldd|
+¦§¨
+}£¥|z{{lekttslrilddlriv{ttf]clri}¢|{u{}|
+|
+
+~¦§¨ztl}{{ttts|z{u{{u{}|£¦§¨¦§¨||}£:97*)(}
+{tt}|}
+||{||¢llkkd\{u{
+tts\[[zl{||µ¶·¦§¨|u¢{{tslerfk¢{{tdc\}¢ek]f]c|
+|v{zll{tt{u{[TT{{tllkzll{ttllklribVUultf]cdc\{{tVTL|||lri{zmkk]|lddtll}VTLred}f]c|zsle||tllddc{zmbVUudc\[[T{{t
+||}ztlttsultttsfkkllk|z\[bttsmttlrittsultutult|u{{tttstll££{{tredf]c}¦§¨¢|\UZ|ztsldc\{||ult{{tv{ztl}zll¦§¨b[Utzl}dc\
+}wl{zm{{tuzt{tttzl{tt}{{t¤¤uztu{{}tsl{ttfkk}|{||sle]cdtts|u|z|£edkf]cult}}|¨©´|
+u||v¤µ¶·¤¤¢lddultultred££
+wl¦§¨JHF)+2}ult£¥v{slelldlek[TTlksv{|}uztu{{{u{¦§¨}¦§¨¤¤|¦§¨£|u£¥mtt[TT|zlek{||{||lldultddctslsle¤jV[{{trfklekv{f]c||lddd\\d\\b[Ullkrg]{{tkd\|
+}|ttstts||sle
+n|u}lddlddtllkd\utrg]f]cztl|
+u}b[Ullddc\||}{u{llk{||tsl|u{ttddc}{u{ddctt{{{ttt{¤UTSv{lek|zddcd\\kd\ztl
+¦§¨Â¾Æ£¤¤«²«}ult|vuzt}}{||¤¦§¨{ttd\\||²¬µsresretsl¦§¨¢v{}{{t||lld|z|ldd}uzt||{u{tts£¥|
+]bZ|u|z|u\[b\[bbVUkk]¢|tsllld{u{}|£¥¦§¨dc\¤¤{zmzll¦§¨£¥
+²²¬\[b*)(zll[[T{tt|uddc{tt¤¦||ult{{t|u}edk{||tt{|uztl|zulttzl||ztltts]cd|z|
+u{{
+llklddtllmtt|}tts{u{}¤tllUMRllkttstll{ttmwSKJ[[Td\\
+cbV|uyle|ulld}ttssle}£¥{u{¤zllrfkf]ctsl{tt{tt{zm}
+||¤|kd\llk||zzlltsl{zm|{tttlltsl|
+{{t{||{u{
+lriv{ult{||¦§¨|||££²Ã¼¿¦§¨{zm¦§¨²¬µ{{t
+f]c¢¦§¨||}{{tlri|v{lekf]cwl{|||{{tsre¦§¨|z¢ddc{{ttsl}llk\[[}ztl}}fkk¦§¨ultllksle|z{||VTL\UZ}£¥lddedkUMRf]c{{tult{||utttslddllk~
+uzt
+tsl~|z}j]\
+|tt{µ¶·f]c*)(tll|u
+mtt{u{}|{zmtslf]c|zlrikd\[TTtt{|ulri¤}dc\}{tt¤¤tts²««{{t|||utt{~{{VTLv{|z¤
+|
+}}utdc\kd\\[[ut||{{t|ulriv|ttsttsllk|z
+j]\{u{i\Vsre}||VTLylellkztfmwlddtsl{zm|}{u{vutullksre}d\\kk]}ut{ttut{||ekdtsl}|{||{{t{{¤{u{¦§¨{{t¦§¨µ¶·£¥
+£¥
+¤|¨©´tllv{u{ekd}
+|kk]ttsrfkv{||zlllri
+¦§¨£
+ut}{{t{u{tsl{{tu{{ddcttsu
+{||{{t¦§¨{u{tll¢
+lek{{|
+d\\ult{zm¤¤ultlkslks{u{rfkdc\}lri{{t}{{tut{tt|llk{zm}||tts{zm{{ttllrfk}{ttsre||{yfztlJHF?;C
+
+}tzlulttll[[T\[[ult||tll|||z||
+
+lriekdlldu{{ult|ukk][TT{ttkd\ddc|u{{t||tllek]ddcw[[Tllkd\\
+f]c{u{llkutlrittstllultsle{ttj]\{||ddcsleztl[TTredlddzll||\[[v{{||{{t¤{ttlldu{{{||lek£tsl||ztl
+tsl|z£¥|
+{{ulri|llddc\{tt|ztfult||lks{{t|
+{u{tll¤llk££¥dc\|z¤¤ulttll}ult|lldlritll||kk]ut¨©´tts{||
+rg]||£¥}}|||{||²¬µ}ukk]v¢|¦§¨ldd|
+|
+~]bZult
+|slellk}|z}{u{|z]bZ¢}|
+JHFlksult|
+|tll}{{ª³·wl
+v¨©´slettsut{||ttsztl
+|uztl{{tek]¤¤:97*)(
+tlltslekdult}|ultkd\mtt||
+u{{kd\{u{lddekd{{lekVTL¤¤¦¤¦¤¦{{{|||
+¨©´lldtll|z||tsl¦§¨ult|
+ddc||}{{t\UZllk{u{}ultj]\r]g{||||{u{j]\}tsl|v}ª³·ult{yftzlutbVUllkzllf]c||uttts\UZ{{tztl|||lld{{tzltts{{tttsut{||d\\ztfzllult
+||{u{lksllkztl¤²¬µ£{{t{{tllk
+v{¤¦¢¤¦{{utkd\lld¨©´{{ttzl¢
+¦§¨£¥¦§¨££|u{{t{u{dc\ut{{tjcV{u{lek¢mttuzttzllrimtt\UZmtt{tt¦§¨ztltt{¦§¨tll¤¦|UUYUMR\[bult
+uzttll}{||lksulttt{lddsretsl||tll{u{utv{}{{t|z||lld¦§¨VTL74,tt{||v{[[T]bZlekztllri{{ult{||llkultkd\sle¦§¨¦§¨¦§¨ut{{t||}{||b[U¢§²£¥mttultf]clddttsuztSKJ[TTultultllki\V}{ttj]\£||¤¤dc\}{{tVTLutSKJtzlb[U{ttSKJ{ttkd\bVU[TT}{ttuztzllkk]tll{||
+lddbVUutkk]lritts}
+|z¤¤{ttrfk{tt}
+ttstll{{{tt¢kd\
+ultttslldsle}£|
+
+£}¦§¨¢
+u{{tzl}edk¦§¨v|red¦§¨ut|
+}{||
+£{zm}¦§¨¤}{{t||z|zllk|zddc
+||{u{u
+}tt{µ¶·lri¨©´}[TTf]clek¦§¨{||lld|zmtttt{{{t||tt{{u{redd\\}¤{u{tslztlulttllut}}{tt
+tzlmtt{zm¢JHF:97{{t}dc\
+ztlztlllkdc\|cbVzlultllk{||ult}v|
+|}tt{¦§¨¦§¨{tttt{lriztl{||tll|VZT|z¤tt{fkkllk||[TTJHFf]c\[[lldultf]cf]c\UZllkultlekyfllek¤¤}{zm}wlSKJd\\JHF{{t|zsre{{t||red{{t|usre{||}|cbVtllzll{ttztluttllllk||{tttzlVTLtll]bZkd\u|¤lld{tt|v{}|{|||
+tt{{ttmttultzll¤¤}lddldd£ddc||
+¤¤tts£¥}¦§¨u£¥£²|uredu{{ztl~}||£¥{ttb[U£kd\}kd\|££}|{{ttts£¥{{tlritsllriz}tslultztlzll¤¦}||{ttztl
+||z\[[¢lld{u{
+¤¦¤
+uzt¤¤{tttll¦§¨|{zm}|ulttll{zm{{ttll¤¤JHF*)(ultcbV|ztts]bZred{ttj]\tsl|kk]ult¤¤f]ckd\bVU
+dc\d\\¤¤|z}|}|zll£¥{{t{{llkuztowlkstt{¤u{{UMRd\\lddv{UMRj]\ultmwtsledkUTS||||tt{
+tll{{t[[T{ttredztllldlri}tzl{{td\\u|u||u{||£ldd{tt[TTd\\FD;rr]{tt{tttlltsllldd\\ztl{{tztltzl{{t|z
+
+ztlrfk{u{{{ztllddj]\mtt{ttlektt{\[bllk|z¤|||tll{||¦§¨£¥{||ª³·¤¦u}··Ä£¥¦§¨«²«f]c{{tf]cldd{tt}tll}cbVddc{u{||ztltts|}¢|£¥ztl{{t
+u{{lddlrimtt]cd]cd}edkj]\|u¦§¨redult¤¤¦§¨uzt}|
+dc\tlllri|
+|ztt{u{{¤{{t|||¤¦}tsl}|z}|umtt{u{{zmztlddcztlult{ttztl||kd\|uultf]c{{||£>EC:97tslSKJ{{tVTLwl}|{u{d\\rg]|z}mtt¤{{tbVZ{u{sre|
+|{||zll|z{u{uztulttll{{tldd}{tt|zUTSult\[blrilldf]ctll£¥mwtsllek
+JHFuzt¦§¨{tt[[T{||kk]utSKJredv{llk|zvd\\tslultedk}||
+b[Uztl
+}kjV|utll{{t{ttdc\||{||lldu
+}}tts{tt{{t}|{|||
+{||ttslektt{{tt{||¦§¨}{{tv{tsl
+¦§¨µ¶·¤¦tsl{tt
+¦§¨¢¦§¨
+}¤¤¦§¨£¢¦§¨ª³·{tttts{zm£{tt{{t{tt\UZred{u{uzt}{ttbVU{|||
+]bZ¢
+ultult|zultdc\llkkd\tlledkttsultfkklks\[blekllk{{kk]¤¦¤¤¦§¨ekdtts}{||{u{uzt{{tdc\|z
+{{tztf
+llk
+:977-2}llk{u{|{u{tzllld|zlldu{{ttstt{lriult}]bZkd\{tt||tlllld}
+|z}rfk¤¤|z|{||¤llktt{lksf]c{u{SKJ}{ttlldtll{ttv{
+|z|zuzt[TT||llkwlrfkVTLsle||slettslldtts|zsle||aWMSKJFD;ztlultu{{[TTslelldkd\|utslttsuzttllb[Utyg{{ztlsrekk]{{t¤¦§¨ddcsle
+|ztts
+}{tttt{{||ddc
+{||{{tts¤¤~
+}¢{{t£¥¤µ¶·¤¦¤¦¤¤¨©´µ¶·¤µ¶·¦§¨£¥f]cmwwl|uuztbVUlldddctsl{ttsle|uult{||rg]|}lri{||mtt|ztt{ddc
+¢{||rfk£¥}ztlzll||ldd|v{uztVTLultSKJtsl[[Ttzl{||{||{tt{{ult|{{t{u{}|||tsl{u{|u{tt|
+uzt>B9*)(zll|||
+{{tllklddbVUd\\lddek]UTSlri[[T{{tslult{{td\\}u{{cbVbVZ}sleb[U{||zll{||}tsl{ttu|zuzt|
+|
+{{\[bJHFJHF\[[f]cd\\\UZb[Ud\\ttsd\\VTL}{zmtsl{|||u{{t|f]c]bZsleldd£ddclld|ztzl|utllaWMsre{{{zmj]\tll||tslztlf]cb[U|z{||}dc\|
+zllek]tslut
+{tt|lriv}¤¤tlliq]tsld\\{||{{t|z{{}}{{{||}{u{||}¦§¨¤¦§¨¨©´{{}}¤¤¤¦sle~£¥¢|||u{{t|||z\[[v{}ztl{||tsllldj]\ttstzl{||wl}lld||lldmttlks|
+lksuzt{{ttts}{{t||lri¤¦r]glldmtt|zldd§²v{
+
+tt{{{|~{{t
+{{tdc\VTLtllVTL]bZJHFJHF|z|
+]bZSKJd\\ultddcd\\b[U|
+|zlekttssleultuzt{{t{{|
+|zllkldd|ztts{u{ldd}|z|zMRKddcult]bZlddultf]cmtttsl[TTultd\\lddu{{}tllj]\f]c|ukd\{||{u{[TT}|{u{sreztl{zmcbV||tzltzlultkd\{||llk
+zllutult¦§¨kd\VTLsle|zdc\||ztlsresrekk]tslutsleldd
+ulttlllddllkSKJiq]tsl}{tt{{{||llk{{¤¤|z¤||tts{{tkd\||¦§¨{||}£¥¢¤ult|z¤£¥uzt¨©´tsl|
+{{t|u¦§¨¤¦}¤ldd¦§¨£¥dc\ldd|utt{
+tt{¤¦tsl|
+|
+{{t¨©´{{|
+ttsut}sle¤ut{||ª³·£¥ekd¤¦£
+§²|z¦§¨¤¢tsl}ztl{u{llk||¦§¨
+}
+v{{{t{||{ttj]\tts}|zttsddcSKJ*)({||dc\lddtllVTLf]c{u{uztttstslu{{lriu{{f]cu{{lld
+||||²¬µdc\b[U¦§¨llkuzttzlddcu{{d\\ddcJHFVZTSKJv{tt{[TTlks||tsld\\[TTddc|utts
+{||red{ttd\\sled\\}\[[zlbVZ}|||||{||v{rg]rfkkd\|kd\{{tslesrelldred|zsletslztl
+{tt|u
+}|}{{t|u{tttsl|sle|v{tsl{tt£tts|
+|{u{ttstt{mtt¤v{llk{tt}¤ztl£¥¨©´¤}|z¦§¨}¦§¨µ¶·Â¾Æ££~¢¢}¦§¨{tt¦§¨{||ttsut£
+{||}}}
+
+ult|
+lri|
+
+|
+|zult|
+dc\²¬µ{u{}|u{zm{tt¤}{ttttsu{{ª³·¦§¨j]\uzttslv{}uztbVU||ztl{{t{tt{{tut{ttllk|u{{t|z\[[dc\:97&&UTSd\\d\\u{{ztl|
+¤{{t¤¦|z|
+mttsle£¥{{tlldsletts£¥ª³·{ttekd
+ekdsrelrif]c{{mttsle{zmzll||¦§¨lddlektlledkult{{t\[[|
+£¥f]cttslddtslkd\sleSKJ\[[leklldtts{u{tll{{t}ztlrfkttssleVTLtllsleztf{u{uzt}f]csredc\}sre{u{{zm{||£}|lldkd\{tttlld\\sre{{t¤||ttstll{u{mtt{tt{{{{{tt{{f]c~£¥tts£tts
+}|tsllri
+¦§¨»ÂÇ²¬µtsltsl¢}|ult|u{u{{{t{u{tts}{{llk|||z{{|
+mtt\[[|
+|
+mttf]cd\\|z|ut
+
+tllmtttll|¢
+¤mtt¤¨©´ztl{tt¡u{{¤¦tts}¦§¨|lrilektts}|{||{tt{{t|uuztutv{lks
+{||{{JHF£:97*)([[TSKJJHF\[[lri{||tsl{ttlri|z}u{{¤kd\£
+v¢|z¤¦¦§¨¦§¨¦§¨f]cf]cVTLek]kk]ultd\\VTL}{||f]ctt{edklddedkuztVTLmtt
+ldd||kd\lddzlllks|||
+{||{u{||lddtlld\\u{{|f]c[TTtll|||u{zmj]\zllj]\{{ttll{{tSKJ
+¤¤|z}|ldd}{ttuldd|z
+{{{tt{{t{{sle{||uzttts{u{||{{{tt{u{tsl£¥tslllktt{lek|
+¢v¨©´ª³·
+¤¦tt{v{²¬µ¤¦}||}
+¤|{||£
+££{{¢¦§¨|{ttv{}zllmtt¤|
+JHFlldlks{ttsleldd¤
+¤¤¦dc\
+}tts{u{lld
+¦§¨llk{||tts|zlek{{ult|uztlv{|utzl|vtlluztttsllklld{{tSKJ*)(lkslldVTLUTSsref]ctllbVZtzllldmtt|z{{t||zlld¢¦§¨{||\[[}{||
+tll|z¢ultlld{||mtt£dc\MSS
+
+{{}lriztlsrezllttslddztl{||llkf]cllkultVTLsre{zmzll|f]ctsl{||{u{dc\SKJultlldnf]c{||}v}ult{|||tts{zm{tt{||{tt{tt
+tsl}£|kd\sleulttll|£{{t}ut
+llkllkttsllk¤{u{ddc
+|u||¦§¨¤¦|z{{{u{}|z¦§¨¢«²«¤}]cd|
+uztkd\{tttsl{tt|lek¦§¨{tt¤¤£¥}tzl|tll}|
+redUMRtt{
+UTS
+
+}}}|¦§¨µ¶·tll¢
+lri{u{¨©´
+u{{tt{¤uzt¤tts¦§¨|tslv||}kk]|
+ldd¦§¨{u{{||²««JHF3+*||
+UTSdc\}|ut[TT{||lkstsl|z||z|z}lri{{|z{||||ekd
+rfkkd\utts||¢ª³·mtt>B9JHFlks|tsl\UZ{{
+\UZfkkVTLult|u¦§¨
+d\\\[[ultek]llkbVUj]\tzlztlslekd\ult¦§¨}ldd{tt{u{tt{b[USKJiWU{u{{zmVTLrg]sreedk||{tttts}|zlltll||rg]ztl||ztlbVUlddu{{}kd\lldtsltllsle{{t{ttllkedk{ttttslldedk{u{tt{llklks|
+sre}¦§¨ÂÅÓ¦§¨
+¤¦|z¦§¨u¢¤¦¤£{u{{{v{lrif]cdc\¤¦|uwsretts{tt£¥ultvtllult|z{{t¤¦v{ldd{tt{||¤¦
+
+{{¢lkslek|u
+
+{{{{t¦§¨}¦§¨¤
+{{tult|zllktslmtt£¥|
+llklddlek{{{{t|v{¨©´¦§¨||vkd\redulttsldc\sle}lekJHF
+{{tlldkd\UMRUTSlksSKJUTS]bZ||lritslkk]tslllk{tt{||||}|ut|z¦§¨v¤¦|z|ztsl
+llkj]\|z£¥{u{tt{\[[|zllduztkk]||tt{lek{u{dc\f]cuzt|ucbVu{{tzlddc|dc\sle|VTLb[Ulri{zmvek]lldsle{||llkd\\JHFttsb[UbVUztl{zmtzl}SKJ]bZfkk|ztll[[Ttslult}|}llkyle|u
+tll||v{ztld\\{||yletlllriwlj]\uztldduztult{{{u{{{lekmttddc¤{||¦§¨{||··Ä¨©´¤¦|z¤u{{ª³·¨©´ª³·¦§¨tsl¤¤¤||¦§¨tsl}tll£¥£}tts{{t||[[T{|||ztll}¤¦mtt|
+fkk£¥v{|ztlllri£¥lddw|
+{{u{{¨©´lrillk{{tlksylelks{{tsl|lksv{{{}ztlztlbVZ}¤ztld\\}{u{}srelekedk£JHF:97llklldj]\lek[[Ttslldd{||lekdc\dc\{ttb[Ulkstsl|u}}|{{¤¦sle{u{tts}lld}lddmtt|
+mtttll{{¨©´slef]cJHFlks|
+b[UJHF{{tD;9u{{|tts{||b[U]bZ[TT||dc\||ttstsllldllkztl{{lekbVZf]c||v{}|||ztfrg]VTLd\\lldllkttsf]cu|z|u}lld|utll}zllrg]j]\{{td\\|zztltt{uztv{lldlldmtt
+}{u{|
+mttllk\[[{{|z£²|
+§²¢£¥{{ª³·lks¤£||{{t¨©´¨©´¦§¨¦§¨uzt¦§¨{u{||ultddcslerfk{u{{tt¤¦{{ttzl]bZmttlri{tt{tt\[[mtt{{}tt{fkk{{t}ztluzt{{
+
+uedk}¨©´{u{lriultn|
+{{lriut{{¦§¨£¥fkk|u{tttzl£{{tv{{u{tsllddcbVSKJlddf]c£JHF*)(\[[[TTSKJdc\}[TT{{tlddSKJtsliq]b[U{{tek]slelldlrittsultlld]bZddc£ttsf]cttsu{{ultUMR|ulddult}|z{ttyfl{|||utsltt{edkSKJlksuzt{{tJHFtll\[[kk]¢||lld}{zm{ttddcb[U{||zl{||b[Ud\\VTLf]c\[[b[UUMRj]\|u{tt
+|uredsre|
+{||uztkd\kd\¤}{{t|tsl{u{
+lritlllld{ttzllyle|tslttslldekd{{yl]cdultuztult{{{||tt{¦§¨
+uzt
+¦§¨¨©´¤¦lrimtt
+|
+|
+£¥¨©´¤¤¤¦¦§¨··Ä
+}{{{u{{{|
+µ¶·}{tt}||}{tt}
+
+|z¤¦mttddctzl{{ultf]c||UUYldd¤¦|
+
+rfk
+mttf]cd\\edk£{u{||||lldµ¶·¤|u£¥mttf]c
+
+}²¬µttslri||llk|ttsred{{t}{{t|tll\[[{{tkd\ek]fkk¢FD;3+*VTLb[Ulrisreldd||[TTJHFd\\\[[||sre{zm|ztlutztlztllld
+ult|
+uzt{u{uztult||tt{llklektlld\\[TT\[[[[TbVUztlb[Uttsf]cf]c{||}[[TVZT|z
+tzl|z{tt{u{{zmrg]ztfkd\dc\{{tultlrikk][TTtts|dc\ek]\[[mwiWUzlltsllldldd|
+lri|
+tslut}|£srekk]kd\ekdv{bVZdc\}tygb[U||redlldlekult|ztts{{t{{t}{{{{]cd{{tt{{||¤|z{{¢tt{
+£¥
+{{ª³·
+}|¨©´
+¤{||edkUUY{{¦§¨tt{ult¦§¨£¥¤¤uztult£¥
+{||{{tldd}{{tred
+ztl
+tsltts{tt{u{}tslu{{lksmtt}]cdttsut{{|z£rfk
+|u¤¤¤¤tt{{u{lks
+££¥ttstllulttts
+f]czllri{u{uttts|
+]cd{u{{{tllkSKJ*)(|zd\\\UZ[[TJHFultddc|zsleut|zv{ultlldzll|zkd\¤{{tv{}
+kk]f]czll¦§¨ddcnult
+¢ult£¥tt{kd\{{f]cult\[b{||\[[llk¤¦tt{dkV]bZ{u{|zslesleztl
+ekdlri{||[TT{zmslewl}}|{||wl||dc\~wl}n}kk]¢tsllriv
+|ztsl}}ztlcbV|zd\\utult}edk{{ttlltslb[Utlltll||mtt{{tuztkk]lld{{tlks{{}
+{{{{tt{||¤¤¨©´¤
+¨©´¨©´¦§¨¢
+tll¤£¥¦§¨£¥¦§¨{{t{{«²«mtt|¨©´{{}¤ztl{u{£¥¦§¨µ¶·£}ttstsl{tt||
+|z{||ztlultnv{||lri[[T{||{{f]c[[T{{t²¬µlritsltt{|u}¢
+¤|z¤{{||{||{||sle{u{{u{j]\j]\¨©´v{{{t¤¤}tll|uztuzt{||D;9*)(f]cVTLlriu{{sre{u{ztlVTLttsddc[TTuztlritzl£¥uztlriult|z{tt¦§¨{{t{||d\\llklri|ttsv{{tt
+||ultult}uztJHF[[Tutlritlldc\tt{]bZkd\tsl{u{redslelddtsl}sle\[[{{tbVU{{tztf
+rfklddsre~r]g{|||{u{lri¢|
+lek[TTb[Utsl[[Tsle
+dc\tllrg]|z|u{tt{u{kd\{zm[TT||ztltt{uztlri}tt{}
+{{
+|
+|
+edk£¤¦{{{{|
+
+¤¦
+¦§¨¨©´}£¥·¶Ñ¤¦}tzl{{lks{u{}¦§¨tts{u{llkv{µ¶·¦§¨{u{tll{u{tll|{ttultllkttsu{{¦§¨¨©´|
+{u{lks~edklks{{lksb[Uyle|¦§¨{ttut|||zª³·
+tt{|
+¤tlltts{{ttsl
+u}}|
+|{tt||tts{||{tttslfkkMRK*)(leksre]bZ{ttlddkd\d\\UTSUMR{{tuztmttdc\{zmvtllldd|
+SKJu{{|
+|
+|uª³·u¤¦§¨kk]\[blksedkldd
+bVU{tt{zm{{{u{{u{tll|tzl|
+[[TbVUlri£FD;ttsredkd\b[Ud\\{zmVTL¢|[TTllk||{||b[U{tt}|sle||kd\lldn{{tlld{|||
+}lri|ttsb[Uek]ztlrg]uztf[TTttsvzllkd\llkuztddc|u{tttt{tsl¤¤¤
+|
+ttsfkk}{u{{{{{}|
+|
+
+}mtt|
+¨©´tts··Ä¤
+¢¨©´ttsrfk£¥£{u{zll{||wl¤¦|zuztlkslri|zttsf]clekekd|z¤|
+lkslriultlksdc\tsl|
+}UUY{{}kd\¦§¨sleult{{t{{||{u{{{¤{||f]crfk}|lriztl¢tt{~|ddc}||{u{ttsultddc{ttultsre\[[||JHF*)(llklldkd\llduddcd\\UTS{u{ddcttszllddc{zmtll{||tts|u¤¦}lkssretsllrij]\j]\¤¤{||lek}}{||[[Tf]c|zzllkd\ttstsllri>EC|z{u{uztztl}{{t{{tslebVZu{{ldd{{tlld|zlriVTL£¥VTLultkd\||j]\||]cdv{VTLdc\dc\tzl{ttuzt
+yle{{tllkut||}llktsltllztl{{tek]sle|ut}ldd|lld}{||mtt{{{{lks
+|
+tt{{||{{¤|
+}}|z
+tts¤¤¦lksnvmtt|z{{¤}|}mttztlult{u{|¨©´||{{t||llkddctts|v{lks{u{{{t{u{{{
+ultlksUMR¤|
+lri|z]bZUMRd\\b[Ullk|z{zm}ldd}|{tt£¥¢sre¦§¨v{£||llkd\\{ttsre|}{{kd\ldd¢|||v}|ddc\[[d\\[TT\UZ[[T}¤¤74,74,lddVTLb[Uuztdc\ddc{u{u{{dc\d\\tsl]bZddcredlritllsle|ekd¤|lekª³·lek²²¬ultu{{b[U¦§¨tlllri{{tt{SKJUTS{u{{tttsllldtt{ylttsztltll|kk]\[[ddc}¦§¨}ulttts}|zj]\|uztlu{{tll|ttsd\\fkk{ttult{|||{zm|
+lksdc\}|ztf{u{¦§¨ttsutult[TTek]||ztl{ttkd\ztl{tt{zm|uultldduzt{{|{{tuztllk
+ultf]c|
+nvfkk{||£{{£¥¤¦u{{
+|
+|
+|
+}tts¤||{{£mtt¤¤dc\{{|{tt¤¤µ¶·ult¨©´£¥zlltllllkttsu{{ekd}tzl}lldtts
+f]crfk\UZd\\\UZ
+|ztsluzt]cd|
+lks[[T{u{¦§¨µ¶·|uzt²²¬{tttts{||{tt}¦§¨{u{bVU|v{||¤|uult¦§¨}|z
+ult{||}kd\|u|
+lrif]c|
+tt{²««JHF3+*bVZllkj]\tll]cdlld]cdult{{tUTS[[TlriVTL|ulksd\\j]\tts¤¦¢¤lddlddldd
+utd\\uztttsedk
+lek{u{|v{|
+{{tslellkVZTlri|zzlddc¤ttstll|
+u{{
+sreb[U{tt}sled\\tts{ttldd\[bldd{zmtt{v¤tzlf]cdc\lri|ukk]{yfd\\llkf]c{{t}tlltll{u{
+
+utj]\zll|
+sle{{tv{{{tsl{{¨©´£¨©´¤ª³·|
+¤¦|
+|z£¦§¨
+£¥¤||lks¤§²{||red}{ttult··Ä|lddtt{sleuzt|fkk}
+}lld{||{{
+{u{MSSf]cUTSf]cmtt{{|¤u{{edkedktsl||}}wl{||ult}bVU[[T}tts]bZ}|{||v{{tt¦§¨«²«tsl¨©´
+{tt[[Ttsl}|slev||ultuztuzt|tllUUYddc\[[£:97&&red{zmJHFVTLMRKu\[[[TTVTLJHFVTLtslsle[TTllddc\i\Vtslttslri¤¦£\[bddc||ult{tt|||}¤{{lksSKJedk{{}lldsle]cdbVZUTSVTLdkVfkkFD;aWM]bZVTLSKJ||uztlrilddldd}tts{ttddctll||redf]c}zlld\\tzl{ttuztdkVVTL}JHFredf]cult{||tll{u{
+lek{tt{|||utll||ldd|z}ttsut{ttf]c|u{|||z}||
+v{¤
+
+
+}lks{u{¤¤|
+²¦§¨
+tt{¤¦}ª³·
+{||¤¦²²¤¦¢¨©´£«²«
+
+{{v{ult«²«¤¦¤|¨©´£¥rfk£¥}
+|u{||{{}{tt{{£¥¢¤¦¨©´|
+|zd\\{{]bZ}lld}¤¦|{{JHFulttt{
+tzl{||{tt¦§¨
+||
+lldldd|
+|||z¤sre|{yff]c|
+}{{lriVTLek]}llkcbVldd[[Ttlledk\[buztztl[TTUTSedk:97&&\[[SKJVTLzlVZTek]FD;ultd\\|zlldsresle
+kd\jcV|llklld\[[}uzt
+
+ª³·£{tttsl{||tllf]ctlllldut\[[ultSKJ{{{zm[[TVZTlddJHFu{{lddVTLtlllldd\\tsltslv{ztllrillkttsj]\lriUTSb[Uldd}ldd}ultzllf]ckd\lritzluztwllddtts|utreddc\uttts{{||}wl{{t{{tddctlllri}redddc{{tztltsluzt|
+u{{}
+{{{{
+¤u{{{{
+£{{{{
+¨©´¤
+¤£¤edk¤¦¢¦§¨¤¢¦§¨~£¥µ¶·¨©´¦§¨¦§¨¤
+|
+||tt{
+
+lrimttekd{u{rfklks\[buztu{{
+f]c[TT}ult¤¦
+{|||zttsult}|zb[Utts£¥{||{tt}}|u|z«²«ldd\[[|u]bZkk]sle}ldd{||{{t{tt|
+|ztlllek{||JHF£JHF3+*edkek]lldb[Udc\lld\UZVTLVTL[TTlddlld{{ttllldd|}yle¤¤{||{{t|
+{u{¢{u{{{¢fkkr]Z{{s_q
+rfklek¤llduztv{uldd|MRK]bZVZ[llklldutekdddcztl]bZUMRztfdc\}JHF\[[f]c|}{||j]\tllkd\d\\
+||{ttttslks|¤¦}£¥}|lldllkultlddlld{ttv{rg]
+{tt{ttlldf]c{{ttllllklddred|{{t¢¤¤¤¦¤u{{
+
+
+¤¤¦£mtt¤
+{{lks²§²§²¤¦£²{{{||lrisre
+u{{
+|
+|z|z
+ult¤¦ª³·tts¤}}}u{{ztl{{tttsj]\uzt|ubVZmttVZ[|z
+tts{{|uf]c
+tllekdUTSlks~[[T{{tlks{{t¦§¨¦§¨tll|£
+lddtt{£²}ult
+edktt{{{t|u||
+{||lldlksultb[Ulld{{t[[Trfkult
+|lldekd[TTtslddc²²¬FD;*)(ultddcSKJD;9JHFcbVf]cSKJ[TTldd\[[tsl[[Trfk}|lld{zmuzt{{tlri{tt\[[{{f]c«²«
+{||}ult}bVZbVU
+{{t¢¡ult]bZultldd[[Tlddlld[TT|ub[Ulld|u{ttek]ddcddcVTLSKJFD;kk]ult{{tddcuztVTLtllbVZ{||[TTtslldd¦§¨lritll}|{{t||bVUttsredredzll{{t|z{{tztl|
+|zut¤¦kd\
+ztledk|z
+llduzt|
+{{}¨©´¤¦¤²¤¦¤}}|{{{{£¤¦|
+
+f]ctt{ult
+{||¨©´«²«
+mtt~
+{{}¤¦|
+}||
+{tt{{d\\{||f]cv{r]g{{wl{|||z]cd|z|z{{|z{||f]c¤tsl||
+lld~£¥||{{lld
+||}||tsl¤lddrfk}ldd
+{u{|
+tt{||«²«lri}¤{||{||d\\kd\tsl\UZlddultu{{uzt|z
+
+}|f]cVZT\UZ¦§¨UMR
+lddVTLFD;FD;[[Tut[TTfkk}[TT[[Tlek[[TztfVTLcbVdc\tslfkk|zmttek]
+||tzl{{ttts¤¤
+tt{ddc}
+¦§¨VTL\UZ|
+ª³·lriedkdc\|zztlttstllekdSKJttskk]|uztlldSKJ|utsltlld\\f]ckjV|SKJb[Uztluztulttsl
+|zsle{tt}lks[[Tkd\red|kk]u{{
+lddllk{{sledc\f]c}ulttllztl||llk{||{{}mtt¤}|{{¤
+nv£}ult{{¤²}|{{}|
+¤|
+¦§¨
+£|
+tzl|
+|zult||¦§¨lks{tt
+{||ow|
+{ttsle|
+ult¦§¨redekd
+¤¦|z]cd|
+mtttslmttedkuztcbV\[[§²|
+¤||f]c}|¤¦v{[TT{{tll}{{d\\}}{{t{||ddcddc
+rfktsluztddcult¦§¨llkdc\|uUMR}tsl{||tsld\\ttsddcu{{{u{{ttlekVZTddc²««D;9*)(dc\VTLFD;D;9ek]kk]bVUult{{tlksd\\lrilriVTLlks|uj]\cbVlldVZTuztMRKu{{{ttlri¤¦u{{u{ttmtt²²¬tts|mttf]c¤tslult}|ulttts]bZ{ttultztl{{tztl]bZ{zmlri\UZ}{u{}|d\\uzt}|}|sre}f]cv{{tlddSKJddcvek]VTL[TTdc\llkddc\[b||tsllldredUTSlldkd\redVTL{||[[TFD;llklddtsltsl{{f]cfkktsl||llkultlrifkkmtt|
+|
+{{
+§²¡¡mk
+}|£{{lks{tt
+|
+¨©´
+¤£¨©´¦§¨|zlri|
+{u{}{{t||z¤]cdlks
+}{tt¤
+lek
+ª³·¤¤{{{u{¢mtt¤{||VTL|z]bZtslultdc\¤¤|
+
+v{{ult¦§¨{u{||tsllek¦§¨}{u{{tt}{u{slev{f]c{{t}||lriztledk{{|
+¤¦§¨sle
+{u{d\\{||mtttslultdc\|z{{kd\ldd\[[tt{\[[¦§¨SKJ&&j]\}f]cVTLJHF]bZzlltll]bZllklldtzlsleuztultVTLtll]bZ[[Tu{{tzlllk|z|z{{td\\²²¬{||ekdlld{{f]cedklldbVUlddult[[Ttt{SKJ{ttlddu{{lriUTSdc\rfk|tsl{{ttslzll|z||{ttttslldddcMRKf]clkstsl
+ekd|
+{{ldddc\{u{FD;Q?@ult}dc\||z{{t~mttlldult}|z{zmf]cuzt}{||UTSylerfk{ttdc\sle{||VTLtzlbVUlddllkdc\ldd||ztfllkldd}u{{mtttt{uzt
+nvedklkstt{¨©´¤¦²§²¨©´lks}}|
+u{{¦§¨£¥¤¤£¥|
+|
+¤¦¢{{u{{ultylttsµ¶·\[[lkstsl
+llklri
+{{{||{{¦§¨£¥ldd|zlks}mttlrirfk\UZd\\\[b{{tslmttlkslks{tt{tt|
+¦§¨¤¦}||¤£{||
+{{ultult{{|z|z¤{{t{{|||z||{||¤¦}{{tddc{tt{{kd\lri|lld{ttttsztlfkk]cdllkbVU-1+ldd{{tF=CsletllSKJ{zmzllldd\UZslelldddcd\\r]Z}}|
+JHF{zmfkku{{}lriuzt}|tt{kd\{||VZTlksllk¢[TT|uzt}lddtlllriUUYVZTVZTUTS{{tslettskd\VTLkd\tsl
+[[T\UZ|vkd\|{{tsle||SKJf]csre{tt{{ult|rg]}lddtslbVUlriv{d\\UTSslekk]||{{t}|{ttttsek]{||ztlttslddjV[\[[\UZ{ttult|{{{||fkk£²
+{{nv{||u{{{{£¤¦}£{{{{yl{{
+¤¤tts~§²ª³·¤£tzl¢lldª³·ª³·lrimtt¤tll¦§¨ztl}zll|¤{{bVZ|
+{tt{{[[Ttll
+|z[[Ttts|z]cduzt{{t{{UMR|
+d\\{zm}
+|sleldd¦§¨}¦§¨{u{{u{
+}|zddc{||{{ult|zkd\red}|tzlsle[[T|z]bZb[U[TT\[[UTSf]c¦§¨FD;*)(f]c|uSKJ]bZlddJHFddclldddc\[[~tzlekd{||ulttzlu{{llklldtt{ekd¢lkszlltt{uztu}|tsltllVTL{ttztl
+uztVTLlri|{tt]bZJHFb[U]cd]bZmtt{tt{zm[[Tlld{u{sreult{||]bZttslld[TTcbVVTLb[U[TT{zmi\VbVZtll}sletlledkUMRek]kk]VTLlddUTSutultkd\{||cbV{tt|ztllbVZuzttsl{|||lldvtsllksbVZ{||ulttll{{ultmttfkk¤£{{lks¡mtt
+
+
+£|
+
+
+~ekd}
+£¤¢||ª³·ª³·{{
+¤{{¦§¨ldd£¥{{¤}|zztl{u{{||
+{{utf]c¤lriUUYmttUTSdc\]cdtts{{ekdleklekttstzlwl~lks§²|
+£¥{{tsl{{¤¦§¨~u{{}}||u{||tt{fkk}|ultlri{{t|u}}||
+ztltslVTL{ttultfkkUTS¦§¨MRK*)({tti\Vkd\FD;bVUPF=dc\UMRdc\sle}tsl{u{ttstll¢jcV|utyg|u{{d\\mttekd}}|
+}uzt|
+|zb[Uddctll}}\[[
+{zmj]\[TTtlltts
+u{{lrillktllztld\\v{|
+ztlVTLttstzl{{{||[[Tb[U{{t}\[[VTLJHFlddiq]d\\VTLlld]bZSKJJHF||||f]c}}ddcd\\tll|ulld£{u{|mtttsl{||mtt|mwtts[TTtll|z|ddcMSSlek¤lks|
+}
+|
+{{¤
+¨©´{{£nv
+£²{u{{{¦§¨}|z¤¦¤¦»ÂÇlks\[b{tt]bZult{{t¤¦}ttsult¤¦{||¦§¨ª³·£¥{{{{tJHF\[[LKRMRKVTL\[bJHFu{{u{{red£¥~|ztts¦§¨¨©´²««v||ª³·ttstt{
+
+ult}¤||ekd
+ddcedkldd{zmmttultdc\|llk{{sledc\{tt]bZ]bZVZT£b[U*)(f]ckk]}|FD;UMR{tt[[TVTLSKJVTLj]\VTL{u{||tlllldkk]ztltslmtt\UZ{u{¤{{«²«¢{||{{tutekdbVZUMR¤{u{{|||ulek
+{{uzt{{tekdJHFUMRldd|z|vf]c{||ztl{ttVZ[~{{ttll{tt[[Tkd\}FD;VZTd\\lddb[UtlllldlddJHFultekdudc\tsl||dc\¦§¨{{tkk]{tt|
+ultredtt{|ztsl{{tzllLKRmtt}bVU{{lriuztmtt{{tt{}|{||{{|
+
+£¤{{|
+
+§²·¶Ñ¨©´{{¤¦¤¦|
+}¦§¨¤¦¦§¨¨©´£¢¤|zfkkf]clks£zllv¬¶Ãlldred|||¦§¨lld|
+{tt{u{{||uzt|z{tttt{JHF~}
+zlluztlriVZTlrillk}|llk{u{|uztl}ult|¤¦§¨¦§¨
+¤}f]clld}{{ldd|
+llktts
+ekd£¥vtll||{ttleksletll||JHF{||zllkd\JHFUTSlekutfkk\[[ddc}JHFSKJbVZkk]b[UPF=3+*FD;[TTD;9JHFlddtsldc\{ttdc\ut{u{{|||¤¤|ttslddddcult[TT|
+¤¬¶Ã¨©´¤¦~iq]tllb[UddcUUYf]c{tt|zddc{u{dc\v{tslultrg]|zekd[TTlks
+{||lek||b[U[[TUTS{ttrfksreslej]\ttsUUYuzttllVTLleksreutwl\[b|ddcultlld||\[[{{£¥{{t{{tlksredult£{||tllmttrg]ttstt{{u{ult{u{
+{{
+
+£u{{{{£
+
+¤£»ÂÇ¤¤¦
+¤¦§¨¤¦§¨¤¢tzl¢u{{ylMSSuzt{{t}}}¤tts¤¢|
+|z\[bu{{{{t£|
+[TTmtt\[[{{UTSult¤|zlddllk{{llk|uv{ttstt{ultztlv{ª³·¦§¨
+¢|
+\UZ}rfkldd||llkmtt}mttu{{ulttts|v{{zllSKJd\\lriu{{ek]|zsleztl[TTVZTllk¦§¨:97*)(u{{SKJJHFSKJ3+*SKJD;9F=Cf]crfkVTL|{tt~ddcsrejcVlldlldedk[TTmttu
+lriek]lri«²«|ztl{tt}|u{{[TTd\\VTL{{tultu{{u{{ttsfkkUMRb[Ulld{tt\UZ}VTLv{ult||redlksi\V[[Ttyglddult|uuf]c|ztlltslVZ[tzl[[T{u{ult|u¦§¨|tts£¥£¥{{t{u{VTLlri{u{
+ddcultkd\u{{¤
+
+mtt{{|
+|
+{{¤§²
+|
+¨©´¤¤{{t}~|
+ª³·¤¦¤¦\[[tt{{||}|¤ddc}¢}¤}UTSVTLb[Ulriuzttt{lri[TTultultult{{¤tlllrilks|zlksutf]c{{ult}tts{||{tt~||v{£tzllkssreUTSddcnVZ[lks||ldd|||uzt{{{u{
+}{||sle[TT\[b]bZsletslVTLekdztlu
+[TTu{{llk²««UMR*)(\[[rg]bVUVTLVTLkd\tts|rfk~tzl|||[TTtt{kd\VTL{{tsl|uf]c[[T{{ttsmttek]{{tuztlriVTLlekttsslettsuztkk]r]Z¦§¨}|kd\f]cJHFddcfkkf]cUMR{u{lldult[TT[TTrfk{{td\\|ult¨©´lks|u|
+tlllldkd\{u{|zut
+tslb[Uddctsluzt|u}v{{tllttsª³·{||ttsutzll}{{ldd{u{}llk|u|
+£¤¦¤}{{{{}|
+mtt
+}¤|
+¤ddcttsult¦§¨
+|z|£¥¤lkslks{{u
+uzttll
+mtt\[bmttmtttt{ultlks[TTuztVTLddcfkk{tt~¤lddyl{{ttslri{{|
+¤¦ztlult|z}|£¥{{t{u{{u{tts{||lritt{ddcu{{\UZtsl{tt}ult}¨©´}{tt{{tt{
+llk{||ddcf]crfk||}|tslbVUf]c|u\UZ{zm|tts[[Ttsld\\|
+{||¤¤MRK:97{ttdc\D;9SKJVTLVTLf]c\UZbVZv{uzt{||slekd\ekdlkstzl}uztlrifkk||tts||\[[ekdtll\[[\[[mttv{ttVTLdc\rfklddtll{u{|
+tts|UTS{{tv{¤¤tllbVUVTL\[bttsult\[bllk}{{ttllddc|UTS|zVTL|zultrfkult¦§¨}¦§¨i\V|
+{{ttt{utlriztllriu{{ldd¤¦lj|
+{||{tt{u{}}ldd}{{t
+}|uttskd\tts}tts|zlks
+{{|z|edklri|
+
+|
+
+}|
+£|
+¤¦¬¶Ã¦§¨
+¦§¨§²§²µ¶·¦§¨¤¦¤}£¥¢lriultttsd\\{||¤¦¤¤f]c|
+tt{¨©´}¤¦u{{
+¤¦lks|
+mttlld[TTekd|
+||{{{{tekd£
+ek]ddckd\ult{u{ttsldd¦§¨|tlllek|zuzt|
+sre{u{[TTtslultult{{t|||z}tt{lksmtt{{{{llk{{ttstsl{{t}rfkVTLtllVTL]bZ{||||tllf]c[[TddcMSS*)(tslb[U[[TaWMJHFSKJuztVTL[TTultddcdc\{zmlldcbVUTScbV}|\UZ{ttult¤¦}u{{tll|
+ttsztl{{tdc\tt{{tt{{tekd\[[srekd\||v{u{r]g|zddclkslldyld\\ttstlltll[[T[[T}|{ttlri|zVTLrfk
+tllsreldd{ttUTSkd\
+UTS]bZ¢u{{uzttlllld{{sle\[[|uztf]c|
+ttsddclek|
+{u{ttsttskd\edklld{||{{\[b|
+
+
+{{tt{£¤¦²{{{{££¤lks§²
+£¥¢}
+
+¦§¨¤\UZ]cdldd|z|tt{
+¦§¨||¤²¦§¨lriedk\UZttsttsmtt]bZlri|u{{\[[|zkd\lddu||SKJtt{u{{ult£¥ulttt{|¦§¨¦§¨¤¤{|||
+ult]bZ}UUY]cdldd{{{{t|z
+lek
+{{|
+lks|zuztulttt{tts}ut||dc\|urfkv{{||{tt|z]bZUTSsle[TTllkUTStt{£LKRD;9lldkd\[TTVTLPF=VTLVTLf]cultf]cddc{{tdc\{u{kd\lrilldtslkd\VZTred{u{«²«uztu{{|lddldd{tt
+]bZMSSlddkd\|{u{
+lks|zdc\}ldd}}lriUUY|z{{:97lksult|zult{{td\\mtt{{tllkrfk[[Tdc\}|}|{||u{{tsle|
+|
+lek¢¤¦¦§¨||}tll{{t|z|u{{tlld|zuztldd}¨©´lks|
+]bZUTS{u{{||tts{||mtt\[b|
+
+
+|
+
+££¤¬¶Ã¤|
+~|
+{u{{{£¨©´|
+¤¤¨©´|
+¤u{{
+ekd|
+¤¦tllmttd\\lks£²rfk¤¦}
+{{rfku{{llkekdldd¦§¨ztltt{ekd{{t}|tll|z|zmttrfk||
+fkk{||ddcultult¤rfk¤{{}{{}[[T
+{u{u{||edktzlult{tt|
+{{tts{{u{{|
+lld}|{{tddc|uJHFJHFlddttsult{{tlritsl[TTllkdc\ddcFD;:97UTS]bZd\\VTLSKJrg]lriyle{{tekdlrilldkk]]bZedktsluzt{||edk}{u{|{tttsl|lld
+{tt|mtt{{t{||[[Ttts\[[|z£{{\[[ekdUTSf]cUTS|
+v[[Tlks{ttlks[[T}SKJr]gSKJUMRkd\}b[UultekdllkaWM}||¢
+{{}¨©´¤¦¦§¨{u{zlluzt}|zlddtsllddlek||{ttuzt||uztllktt{|z{{
+{{tmtt|
+§²§²lks|
+§²¤··Äª³·
+{{
+{{{{¡tts{{~
+¦§¨··Ä\[[tllf]cekd|
+|
+¤
+}u{{tt{{u{{{tts{u{lrittstt{mtt{{mtt¤lekrfku{{\[[|ztldc\lldkd\|lldu{{d\\||ult{{tllF=C}
+
+}z~}{tt
+|}{{llk|zuzt{u{¤¦|
+
+mtt
+|
+}llk{{¤¦¤
+
+|rg]VTLFD;[TTUTSekdlddztlllkllkdc\[[TUMRztlUTS:97:97sreb[UlddSKJsreD;9lddSKJldd{||lldsrezllf]csleutuultlld{tt||]bZlri||tsl|
+ut[[T[[T[[Ttsltsl¤{{tldd}ttstts~uzt|
+MSS\[[[TT]bZ[TTi\V|{u{{{t||{ttsrej]\leklddcbVrg]{{t{tttlltyg|uttslldmttdc\UTS¢²²¬
+£¥¤¦f]cut|z{tt|u{||{||ddcultedk{{|zlks|
+}¤¦|
+¤|
+|
+
+§²^fs
+·¶Ñ
+§²{{{{{{¢¤£¨©´|ult}¤tsllks
+u{{mttmttlksddc{||}mttlks
+¤lrimtt}|lritsllri|{{tsre¦§¨{{tredlld]bZ\[bUMR{{{{redv{¤}{u{
+||uzt¤tsl|
+]bZ||
+tll¨©´¤tt{mttv{uzt}¢lksmttuztekd
+llktlltzlek][[Tlldslettsv{|ddcekdtslztlultdc\,55||FD;74,{{tlrif]c{zmlriFD;\[[VTL{|||zsle|zttsjV[tslrg]tslslej]\sle||lekllk{{ttzlllddc\|
+{||ek]b[U{ttlrivlri\[[¦§¨ekd
+uzt|utt{{{lri|
+kd\UTS\UZdc\[TTlldbVU{{t\[[lldVZTultyle}cbVkk]lri{zmzll[TTsreztlf]c]bZ|
+UTSlri]bZztl{||«²«tsl||d\\{ttmtt{u{
+tt{}]cdtts{{lks||}{tt¤¡
+}|
+}£{{|
+}¨©´¤£²}
+­À¶¤¦¤¤µ¶·{{|zultmttttsuzt}edk|zmttUTS\[b]bZdc\tsl{{nv]cd£
+d\\\[[|z{u{tllj]\|
+£ldddc\|
+mtt|z}v{£¥lks¤}v{{wltt{ylv{}ut}¤¦¤¤llktll
+ulttt{
+~tzl}¤|
+}nv§²ddcmttlksd\\lrilddd\\ekd{tt{{tddc{||}{tttzltts{zmj]\\UZUTSUTSJHF74,lridkVSKJVTLJHFbVZVTLbVUtllu{{d\\srelksztlkk]tslztlddclri{tt||ztlfkk{||tzl}]bZmtt{u{llk|zFD;MSSlrilri]bZ{{tlllkslddllkddctll\[bultuzt\[b}tsl}lks]bZUMR||b[Uult£rg]LKR{ttkk]UTSlddVTL[TTUMRlriu{u{lld
+{||{ttª³·¤|
+kd\tzl
+
+\[bek]tt{{{u{{¤|
+mtt£
+¬¶Ã¤££
+¤}£ª³·}¤¤¤ª³·{{|z£¥
+ulttt{tt{UTSultlksu{{}|
+lksekd]bZ]bZtsl}|
+mk
+\[b\[[kk]|zultztl
+tlllri|zddcultttsek]]cdMRK}UMRv{¤¦~{{ult£²v{llk£¥¦§¨¦§¨|zmttmttf]c|
+ek]\[bultllktts£¥|
+{{
+}{{lksVZTJHF{ttultUTSu{{tlllld{{tedk||sletsl{||kk]SKJSKJaWM|
+ekd*)(kd\kk]bVUVTL:97D;9\UZbVUllk]bZtsl}f]ckd\mttcbVldd\[[ztlztllldmttcbV|dc\b[Ulld|
+]bZ]cdekdJHFu{{MRKVZ[llkkd\edk{||{{|
+lddldd{{lks|zllk
+tslztlutUMRjcVj]\lddbVZ{|||z|uf]crfkrg]\[[ldddc\{||mtt|z{{t[TT\[[\[btsltts|||{||lek|¤red¦§¨lld£mttu{{uzt{u{{{lkstsl}{{u{{{{fkkmttu{{|
+mttmtt}~§²£²{||~~µ¶·{u{|
+nv{u{|
+{|||
+¨©´u{{²¬µ£¥|
+ttsult{u{mtt}|mttfkk|
+mtt|z|
+ult¤¦mtt
+leklldllk{||VTL}UTS[TTlldVTL{||utJHFtllJHFtslkd\¦§¨lks¦§¨¢tslu}JHFleksle¤}
+
+¨©´ttsuztlri\[blksu{{tsl\[b}f]c||~tt{{||£|
+tts{tt{||mtt|
+uztlldf]clrilld{{tztl]cd\[[redVTL[[T|zrg]FD;[[Tdc\SKJ:97*)(UTSVTLaWMVTLSKJJHFf]ckk]llkSKJlrikd\zllrfkd\\lrilriVTL}yle|ubVUmtt{zm{{tkd\tts{{t{tt||z||lddlrilksekdmtttzlult||{{lrimtt
+}tt{|zredrg]lrifkk{{tlddsle|utsllri}|}|D;9||
+lldulttt{[[Tlddttslrid\\b[UJHFd\\lldtt{{ttuztkd\{{f]ctsl{{t{u{{ttult{{mtt||{{tt{]bZ]cd{{mttmttmtt{{nv
+
+§²¤¤¤mtt{{£|
+¨©´lks{{¨©´¤¦}lrif]c{u{[TT¨©´edklekuzt
+lks]bZlrimttmttmtt~u{{mtt{{{u{||ztllkk]lddb[U||{{tultlekdc\MRKllkrfkf]cf]cUMRtll{{¤¦§¨||
+¨©´ultuzt||}mttlksVTL\[[u{{tslultttsult{{{{edk}mttVZ[tts¤{{uzt\[[tlltsl\[btts[TTztlVZTkd\VTLb[UyleUTS[TTµ¶·JHF>ECSKJVTLJHF74,[TTrfk}b[U}f]cllklld{||UMR\[[VZTi\V]bZlriekdVTL|ztll|zfkktzl¦§¨fkk[[Trg]ekd{{¤tll
+¦§¨||{u{g\rUTSedkkd\u{{mttmttSKJult|z{u{£ddcd\\{u{lddsleldd|z]cdred|
+cbVd\\f]c|zmttd\\\[[utttsu{{uztuzt¦§¨ttsult|z{{t|||lri}mtt|zlkskd\{{¨©´£¬¶Ã
+|
+{{§²£lks
+¤¦§¨|
+¤}
+{{§²¤{{uzt¤£tsl|
+llktt{|z[[Tmttu{{|
+£|
+|
+
+u{{lek|
+lkslrimttu{{lld|z¨©´}lrib[Uekdr]g\[[VTLf]c}{||f]cmttult|{u{f]c¤||tyg{tt
+}lekrfk¦§¨{tt}|z¨©´|z{||llkllk{u{tts{{{{lksttstll}uzt{{
+\[[d\\ek]d\\edkllklddtsllri[[TVTLb[Uultlddu{{¦§¨UMR*)(aWMVTLd\\VTL[[TD;9[TTb[U{u{]bZ{{tttsztlSKJlld||tsltsluztddc|u{zmekdkd\ddc\[[lldttstygb[U}sle\[[|z¤
+¸Á¹lri|
+uzt]cdlri{{|z]bZf]c{{lrimttb[Ud\\\[[||lldlld{{lldtslsleekd|zldddc\tslj]\VTLv{u{{
+
+MRKVZT|uztsre}|z¦§¨¦§¨|z£¥{||||{{ttsl|{{
+ultmttVZTtt{{{|
+¤}
+}¤}¤¦£
+}~|
+lri£¨©´§²|z}¤¤ª³·¤ultult|
+
+{{
+
+lldu{{uzttsl}|
+¤¤¦nv¤¦¤¦{{mtt{u{ttsekd}lddddckd\uzt{{SKJttsUMRdc\D;9{ttMRKsle{{}{{tll{{t}¤lrid\\kd\{tt|
+}}{{t¨©´¤{u{ª³·}|u{{mttu{{tll
+lks|
+{{f]c{||{tt{{{{lrilkstsl{ttlld{{tmttultkd\rfk{{]bZkk]tllVTLUTS]bZ²²¬]bZ:97}VTLtzli\VJHFi\VUMRVTL
+\[[\[[mttnv|uzttll}|bVU¤¤ultlld]bZedk|
+sre{ttkd\bVUf]c}¤¦|z[TTtll¤¦[[Tllkd\\||}¤¦u{{edkVTL\[b\[bVTLdc\{||||ztlttsred]bZek]cbV
+llk]cdedkd\\lld]bZkk]tslUTS[[Tedk{||lriddcu{{mttsrei\V²²¬¦§¨{||uzt{||{{{{UTS|||
+|
+ttstt{tt{
+}tll£|
+u{{}{{¤§²££¨©´¬¶Ã§²
+mtt§²]cd¤¦
+|
+~{||¤¤µ¶·¤¤¤¤¦¤
+
+lriª³·]cdu{{]cd
+~|
+u{{mtt}
+mtt{u{cbV]cdf]cSKJttstllztlddcttsekdlrilksSKJ]cd|
+[TTlriddc[[T{u{lksylttszll¢{|||z¤¦§¨tsl¤¦¢{{{{|
+{tt
+}tt{lri|
+]bZmtttt{tllddcuztbVU\[[
+tsl|zsrecbVyfdlddred[[T¦§¨JHF*)(kd\VTLek]VTLMRKD;9{{t[TTlddJHFVTL\[[tt{{u{{||zll}ekd|tts}tsllekkd\VZT\[[{ttSKJ{{tzll|u|ztsltlluzt{tt}u||\[bcbVn
+fkkbVZSKJzlttstllkd\}VTL|zlek[TTtsld\\]bZ¨©´ult¤¤[TTUMRultrfklri]bZUMR|
+lriVZT{tt{{|z¤¢
+|ztslult
+||[[Tfkkuzt}tts{||
+{{mtt{{nv
+
+§²|
+²{{¤¦§¨u{{f]c£{u{
+£¥}¤uzt¤edk¤¤¦¦§¨
+¤¦µ¶·
+]cd|zVZ[mtt]cd§²ddcuztfkklkslksUTSSKJtsl{{t]cd{{tuzt
+|ztts||fkktt{lrif]ctts[TT[[TVTL{u{ttsmtt¤¦tzl{tt||}¦§¨¤¤{u{{u{{||u{{{{lkslksttsf]c]cdlks|
+\[b|
+ttstsl{tt|tll{||uztlld|z[[TVTLJHFlld[[T]bZult²²¬UTS*)(dc\[[TJHFaWMD;9D;9jV[FD;JHF\[[b[Uf]cultd\\lek}tt{ultiq][[T}zl|ek]u{{}uttzl|}rg]j]\}
+zlllddek]mtt{{tttslri{u{¤¦|tll{{||lldMRKSKJF=C{{trfkr]ZtllbVU]bZekdsle{tttlluekdtlltll
+v{ult{u{\[[ultfkk>B9tll|
+cbVekdu{{||{{|¤ttszlllddmtttslttstt{{{t
+tts|
+{tt¤mttlriuzt|
+\[b}
+
+
+}£
+¤¦¤{{¦§¨£
+ª³·¤¤¤¤¤~¤u{{lks
+kd\f]c|z|
+mttVZTnv|
+
+llku{{
+ult
+}f]c¤¤{|||zllk|z{{t]bZsle||dc\||\[[{tt\[b[TT}tzl|
+VTLek]JHF{u{¨©´{{¦§¨{ttuzttsl}~tll|
+ztl|
+]bZ{|||
+u{{{{
+
+{ttu{{mtt]cd
+{{||b[Uekd{ttfkkZbN|z\UZekdSKJVTLldd[[Tdc\VTL¦§¨:97*)(slejcVD;93+*JHF74,JHF[TTult}|ulldttsult||ult[[TttsUTS[[Tek]ddc{{
+|z|uultultultlksuzt\UZlritslek]{u{tsllri]cd?;C{tt[[Tsle{tt|ulriJHFddcdc\ddcd\\tlluVTL[TTttsd\\ultttsb[Uult[TTUMR[TTlri{||ttsekdfkk¢}|}}tll¢llk··Ämttuzt¦§¨ztl{|||zu{{
+tsl¤mtt{{|
+
+£¤ª³·}|
+§²ª³·¡¡}}
+¤¬¶Ã£¥¦§¨ª³·¤¦§²¢¤§²|
+£¥v¦§¨¤¤lks
+¤¦]cduztmttu{{{{tts|
+fkkmtt|
+{{edk]bZlks}|}rfk{{t
+tsl]bZ[[TUTS~u{{|uekd[[Tdc\u{{VZ[lrilekuztuzttsllrilriultd\\|
+tt{¦§¨¦§¨mwtslVTL{{¤{||}tslllklriult¤{{}tt{lks]bZ{{{u{{||f]cdc\SKJtsl|llk[TT[[TztlVTLsrett{d\\¤¤JHF*)(j]\cbVJHFSKJF=CF=C[[T[[TbVU}{{t||²««{u{tlllekllktll{zmdc\kd\{{t{{tlri]bZ¤wl
+}||red|
+}sle£¥
+¤¦SKJlektll~}\[bultleklritsld\\{ttddcv{mtttllb[Ud\\kd\b[UbVZdc\lddF=Cf]clekmttf]cmttttsu{{
+lri}|lldtsl
+
+{u{²²¬fkkuztf]c|{ttlld
+{{|
+{{
+¤¦§²§²}}|
+£§²tt{¤{{t
+¬¶Ã
+£¥¨©´lks
+lek£¤~mtt§²lddmttUTS|
+mtt|z¤¦£tt{{||
+
+{{lks{{t
+tll¤¤kk]uztVZTddclekbVZtslkd\lksVTL]bZtlluzt[TTtll]bZekdu{{{{{{|zlri{{{u{lld{u{v{ekd{{tzll||}|{{tts}f]cmttf]clri{{mtt]bZedk
+mtttt{dc\]cdu{{ttsllk{tt|zztl]cdlek[[T{{trg]VTL[[TSKJldd¦§¨\[[*)(sleJHFbVZJHFJHFVTLVTLkd\[TT{{t||ttsrfk{{
+{{ttslllklrillkttsu{{f]c}}{{tek]lksfkk}ttstzld\\uzt]cdultttsd\\
+UUY|||zddcdc\UMRdc\mttrg]leklddlri{ttjcV¦§¨[TTj]\ek][TT{tt}|
+llk{ttv{}|ztt{\[[]cd\[[
+¤||{||{||tsl|ztt{{||ekd}|zsle¢|
+ekd]bZ|zdc\
+
+
+¤¤¦¤£
+££}||
+{{{{{||{{¤§²¤¦|
+¤
+ult··Ä£¤¤¦¤¦lks]cdlksmttlri\[b
+mttmttult
+§²{{t{{{{t}tts{{t]bZ[[T|zuztllkf]c{{]bZek]tsl\[[JHFmttmtt|
+{||ddcztl[[T\[[¤¦§¨}lld¦§¨{{tlld
+uzt}lkslld\[[tsl}uzt|
+{{lks{||VZ[{{||leklddlri{{[[T{{tsl
+{{t]bZ|{u{{zmedkddc[[Tdc\VTLztl\UZldd¦§¨LKR*)(ztf{{t{ttUMRVTLj]\|zrg]v{f]ckd\tts{u{fkkv{tt{slekd\dc\ttsuztlks{u{tt{
+{||{tt\UZ|uf]ckk]{{t{{\[buzt¤¦tslmttlkstsl{||SKJ\[[[TT|
+[[Tdc\tllkd\lkskd\uttzl|u{zm¦§¨tsld\\kk]lld{{ultf]c||ult]cdlkslks{||lek¢
+
+}¤¦u··Ä¦§¨ekd
+{||ult£¥{{|ztts¤{||{||{ttlks¤¦}|
+|
+}|
+£{{¤|
+£¥{u{\[b·¶Ñ£¥¨©´¦§¨ªÁÅ¤¨©´{||
+¨©´¤¦§²£¤¦u{{|
+mtt\[[tts}|
+mtt]cdfkkddc|
+ultlriv{||d\\[TTkd\kd\fkksre\UZJHFmtttts{{VTLb[Uutmtt\[b\[b|
+{||u{{|[[Tlld}}{{|u{tt{u{|
+{tt{ttmttunvmttmtttslvultmtttt{
+||uztu{{ultmttUUYult{{t{||]bZsle\[[UTS[[Tllkdc\VTLVTLVTLd\\jV[SKJ¦§¨\[b74,red]bZlddekd[TTSKJ]bZSKJf]cb[Utslddcztl{{rfkvultdc\kk]{{tkk]dc\ult{{t|ud\\}[TTtzllri[[Tekdtsl¦§¨tlltts|z|zfkk}u{{{||uzt]cdJHFlksdc\[[TtllSKJtsl|zmtt
+tllVTLsretll|{zmf]cllk{{t{ttUTSztl{ttllkf]ctllf]cSKJJHFultu{{JHFtt{}¤¦{tt{u{
+mttvª³·dc\leklldkk]{||edk{{t|
+¤|
+ª³·ult{{mtttts|ztt{uzt{{ª³·¤mk
+{{{{¤¤}¤¦lekd\\|
+}f]clksª³·
+|z»ÂÇ|z{{t¨©´ª³·¤¦fkkVZ[|
+{{^fs]cdmtt\[bult¤¦{{¤f]c||tslddc
+JHF|
+uutf]cult\[[lkstt{{ttult¤£nv\[[]bZekd]bZJHFddcult¤
+
+¨©´kk]|
+{||tll||tslult\[[|SKJf]c£|
+{||tsl
+mttlks{{mtttslultyl\UZtsluztultuzt||ddcd\\kd\UTStslVTL[TTlld]bZrg]d\\¤¦LKR*)(bVUVTL74,JHFJHFf]clldUMR{tt|z|uztb[U}{u{ztl{{tkk]b[U[[T{{tdc\v{ut{{{tt{{tlricbV|zlek||tts{tttslult
+{u{{u{tts|zmttUTS\[bUMRd\\ekdVTL[[TbVZult{{srered[TTbVUf]cSKJ
+sletsl{zm¦§¨u{{}[TTSKJ||bVZlddllk{u{SKJf]clkstt{MSS{u{|¤|uddclks
+¦§¨tslult{{t£¥
+¢{||{{{{\[btt{{{¤¤¤mtt}}lksmk
+~tts{{t}ttsu{{
+¤¤¦|
+tsl]cdu{{¤¦
+{ttlks¤
+§²
+¤¦]cdUTS}nvmttVZ[\[b\[b|
+}\[[|
+}|
+
+{{{u{MRK{{¤f]cllkkd\{{lkslksmtt|z
+
+^fs\[[mttu{{{{t|zVTLtsltslVTLfkk
+{{
+ultu¤¤j]\
+u{{|f]cultLKR
+}lddtts}
+¤
+lekuzt{u{|
+lksmttlri|
+lriuztlekultd\\dc\UMRek]sle[TT]bZSKJ\[b[TT¦§¨MSS-1+VTL[TTPF=UTSddc\[[lldutred|z|z||u{{{ttbVZlek{zmj]\VTLmttdc\tzl|
+{||lek}
+{{t{{t\[[}UMR}tt{|z{{fkk¤
+{{¤|zwlVTLtsl[TTlksvSKJ|zddc{||}lddj]\tts|vJHF[TT|urfk{{tultslettstll{tt
+MSSf]cult\[bldd{ttultf]clek¤¦|z¤
+{||||¤}
+lld|
+
+uzt{||mttedk|z§²¤¤¦¤¤¦§¨¦§¨²¡|
+¡{{mttuzt£¥£llkult|
+¤¤¦|zf]cf]c{{¤}¨©´mtt]cd\[[ldd|
+mtt{{VZ[lks{{lksmtt{{lek\[blks{u{{ttSKJ{u{tll{u{VZ[tt{llkddclddrfk|
+{{tt{edk|
+
+mtt]cd]cdlld{||{ttult{{]cd{{t{tt¤¤u{{u{{|z[TTtt{{{|
+u{{ekd{{t{||tllfkk{u{VZT|
+
+{||ddc|
+ult
+ldd{tt|zekdddcUMRztlfkk
+SKJVTLdc\D;9JHFlldVTLldd¦§¨JHF,55sled\\:97JHFredbVUlri{u{tllUTSVTLlriultf]cultult]bZ{{tsl]bZ|uf]clekultdc\llk
+VTLVZTlek{{¦§¨UTSd\\
+{||tt{}¤ult
+{{tJHFf]cult{ttsleztlrfk£redrr]sletts¢¤{||
+{{rfk{zm\UZJHFddc{{\UZLKR}£¥{u{ldd
+|zmtt||¤lksut|u{||{tt[[Tmk
+uztlks{{
+§²··Ä£¨©´¤¤¤}~mtt{{t{{t{{¨©´¨©´¤µ¶·}¤]cd{||{{ult{{
+
+{{ttstt{{||]cd
+tts]cd|zn
+mttlkslks¤ultu{{}}}uztg\r}edk||f]c|
+{{|
+lks\[blks£nv¢|z{{}|tll
+
+tsl
+tslult
+¤¦tt{}mtt
+~¤mttfkk}
+ttsfkkttsu{{{{{{\[[mttmttUMRllk}mttuztUTSfkkUTSSKJ|ztsl[TTSKJ[[Trg]aWMlrilddcbVult¦§¨LKR,55wl[TT\UZddcJHFtll[[Tultllk]bZtzl{ttult[TTtsl||SKJmtt|zttsek]lddllkd\\{||d\\mttJHFVZTbVZlks
+mtt|
+}}{{u{{lks¤{ttsle[[TUMR?;Cf]cSKJ}lekttstt{f]c|UMRkk]ztl}|VTLuzt
+f]c||VTL
+lddldd[[Tekdd\\mttlks\[b{|||
+lksldd{{tts}|zu{{{{||
+|
+|}tll}||tll{{{{¤¦
+
+§²¨©´£·¶Ñ¤
+¡u{{b[Ulld{{||££¥¦§¨ult~¦§¨|z|
+¤¦§¨¤¦¨©´£²mtt¤lkslddmtt¤¦£|
+{{nv¤¦]cd|
+\[b|zlek\UZlkslek~}
+}lks}
+lks{||{{LKR
+{{\[b~|
+mttd\\
+£¥
+lri}¦§¨{{t
+|
+|
+lks{u{¤¤¦£|
+tllf]cfkklriu{{ultu{{{{|||
+mttlkslks
+
+lks]cddc\\[[dc\[TTultddcsre{ttlrikd\ztlVTL¦§¨MSS:97tzl}ultSKJVTLVZTVTL[TT[[Tf]cutllkdc\lekb[Utts}tt{|||
+mtt|zuztlld|f]clksultult¤¦|zddc{ttJHFtsl|u|
+u{{|
+ttstt{
+}tlld\\iq]lriUMR|
+d\\llktlllri\UZ[TTsle}\[[ult}ztl¦§¨\[[||]cdJHF[TTVZTVTL\[[ekdSKJ^fsmttSKJdc\ldd¤ult}|}{||
+uztllklldtll¢{||{{tzlltts\[b}ult£u{{ulttt{¤
+
+¤£lek{u{}{u{µ¶·¢¤¨©´ª³·§²¢|
+¤¦v{£¥}£
+
+|
+¤¦lri¨©´{{|
+£¤¦}mttlektt{v[TT{{t{{t{{tztl]bZ
+{{||tts{||JHFVZ[lksn
+MSSmttmtt{||fkk\[[¤¤¦|
+ldd
+}|nvultdc\¤tt{edkUUY{||{{mtt]cd\[b^fs
+mttmttmttf]cmtttslekduztUTS|utleklrid\\f]ccbVlddSKJlldUMRr]ZVTLµ¶·OS`)+2|llkFD;[[TSKJFD;SKJVZTUMRJHFJHFtsllldredSKJ{||UTS\[b¨©´ekd¢|z|
+tts{||mtt
+{||lri¤]cdvuztztl[TTztltts¤\[btsl{{
+{u{UTS|
+]bZ{{JHFddcult}|\[[d\\srelri{tt}|rfksrebVZdc\edksleddcu{{\[[ekdf]c\UZ|
+d\\|z[[T\[[\[b¤d\\{{td\\£¥¨©´¦§¨||lritts
+}{tt¦§¨¤¦||||
+¢
+ttsUUY{{¤¤¦}¬¶Ã~£¨©´
+£uzt¦§¨
+tt{~{tt{||¤¤{tt
+}
+¤£lks¤¦
+]cdlriddcult|
+uzt|
+¬¶Ã¤ddcultult[TTtllekdiq]]bZekdkd\{{\[[ekdf]c¤{u{lksmtttt{|
+|
+n
+¡ek]|
+lksuztmtt{{lks{{~
+tll}|
+{{lksddc{u{{{tult|
+mtt|
+{{lksfkk\[b]cd\[b]cdfkkddcuzt]cdlri|z{||[TTb[Ukd\sleb[UyleyfdllkJHFaWMlri¤¦OS`*)(tts}{ttd\\sre{{tb[UVTL74,JHFFD;UTSVZTkd\redjV[{u{ekdmtt{{tult{{t|zu{{lkslri\UZuzt}[TTlri]cdddc{||UTStt{¢|
+tts{u{|
+uztultUTSlddztl|zek]{{:97f]c\[[{ttlld{u{|z{ttrfk{ttsref]cUMR[[TlriJHF||\[b{{¤ult]bZult}||mttekdtt{£¥ª³·{||{||¤¦}{{tª³·}u{{|
+{{ultmk
+}§²¤¦~¤¦ult²¤¦££
+£|
+tll¤¦}µ¶·
+¤¦|
+«²«£¦§¨¤lks¤¤£
+¨©´¡¡
+{tt±¯VZ[{{]cdmttUUY
+ultylf]cf]cwlddcJHF[[T|edkulttt{edkmtt}]cdMRK{{|
+OS`lri]bZLKR{{lksuztyl¤¤
+
+
+}
+edkttslekmttfkk{||
+|
+\[[f]c\[b]cd{{lks|
+}
+||
+lksVZT
+f]ckd\b[Uf]c[[Trg]red{{tekd]bZtsl¨©´JHF,55mttlldbVUFD;b[Uzlekd[[Tekdlri¢SKJlld}{u{{u{d\\UTS
+lks|zlrimttu{{mttllk\[[llk\[[ldd{tt{||lri{{ulttsl{{mtt|{||}}ult{{ttsdc\{{t{{t[[TlksJHFJHFd\\|z{{|utsl[TTrfkVTLrfkdc\FD;sleekd[TTkk]|
+lld}{u{JHF{{\[[UUY]bZ{u{SKJllkzlllek{||||
+
+
+}lldlri}ldd|z{{llklkslekmtt¤¦{{|
+£§²¡¤{{¤
Index: /code/branches/ode/ode-0.9/include/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/include/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/include/Makefile.am	(revision 216)
@@ -0,0 +1,1 @@
+SUBDIRS = ode
Index: /code/branches/ode/ode-0.9/include/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/include/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/include/Makefile.in	(revision 216)
@@ -0,0 +1,488 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = ode
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  include/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic ctags \
+	ctags-recursive distclean distclean-generic distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+	tags-recursive uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/include/drawstuff/drawstuff.h
===================================================================
--- /code/branches/ode/ode-0.9/include/drawstuff/drawstuff.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/drawstuff/drawstuff.h	(revision 216)
@@ -0,0 +1,294 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/** @defgroup drawstuff DrawStuff
+
+DrawStuff is a library for rendering simple 3D objects in a virtual 
+environment, for the purposes of demonstrating the features of ODE.
+It is provided for demonstration purposes and is not intended for
+production use.
+
+@section Notes
+
+In the virtual world, the z axis is "up" and z=0 is the floor.
+
+The user is able to click+drag in the main window to move the camera:
+  * left button - pan and tilt.
+  * right button - forward and sideways.
+  * left + right button (or middle button) - sideways and up.
+*/
+
+
+#ifndef __DRAWSTUFF_H__
+#define __DRAWSTUFF_H__
+
+/* Define a DLL export symbol for those platforms that need it */
+#if defined(ODE_PLATFORM_WINDOWS)
+  #if defined(DS_DLL)
+    #define DS_API __declspec(dllexport)
+  #elif !defined(DS_LIB)
+    #define DS_DLL_API __declspec(dllimport)
+  #endif
+#endif
+    
+#if !defined(DS_API)
+  #define DS_API
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <drawstuff/version.h>
+
+
+/* texture numbers */
+#define DS_NONE   0	/* uses the current color instead of a texture */
+#define DS_WOOD   1
+
+
+/**
+ * @struct dsFunctions
+ * @brief Set of functions to be used as callbacks by the simulation loop.
+ * @ingroup drawstuff
+ */
+typedef struct dsFunctions {
+  int version;			/* put DS_VERSION here */
+  /* version 1 data */
+  void (*start)();		/* called before sim loop starts */
+  void (*step) (int pause);	/* called before every frame */
+  void (*command) (int cmd);	/* called if a command key is pressed */
+  void (*stop)();		/* called after sim loop exits */
+  /* version 2 data */
+  char *path_to_textures;	/* if nonzero, path to texture files */
+} dsFunctions;
+
+
+/**
+ * @brief Does the complete simulation.
+ * @ingroup drawstuff
+ * This function starts running the simulation, and only exits when the simulation is done.
+ * Function pointers should be provided for the callbacks.
+ * @param argv supports flags like '-notex' '-noshadow' '-pause'
+ * @param fn Callback functions.
+ */
+DS_API void dsSimulationLoop (int argc, char **argv,
+		       int window_width, int window_height,
+		       struct dsFunctions *fn);
+
+/**
+ * @brief exit with error message.
+ * @ingroup drawstuff
+ * This function displays an error message then exit.
+ * @param msg format strin, like printf, without the newline character.
+ */
+DS_API void dsError (char *msg, ...);
+
+/**
+ * @brief exit with error message and core dump.
+ * @ingroup drawstuff
+ * this functions tries to dump core or start the debugger.
+ * @param msg format strin, like printf, without the newline character.
+ */
+DS_API void dsDebug (char *msg, ...);
+
+/**
+ * @brief print log message
+ * @ingroup drawstuff
+ * @param msg format string, like printf, without the \n.
+ */
+DS_API void dsPrint (char *msg, ...);
+
+/**
+ * @brief Sets the viewpoint
+ * @ingroup drawstuff
+ * @param xyz camera position.
+ * @param hpr contains heading, pitch and roll numbers in degrees. heading=0
+ * points along the x axis, pitch=0 is looking towards the horizon, and
+ * roll 0 is "unrotated".
+ */
+DS_API void dsSetViewpoint (float xyz[3], float hpr[3]);
+
+
+/**
+ * @brief Gets the viewpoint
+ * @ingroup drawstuff
+ * @param xyz position
+ * @param hpr heading,pitch,roll.
+ */
+DS_API void dsGetViewpoint (float xyz[3], float hpr[3]);
+
+/**
+ * @brief Stop the simulation loop.
+ * @ingroup drawstuff
+ * Calling this from within dsSimulationLoop()
+ * will cause it to exit and return to the caller. it is the same as if the
+ * user used the exit command. using this outside the loop will have no
+ * effect.
+ */
+DS_API void dsStop();
+
+/**
+ * @brief Get the elapsed time (on wall-clock)
+ * @ingroup drawstuff
+ * It returns the nr of seconds since the last call to this function.
+ */
+DS_API double dsElapsedTime();
+
+/**
+ * @brief Toggle the rendering of textures.
+ * @ingroup drawstuff
+ * It changes the way objects are drawn. these changes will apply to all further
+ * dsDrawXXX() functions. 
+ * @param the texture number must be a DS_xxx texture constant.
+ * The current texture is colored according to the current color.
+ * At the start of each frame, the texture is reset to none and the color is
+ * reset to white.
+ */
+DS_API void dsSetTexture (int texture_number);
+
+/**
+ * @brief Set the color with which geometry is drawn.
+ * @ingroup drawstuff
+ * @param red Red component from 0 to 1
+ * @param green Green component from 0 to 1
+ * @param blue Blue component from 0 to 1
+ */
+DS_API void dsSetColor (float red, float green, float blue);
+
+/**
+ * @brief Set the color and transparency with which geometry is drawn.
+ * @ingroup drawstuff
+ * @param alpha Note that alpha transparency is a misnomer: it is alpha opacity.
+ * 1.0 means fully opaque, and 0.0 means fully transparent.
+ */
+DS_API void dsSetColorAlpha (float red, float green, float blue, float alpha);
+
+/**
+ * @brief Draw a box.
+ * @ingroup drawstuff
+ * @param pos is the x,y,z of the center of the object.
+ * @param R is a 3x3 rotation matrix for the object, stored by row like this:
+ *        [ R11 R12 R13 0 ]
+ *        [ R21 R22 R23 0 ]
+ *        [ R31 R32 R33 0 ]
+ * @param sides[] is an array of x,y,z side lengths.
+ */
+DS_API void dsDrawBox (const float pos[3], const float R[12], const float sides[3]);
+
+/**
+ * @brief Draw a sphere.
+ * @ingroup drawstuff
+ * @param pos Position of center.
+ * @param R orientation.
+ * @param radius
+ */
+DS_API void dsDrawSphere (const float pos[3], const float R[12], float radius);
+
+/**
+ * @brief Draw a triangle.
+ * @ingroup drawstuff
+ * @param pos Position of center
+ * @param R orientation
+ * @param v0 first vertex
+ * @param v1 second
+ * @param v2 third vertex
+ * @param solid set to 0 for wireframe
+ */
+DS_API void dsDrawTriangle (const float pos[3], const float R[12],
+		     const float *v0, const float *v1, const float *v2, int solid);
+
+/**
+ * @brief Draw a z-aligned cylinder
+ * @ingroup drawstuff
+ */
+DS_API void dsDrawCylinder (const float pos[3], const float R[12],
+		     float length, float radius);
+
+/**
+ * @brief Draw a z-aligned capsule
+ * @ingroup drawstuff
+ */
+DS_API void dsDrawCapsule (const float pos[3], const float R[12],
+		    float length, float radius);
+
+/**
+ * @brief Draw a line.
+ * @ingroup drawstuff
+ */
+DS_API void dsDrawLine (const float pos1[3], const float pos2[3]);
+
+/**
+ * @brief Draw a convex shape.
+ * @ingroup drawstuff
+ */
+DS_API void dsDrawConvex(const float pos[3], const float R[12],
+		  float *_planes,
+		  unsigned int _planecount,
+		  float *_points,
+		  unsigned int _pointcount,
+		  unsigned int *_polygons);
+
+ /* these drawing functions are identical to the ones above, except they take
+ * double arrays for `pos' and `R'.
+ */
+DS_API void dsDrawBoxD (const double pos[3], const double R[12],
+		 const double sides[3]);
+DS_API void dsDrawSphereD (const double pos[3], const double R[12],
+		    const float radius);
+DS_API void dsDrawTriangleD (const double pos[3], const double R[12],
+		      const double *v0, const double *v1, const double *v2, int solid);
+DS_API void dsDrawCylinderD (const double pos[3], const double R[12],
+		      float length, float radius);
+DS_API void dsDrawCapsuleD (const double pos[3], const double R[12],
+		     float length, float radius);
+DS_API void dsDrawLineD (const double pos1[3], const double pos2[3]);
+DS_API void dsDrawConvexD(const double pos[3], const double R[12],
+		  double *_planes,
+		  unsigned int _planecount,
+		  double *_points,
+		  unsigned int _pointcount,
+		  unsigned int *_polygons);
+
+/**
+ * @brief Set the quality with which curved objects are rendered.
+ * @ingroup drawstuff
+ * Higher numbers are higher quality, but slower to draw. 
+ * This must be set before the first objects are drawn to be effective.
+ * Default sphere quality is 1, default capsule quality is 3.
+ */
+DS_API void dsSetSphereQuality (int n);		/* default = 1 */
+DS_API void dsSetCapsuleQuality (int n);		/* default = 3 */
+
+// Backwards compatible API
+#define dsDrawCappedCylinder dsDrawCapsule
+#define dsDrawCappedCylinderD dsDrawCapsuleD
+#define dsSetCappedCylinderQuality dsSetCapsuleQuality
+
+/* closing bracket for extern "C" */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: /code/branches/ode/ode-0.9/include/drawstuff/version.h
===================================================================
--- /code/branches/ode/ode-0.9/include/drawstuff/version.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/drawstuff/version.h	(revision 216)
@@ -0,0 +1,29 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef __VERSION_H
+#define __VERSION_H
+
+/* high byte is major version, low byte is minor version */
+#define DS_VERSION 0x0002
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/Makefile.am	(revision 216)
@@ -0,0 +1,23 @@
+libglitch_includedir = $(includedir)/ode
+libglitch_include_HEADERS = 	collision_trimesh.h \
+				mass.h \
+				odecpp.h \
+				common.h \
+				matrix.h \
+				odecpp_collision.h \
+				compatibility.h \
+				memory.h \
+				contact.h \
+				misc.h \
+				odemath.h \
+				collision.h \
+				error.h \
+				objects.h \
+				rotation.h \
+				collision_space.h \
+				export-dif.h \
+				ode.h  \
+				timer.h \
+				config.h
+
+EXTRA_DIST = config.h.in
Index: /code/branches/ode/ode-0.9/include/ode/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/Makefile.in	(revision 216)
@@ -0,0 +1,448 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include/ode
+DIST_COMMON = README $(libglitch_include_HEADERS) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+	$(srcdir)/config.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libglitch_includedir)"
+libglitch_includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libglitch_include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+libglitch_includedir = $(includedir)/ode
+libglitch_include_HEADERS = collision_trimesh.h \
+				mass.h \
+				odecpp.h \
+				common.h \
+				matrix.h \
+				odecpp_collision.h \
+				compatibility.h \
+				memory.h \
+				contact.h \
+				misc.h \
+				odemath.h \
+				collision.h \
+				error.h \
+				objects.h \
+				rotation.h \
+				collision_space.h \
+				export-dif.h \
+				ode.h  \
+				timer.h \
+				config.h
+
+EXTRA_DIST = config.h.in
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  include/ode/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  include/ode/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status include/ode/config.h
+$(srcdir)/config.h.in:  $(am__configure_deps) 
+	cd $(top_srcdir) && $(AUTOHEADER)
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+install-libglitch_includeHEADERS: $(libglitch_include_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libglitch_includedir)" || $(MKDIR_P) "$(DESTDIR)$(libglitch_includedir)"
+	@list='$(libglitch_include_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(libglitch_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libglitch_includedir)/$$f'"; \
+	  $(libglitch_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libglitch_includedir)/$$f"; \
+	done
+
+uninstall-libglitch_includeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libglitch_include_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libglitch_includedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(libglitch_includedir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS) config.h
+installdirs:
+	for dir in "$(DESTDIR)$(libglitch_includedir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libglitch_includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libglitch_includeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	ctags distclean distclean-generic distclean-hdr distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libglitch_includeHEADERS install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+	pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-libglitch_includeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/include/ode/README
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/README	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/README	(revision 216)
@@ -0,0 +1,18 @@
+
+this is the public C interface to the ODE library.
+
+all these files should be includable from C, i.e. they should not use any
+C++ features. everything should be protected with
+
+	#ifdef __cplusplus
+	extern "C" {
+	#endif
+
+	...
+
+	#ifdef __cplusplus
+	}
+	#endif
+
+the only exceptions are the odecpp.h and odecpp_collisioh.h files, which define a C++ wrapper for
+the C interface. remember to keep this in sync!
Index: /code/branches/ode/ode-0.9/include/ode/collision.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/collision.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/collision.h	(revision 216)
@@ -0,0 +1,1386 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_COLLISION_H_
+#define _ODE_COLLISION_H_
+
+#include <ode/common.h>
+#include <ode/collision_space.h>
+#include <ode/contact.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup collide Collision Detection
+ *
+ * ODE has two main components: a dynamics simulation engine and a collision
+ * detection engine. The collision engine is given information about the
+ * shape of each body. At each time step it figures out which bodies touch
+ * each other and passes the resulting contact point information to the user.
+ * The user in turn creates contact joints between bodies.
+ *
+ * Using ODE's collision detection is optional - an alternative collision
+ * detection system can be used as long as it can supply the right kinds of
+ * contact information.
+ */
+
+
+/* ************************************************************************ */
+/* general functions */
+
+/**
+ * @brief Destroy a geom, removing it from any space.
+ *
+ * Destroy a geom, removing it from any space it is in first. This one
+ * function destroys a geom of any type, but to create a geom you must call
+ * a creation function for that type.
+ *
+ * When a space is destroyed, if its cleanup mode is 1 (the default) then all
+ * the geoms in that space are automatically destroyed as well.
+ *
+ * @param geom the geom to be destroyed.
+ * @ingroup collide
+ */
+ODE_API void dGeomDestroy (dGeomID geom);
+
+
+/**
+ * @brief Set the user-defined data pointer stored in the geom.
+ *
+ * @param geom the geom to hold the data
+ * @param data the data pointer to be stored
+ * @ingroup collide
+ */
+ODE_API void dGeomSetData (dGeomID geom, void* data);
+
+
+/**
+ * @brief Get the user-defined data pointer stored in the geom.
+ *
+ * @param geom the geom containing the data
+ * @ingroup collide
+ */
+ODE_API void *dGeomGetData (dGeomID geom);
+
+
+/**
+ * @brief Set the body associated with a placeable geom.
+ *
+ * Setting a body on a geom automatically combines the position vector and
+ * rotation matrix of the body and geom, so that setting the position or
+ * orientation of one will set the value for both objects. Setting a body
+ * ID of zero gives the geom its own position and rotation, independent
+ * from any body. If the geom was previously connected to a body then its
+ * new independent position/rotation is set to the current position/rotation
+ * of the body.
+ *
+ * Calling these functions on a non-placeable geom results in a runtime
+ * error in the debug build of ODE.
+ *
+ * @param geom the geom to connect
+ * @param body the body to attach to the geom
+ * @ingroup collide
+ */
+ODE_API void dGeomSetBody (dGeomID geom, dBodyID body);
+
+
+/**
+ * @brief Get the body associated with a placeable geom.
+ * @param geom the geom to query.
+ * @sa dGeomSetBody
+ * @ingroup collide
+ */
+ODE_API dBodyID dGeomGetBody (dGeomID geom);
+
+
+/**
+ * @brief Set the position vector of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's position will also be changed.
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom the geom to set.
+ * @param x the new X coordinate.
+ * @param y the new Y coordinate.
+ * @param z the new Z coordinate.
+ * @sa dBodySetPosition
+ * @ingroup collide
+ */
+ODE_API void dGeomSetPosition (dGeomID geom, dReal x, dReal y, dReal z);
+
+
+/**
+ * @brief Set the rotation matrix of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's rotation will also be changed.
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom the geom to set.
+ * @param R the new rotation matrix.
+ * @sa dBodySetRotation
+ * @ingroup collide
+ */
+ODE_API void dGeomSetRotation (dGeomID geom, const dMatrix3 R);
+
+
+/**
+ * @brief Set the rotation of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's rotation will also be changed.
+ *
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom the geom to set.
+ * @param Q the new rotation.
+ * @sa dBodySetQuaternion
+ * @ingroup collide
+ */
+ODE_API void dGeomSetQuaternion (dGeomID geom, const dQuaternion Q);
+
+
+/**
+ * @brief Get the position vector of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's position will be returned.
+ *
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom the geom to query.
+ * @returns A pointer to the geom's position vector.
+ * @remarks The returned value is a pointer to the geom's internal
+ *          data structure. It is valid until any changes are made
+ *          to the geom.
+ * @sa dBodyGetPosition
+ * @ingroup collide
+ */
+ODE_API const dReal * dGeomGetPosition (dGeomID geom);
+
+
+/**
+ * @brief Copy the position of a geom into a vector.
+ * @ingroup collide
+ * @param geom  the geom to query
+ * @param pos   a copy of the geom position
+ * @sa dGeomGetPosition
+ */
+ODE_API void dGeomCopyPosition (dGeomID geom, dVector3 pos);
+
+
+/**
+ * @brief Get the rotation matrix of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's rotation will be returned.
+ *
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom the geom to query.
+ * @returns A pointer to the geom's rotation matrix.
+ * @remarks The returned value is a pointer to the geom's internal
+ *          data structure. It is valid until any changes are made
+ *          to the geom.
+ * @sa dBodyGetRotation
+ * @ingroup collide
+ */
+ODE_API const dReal * dGeomGetRotation (dGeomID geom);
+
+
+/**
+ * @brief Get the rotation matrix of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's rotation will be returned.
+ *
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom   the geom to query.
+ * @param R      a copy of the geom rotation
+ * @sa dGeomGetRotation
+ * @ingroup collide
+ */
+ODE_API void dGeomCopyRotation(dGeomID geom, dMatrix3 R);
+
+
+/**
+ * @brief Get the rotation quaternion of a placeable geom.
+ *
+ * If the geom is attached to a body, the body's quaternion will be returned.
+ *
+ * Calling this function on a non-placeable geom results in a runtime error in
+ * the debug build of ODE.
+ *
+ * @param geom the geom to query.
+ * @param result a copy of the rotation quaternion.
+ * @sa dBodyGetQuaternion
+ * @ingroup collide
+ */
+ODE_API void dGeomGetQuaternion (dGeomID geom, dQuaternion result);
+
+
+/**
+ * @brief Return the axis-aligned bounding box.
+ *
+ * Return in aabb an axis aligned bounding box that surrounds the given geom.
+ * The aabb array has elements (minx, maxx, miny, maxy, minz, maxz). If the
+ * geom is a space, a bounding box that surrounds all contained geoms is
+ * returned.
+ *
+ * This function may return a pre-computed cached bounding box, if it can
+ * determine that the geom has not moved since the last time the bounding
+ * box was computed.
+ *
+ * @param geom the geom to query
+ * @param aabb the returned bounding box
+ * @ingroup collide
+ */
+ODE_API void dGeomGetAABB (dGeomID geom, dReal aabb[6]);
+
+
+/**
+ * @brief Determing if a geom is a space.
+ * @param geom the geom to query
+ * @returns Non-zero if the geom is a space, zero otherwise.
+ * @ingroup collide
+ */
+ODE_API int dGeomIsSpace (dGeomID geom);
+
+
+/**
+ * @brief Query for the space containing a particular geom.
+ * @param geom the geom to query
+ * @returns The space that contains the geom, or NULL if the geom is
+ *          not contained by a space.
+ * @ingroup collide
+ */
+ODE_API dSpaceID dGeomGetSpace (dGeomID);
+
+
+/**
+ * @brief Given a geom, this returns its class.
+ *
+ * The ODE classes are:
+ *  @li dSphereClass
+ *  @li dBoxClass
+ *  @li dCylinderClass
+ *  @li dPlaneClass
+ *  @li dRayClass
+ *  @li dConvexClass
+ *  @li dGeomTransformClass
+ *  @li dTriMeshClass
+ *  @li dSimpleSpaceClass
+ *  @li dHashSpaceClass
+ *  @li dQuadTreeSpaceClass
+ *  @li dFirstUserClass
+ *  @li dLastUserClass
+ *
+ * User-defined class will return their own number.
+ *
+ * @param geom the geom to query
+ * @returns The geom class ID.
+ * @ingroup collide
+ */
+ODE_API int dGeomGetClass (dGeomID geom);
+
+
+/**
+ * @brief Set the "category" bitfield for the given geom.
+ *
+ * The category bitfield is used by spaces to govern which geoms will
+ * interact with each other. The bitfield is guaranteed to be at least
+ * 32 bits wide. The default category values for newly created geoms
+ * have all bits set.
+ *
+ * @param geom the geom to set
+ * @param bits the new bitfield value
+ * @ingroup collide
+ */
+ODE_API void dGeomSetCategoryBits (dGeomID geom, unsigned long bits);
+
+
+/**
+ * @brief Set the "collide" bitfield for the given geom.
+ *
+ * The collide bitfield is used by spaces to govern which geoms will
+ * interact with each other. The bitfield is guaranteed to be at least
+ * 32 bits wide. The default category values for newly created geoms
+ * have all bits set.
+ *
+ * @param geom the geom to set
+ * @param bits the new bitfield value
+ * @ingroup collide
+ */
+ODE_API void dGeomSetCollideBits (dGeomID geom, unsigned long bits);
+
+
+/**
+ * @brief Get the "category" bitfield for the given geom.
+ *
+ * @param geom the geom to set
+ * @param bits the new bitfield value
+ * @sa dGeomSetCategoryBits
+ * @ingroup collide
+ */
+ODE_API unsigned long dGeomGetCategoryBits (dGeomID);
+
+
+/**
+ * @brief Get the "collide" bitfield for the given geom.
+ *
+ * @param geom the geom to set
+ * @param bits the new bitfield value
+ * @sa dGeomSetCollideBits
+ * @ingroup collide
+ */
+ODE_API unsigned long dGeomGetCollideBits (dGeomID);
+
+
+/**
+ * @brief Enable a geom.
+ *
+ * Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2,
+ * although they can still be members of a space. New geoms are created in
+ * the enabled state.
+ *
+ * @param geom   the geom to enable
+ * @sa dGeomDisable
+ * @sa dGeomIsEnabled
+ * @ingroup collide
+ */
+ODE_API void dGeomEnable (dGeomID geom);
+
+
+/**
+ * @brief Disable a geom.
+ *
+ * Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2,
+ * although they can still be members of a space. New geoms are created in
+ * the enabled state.
+ *
+ * @param geom   the geom to disable
+ * @sa dGeomDisable
+ * @sa dGeomIsEnabled
+ * @ingroup collide
+ */
+ODE_API void dGeomDisable (dGeomID geom);
+
+
+/**
+ * @brief Check to see if a geom is enabled.
+ *
+ * Disabled geoms are completely ignored by dSpaceCollide and dSpaceCollide2,
+ * although they can still be members of a space. New geoms are created in
+ * the enabled state.
+ *
+ * @param geom   the geom to query
+ * @returns Non-zero if the geom is enabled, zero otherwise.
+ * @sa dGeomDisable
+ * @sa dGeomIsEnabled
+ * @ingroup collide
+ */
+ODE_API int dGeomIsEnabled (dGeomID geom);
+
+/* ************************************************************************ */
+/* geom offset from body */
+
+/**
+ * @brief Set the local offset position of a geom from its body.
+ *
+ * Sets the geom's positional offset in local coordinates.
+ * After this call, the geom will be at a new position determined from the
+ * body's position and the offset.
+ * The geom must be attached to a body.
+ * If the geom did not have an offset, it is automatically created.
+ *
+ * @param geom the geom to set.
+ * @param x the new X coordinate.
+ * @param y the new Y coordinate.
+ * @param z the new Z coordinate.
+ * @ingroup collide
+ */
+ODE_API void dGeomSetOffsetPosition (dGeomID geom, dReal x, dReal y, dReal z);
+
+
+/**
+ * @brief Set the local offset rotation matrix of a geom from its body.
+ *
+ * Sets the geom's rotational offset in local coordinates.
+ * After this call, the geom will be at a new position determined from the
+ * body's position and the offset.
+ * The geom must be attached to a body.
+ * If the geom did not have an offset, it is automatically created.
+ *
+ * @param geom the geom to set.
+ * @param R the new rotation matrix.
+ * @ingroup collide
+ */
+ODE_API void dGeomSetOffsetRotation (dGeomID geom, const dMatrix3 R);
+
+
+/**
+ * @brief Set the local offset rotation of a geom from its body.
+ *
+ * Sets the geom's rotational offset in local coordinates.
+ * After this call, the geom will be at a new position determined from the
+ * body's position and the offset.
+ * The geom must be attached to a body.
+ * If the geom did not have an offset, it is automatically created.
+ *
+ * @param geom the geom to set.
+ * @param Q the new rotation.
+ * @ingroup collide
+ */
+ODE_API void dGeomSetOffsetQuaternion (dGeomID geom, const dQuaternion Q);
+
+
+/**
+ * @brief Set the offset position of a geom from its body.
+ *
+ * Sets the geom's positional offset to move it to the new world
+ * coordinates.
+ * After this call, the geom will be at the world position passed in,
+ * and the offset will be the difference from the current body position.
+ * The geom must be attached to a body.
+ * If the geom did not have an offset, it is automatically created.
+ *
+ * @param geom the geom to set.
+ * @param x the new X coordinate.
+ * @param y the new Y coordinate.
+ * @param z the new Z coordinate.
+ * @ingroup collide
+ */
+ODE_API void dGeomSetOffsetWorldPosition (dGeomID geom, dReal x, dReal y, dReal z);
+
+
+/**
+ * @brief Set the offset rotation of a geom from its body.
+ *
+ * Sets the geom's rotational offset to orient it to the new world
+ * rotation matrix.
+ * After this call, the geom will be at the world orientation passed in,
+ * and the offset will be the difference from the current body orientation.
+ * The geom must be attached to a body.
+ * If the geom did not have an offset, it is automatically created.
+ *
+ * @param geom the geom to set.
+ * @param R the new rotation matrix.
+ * @ingroup collide
+ */
+ODE_API void dGeomSetOffsetWorldRotation (dGeomID geom, const dMatrix3 R);
+
+
+/**
+ * @brief Set the offset rotation of a geom from its body.
+ *
+ * Sets the geom's rotational offset to orient it to the new world
+ * rotation matrix.
+ * After this call, the geom will be at the world orientation passed in,
+ * and the offset will be the difference from the current body orientation.
+ * The geom must be attached to a body.
+ * If the geom did not have an offset, it is automatically created.
+ *
+ * @param geom the geom to set.
+ * @param Q the new rotation.
+ * @ingroup collide
+ */
+ODE_API void dGeomSetOffsetWorldQuaternion (dGeomID geom, const dQuaternion);
+
+
+/**
+ * @brief Clear any offset from the geom.
+ *
+ * If the geom has an offset, it is eliminated and the geom is
+ * repositioned at the body's position.  If the geom has no offset,
+ * this function does nothing.
+ * This is more efficient than calling dGeomSetOffsetPosition(zero)
+ * and dGeomSetOffsetRotation(identiy), because this function actually
+ * eliminates the offset, rather than leaving it as the identity transform.
+ *
+ * @param geom the geom to have its offset destroyed.
+ * @ingroup collide
+ */
+ODE_API void dGeomClearOffset(dGeomID geom);
+
+
+/**
+ * @brief Check to see whether the geom has an offset.
+ *
+ * This function will return non-zero if the offset has been created.
+ * Note that there is a difference between a geom with no offset,
+ * and a geom with an offset that is the identity transform.
+ * In the latter case, although the observed behaviour is identical,
+ * there is a unnecessary computation involved because the geom will
+ * be applying the transform whenever it needs to recalculate its world
+ * position.
+ *
+ * @param geom the geom to query.
+ * @returns Non-zero if the geom has an offset, zero otherwise.
+ * @ingroup collide
+ */
+ODE_API int dGeomIsOffset(dGeomID geom);
+
+
+/**
+ * @brief Get the offset position vector of a geom.
+ *
+ * Returns the positional offset of the geom in local coordinates.
+ * If the geom has no offset, this function returns the zero vector.
+ *
+ * @param geom the geom to query.
+ * @returns A pointer to the geom's offset vector.
+ * @remarks The returned value is a pointer to the geom's internal
+ *          data structure. It is valid until any changes are made
+ *          to the geom.
+ * @ingroup collide
+ */
+ODE_API const dReal * dGeomGetOffsetPosition (dGeomID geom);
+
+
+/**
+ * @brief Copy the offset position vector of a geom.
+ *
+ * Returns the positional offset of the geom in local coordinates.
+ * If the geom has no offset, this function returns the zero vector.
+ *
+ * @param geom   the geom to query.
+ * @param pos    returns the offset position
+ * @ingroup collide
+ */
+ODE_API void dGeomCopyOffsetPosition (dGeomID geom, dVector3 pos);
+
+
+/**
+ * @brief Get the offset rotation matrix of a geom.
+ *
+ * Returns the rotational offset of the geom in local coordinates.
+ * If the geom has no offset, this function returns the identity
+ * matrix.
+ *
+ * @param geom the geom to query.
+ * @returns A pointer to the geom's offset rotation matrix.
+ * @remarks The returned value is a pointer to the geom's internal
+ *          data structure. It is valid until any changes are made
+ *          to the geom.
+ * @ingroup collide
+ */
+ODE_API const dReal * dGeomGetOffsetRotation (dGeomID geom);
+
+
+/**
+ * @brief Copy the offset rotation matrix of a geom.
+ *
+ * Returns the rotational offset of the geom in local coordinates.
+ * If the geom has no offset, this function returns the identity
+ * matrix.
+ *
+ * @param geom   the geom to query.
+ * @param R      returns the rotation matrix.
+ * @ingroup collide
+ */
+ODE_API void dGeomCopyOffsetRotation (dGeomID geom, dMatrix3 R);
+
+
+/**
+ * @brief Get the offset rotation quaternion of a geom.
+ *
+ * Returns the rotation offset of the geom as a quaternion.
+ * If the geom has no offset, the identity quaternion is returned.
+ *
+ * @param geom the geom to query.
+ * @param result a copy of the rotation quaternion.
+ * @ingroup collide
+ */
+ODE_API void dGeomGetOffsetQuaternion (dGeomID geom, dQuaternion result);
+
+
+/* ************************************************************************ */
+/* collision detection */
+
+/*
+ *	Just generate any contacts (disables any contact refining).
+ */
+#define CONTACTS_UNIMPORTANT			0x80000000
+
+/**
+ *
+ * @brief Given two geoms o1 and o2 that potentially intersect,
+ * generate contact information for them.
+ *
+ * Internally, this just calls the correct class-specific collision
+ * functions for o1 and o2.
+ *
+ * @param o1 The first geom to test.
+ * @param o2 The second geom to test.
+ *
+ * @param flags The flags specify how contacts should be generated if
+ * the geoms touch. The lower 16 bits of flags is an integer that
+ * specifies the maximum number of contact points to generate. You must
+ * ask for at least one contact. 
+ * Additionally, following bits may be set:
+ * CONTACTS_UNIMPORTANT -- just generate any contacts (skip contact refining).
+ * All other bits in flags must be set to zero. In the future the other bits 
+ * may be used to select from different contact generation strategies.
+ *
+ * @param contact Points to an array of dContactGeom structures. The array
+ * must be able to hold at least the maximum number of contacts. These
+ * dContactGeom structures may be embedded within larger structures in the
+ * array -- the skip parameter is the byte offset from one dContactGeom to
+ * the next in the array. If skip is sizeof(dContactGeom) then contact
+ * points to a normal (C-style) array. It is an error for skip to be smaller
+ * than sizeof(dContactGeom).
+ *
+ * @returns If the geoms intersect, this function returns the number of contact
+ * points generated (and updates the contact array), otherwise it returns 0
+ * (and the contact array is not touched).
+ *
+ * @remarks If a space is passed as o1 or o2 then this function will collide
+ * all objects contained in o1 with all objects contained in o2, and return
+ * the resulting contact points. This method for colliding spaces with geoms
+ * (or spaces with spaces) provides no user control over the individual
+ * collisions. To get that control, use dSpaceCollide or dSpaceCollide2 instead.
+ *
+ * @remarks If o1 and o2 are the same geom then this function will do nothing
+ * and return 0. Technically speaking an object intersects with itself, but it
+ * is not useful to find contact points in this case.
+ *
+ * @remarks This function does not care if o1 and o2 are in the same space or not
+ * (or indeed if they are in any space at all).
+ *
+ * @ingroup collide
+ */
+ODE_API int dCollide (dGeomID o1, dGeomID o2, int flags, dContactGeom *contact,
+	      int skip);
+
+/**
+ * @brief Determines which pairs of geoms in a space may potentially intersect,
+ * and calls the callback function for each candidate pair.
+ *
+ * @param space The space to test.
+ *
+ * @param data Passed from dSpaceCollide directly to the callback
+ * function. Its meaning is user defined. The o1 and o2 arguments are the
+ * geoms that may be near each other.
+ *
+ * @param callback A callback function is of type @ref dNearCallback.
+ *
+ * @remarks Other spaces that are contained within the colliding space are
+ * not treated specially, i.e. they are not recursed into. The callback
+ * function may be passed these contained spaces as one or both geom
+ * arguments.
+ *
+ * @remarks dSpaceCollide() is guaranteed to pass all intersecting geom
+ * pairs to the callback function, but may also pass close but
+ * non-intersecting pairs. The number of these calls depends on the
+ * internal algorithms used by the space. Thus you should not expect
+ * that dCollide will return contacts for every pair passed to the
+ * callback.
+ *
+ * @sa dSpaceCollide2
+ * @ingroup collide
+ */
+ODE_API void dSpaceCollide (dSpaceID space, void *data, dNearCallback *callback);
+
+
+/**
+ * @brief Determines which geoms from one space may potentially intersect with 
+ * geoms from another space, and calls the callback function for each candidate 
+ * pair. 
+ *
+ * @param space1 The first space to test.
+ *
+ * @param space2 The second space to test.
+ *
+ * @param data Passed from dSpaceCollide directly to the callback
+ * function. Its meaning is user defined. The o1 and o2 arguments are the
+ * geoms that may be near each other.
+ *
+ * @param callback A callback function is of type @ref dNearCallback.
+ *
+ * @remarks This function can also test a single non-space geom against a 
+ * space. This function is useful when there is a collision hierarchy, i.e. 
+ * when there are spaces that contain other spaces.
+ *
+ * @remarks Other spaces that are contained within the colliding space are
+ * not treated specially, i.e. they are not recursed into. The callback
+ * function may be passed these contained spaces as one or both geom
+ * arguments.
+ *
+ * @remarks dSpaceCollide2() is guaranteed to pass all intersecting geom
+ * pairs to the callback function, but may also pass close but
+ * non-intersecting pairs. The number of these calls depends on the
+ * internal algorithms used by the space. Thus you should not expect
+ * that dCollide will return contacts for every pair passed to the
+ * callback.
+ *
+ * @sa dSpaceCollide
+ * @ingroup collide
+ */
+ODE_API void dSpaceCollide2 (dGeomID space1, dGeomID space2, void *data, dNearCallback *callback);
+
+
+/* ************************************************************************ */
+/* standard classes */
+
+/* the maximum number of user classes that are supported */
+enum {
+  dMaxUserClasses = 4
+};
+
+/* class numbers - each geometry object needs a unique number */
+enum {
+  dSphereClass = 0,
+  dBoxClass,
+  dCapsuleClass,
+  dCylinderClass,
+  dPlaneClass,
+  dRayClass,
+  dConvexClass,
+  dGeomTransformClass,
+  dTriMeshClass,
+  dHeightfieldClass,
+
+  dFirstSpaceClass,
+  dSimpleSpaceClass = dFirstSpaceClass,
+  dHashSpaceClass,
+  dQuadTreeSpaceClass,
+  dLastSpaceClass = dQuadTreeSpaceClass,
+
+  dFirstUserClass,
+  dLastUserClass = dFirstUserClass + dMaxUserClasses - 1,
+  dGeomNumClasses
+};
+
+
+/**
+ * @defgroup collide_sphere Sphere Class
+ * @ingroup collide
+ */
+
+/**
+ * @brief Create a sphere geom of the given radius, and return its ID. 
+ *
+ * @param space   a space to contain the new geom. May be null.
+ * @param radius  the radius of the sphere.
+ *
+ * @returns A new sphere geom.
+ *
+ * @remarks The point of reference for a sphere is its center.
+ *
+ * @sa dGeomDestroy
+ * @sa dGeomSphereSetRadius
+ * @ingroup collide_sphere
+ */
+ODE_API dGeomID dCreateSphere (dSpaceID space, dReal radius);
+
+
+/**
+ * @brief Set the radius of a sphere geom.
+ *
+ * @param sphere  the sphere to set.
+ * @param radius  the new radius.
+ *
+ * @sa dGeomSphereGetRadius
+ * @ingroup collide_sphere
+ */
+ODE_API void dGeomSphereSetRadius (dGeomID sphere, dReal radius);
+
+
+/**
+ * @brief Retrieves the radius of a sphere geom.
+ *
+ * @param sphere  the sphere to query.
+ *
+ * @sa dGeomSphereSetRadius
+ * @ingroup collide_sphere
+ */
+ODE_API dReal dGeomSphereGetRadius (dGeomID sphere);
+
+
+/**
+ * @brief Calculate the depth of the a given point within a sphere.
+ *
+ * @param sphere  the sphere to query.
+ * @param x       the X coordinate of the point.
+ * @param y       the Y coordinate of the point.
+ * @param z       the Z coordinate of the point.
+ *
+ * @returns The depth of the point. Points inside the sphere will have a 
+ * positive depth, points outside it will have a negative depth, and points
+ * on the surface will have a depth of zero.
+ *
+ * @ingroup collide_sphere
+ */
+ODE_API dReal dGeomSpherePointDepth (dGeomID sphere, dReal x, dReal y, dReal z);
+
+
+//--> Convex Functions
+ODE_API dGeomID dCreateConvex (dSpaceID space,
+			       dReal *_planes,
+			       unsigned int _planecount,
+			       dReal *_points,
+			       unsigned int _pointcount,unsigned int *_polygons);
+
+ODE_API void dGeomSetConvex (dGeomID g,
+			     dReal *_planes,
+			     unsigned int _count,
+			     dReal *_points,
+			     unsigned int _pointcount,unsigned int *_polygons);
+//<-- Convex Functions
+
+/**
+ * @defgroup collide_box Box Class
+ * @ingroup collide
+ */
+
+/**
+ * @brief Create a box geom with the provided side lengths.
+ *
+ * @param space   a space to contain the new geom. May be null.
+ * @param lx      the length of the box along the X axis
+ * @param ly      the length of the box along the Y axis
+ * @param lz      the length of the box along the Z axis
+ *
+ * @returns A new box geom.
+ *
+ * @remarks The point of reference for a box is its center.
+ *
+ * @sa dGeomDestroy
+ * @sa dGeomBoxSetLengths
+ * @ingroup collide_box
+ */
+ODE_API dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz);
+
+
+/**
+ * @brief Set the side lengths of the given box.
+ *
+ * @param box  the box to set
+ * @param lx      the length of the box along the X axis
+ * @param ly      the length of the box along the Y axis
+ * @param lz      the length of the box along the Z axis
+ *
+ * @sa dGeomBoxGetLengths
+ * @ingroup collide_box
+ */
+ODE_API void dGeomBoxSetLengths (dGeomID box, dReal lx, dReal ly, dReal lz);
+
+
+/**
+ * @brief Get the side lengths of a box.
+ *
+ * @param box     the box to query
+ * @param result  the returned side lengths
+ *
+ * @sa dGeomBoxSetLengths
+ * @ingroup collide_box
+ */
+ODE_API void dGeomBoxGetLengths (dGeomID box, dVector3 result);
+
+
+/**
+ * @brief Return the depth of a point in a box.
+ * 
+ * @param box  the box to query
+ * @param x    the X coordinate of the point to test.
+ * @param y    the Y coordinate of the point to test.
+ * @param z    the Z coordinate of the point to test.
+ *
+ * @returns The depth of the point. Points inside the box will have a 
+ * positive depth, points outside it will have a negative depth, and points
+ * on the surface will have a depth of zero.
+ */
+ODE_API dReal dGeomBoxPointDepth (dGeomID box, dReal x, dReal y, dReal z);
+
+
+ODE_API dGeomID dCreatePlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d);
+ODE_API void dGeomPlaneSetParams (dGeomID plane, dReal a, dReal b, dReal c, dReal d);
+ODE_API void dGeomPlaneGetParams (dGeomID plane, dVector4 result);
+ODE_API dReal dGeomPlanePointDepth (dGeomID plane, dReal x, dReal y, dReal z);
+
+ODE_API dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length);
+ODE_API void dGeomCapsuleSetParams (dGeomID ccylinder, dReal radius, dReal length);
+ODE_API void dGeomCapsuleGetParams (dGeomID ccylinder, dReal *radius, dReal *length);
+ODE_API dReal dGeomCapsulePointDepth (dGeomID ccylinder, dReal x, dReal y, dReal z);
+
+// For now we want to have a backwards compatible C-API, note: C++ API is not.
+#define dCreateCCylinder dCreateCapsule
+#define dGeomCCylinderSetParams dGeomCapsuleSetParams
+#define dGeomCCylinderGetParams dGeomCapsuleGetParams
+#define dGeomCCylinderPointDepth dGeomCapsulePointDepth
+#define dCCylinderClass dCapsuleClass
+
+ODE_API dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length);
+ODE_API void dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length);
+ODE_API void dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length);
+
+ODE_API dGeomID dCreateRay (dSpaceID space, dReal length);
+ODE_API void dGeomRaySetLength (dGeomID ray, dReal length);
+ODE_API dReal dGeomRayGetLength (dGeomID ray);
+ODE_API void dGeomRaySet (dGeomID ray, dReal px, dReal py, dReal pz,
+		  dReal dx, dReal dy, dReal dz);
+ODE_API void dGeomRayGet (dGeomID ray, dVector3 start, dVector3 dir);
+
+/*
+ * Set/get ray flags that influence ray collision detection.
+ * These flags are currently only noticed by the trimesh collider, because
+ * they can make a major differences there.
+ */
+ODE_API void dGeomRaySetParams (dGeomID g, int FirstContact, int BackfaceCull);
+ODE_API void dGeomRayGetParams (dGeomID g, int *FirstContact, int *BackfaceCull);
+ODE_API void dGeomRaySetClosestHit (dGeomID g, int closestHit);
+ODE_API int dGeomRayGetClosestHit (dGeomID g);
+
+#include "collision_trimesh.h"
+
+ODE_API dGeomID dCreateGeomTransform (dSpaceID space);
+ODE_API void dGeomTransformSetGeom (dGeomID g, dGeomID obj);
+ODE_API dGeomID dGeomTransformGetGeom (dGeomID g);
+ODE_API void dGeomTransformSetCleanup (dGeomID g, int mode);
+ODE_API int dGeomTransformGetCleanup (dGeomID g);
+ODE_API void dGeomTransformSetInfo (dGeomID g, int mode);
+ODE_API int dGeomTransformGetInfo (dGeomID g);
+
+
+/* ************************************************************************ */
+/* heightfield functions */
+
+
+// Data storage for heightfield data.
+struct dxHeightfieldData;
+typedef struct dxHeightfieldData* dHeightfieldDataID;
+
+
+/**
+ * @brief Callback prototype
+ *
+ * Used by the callback heightfield data type to sample a height for a
+ * given cell position.
+ *
+ * @param p_user_data User data specified when creating the dHeightfieldDataID
+ * @param x The index of a sample in the local x axis. It is a value
+ * in the range zero to ( nWidthSamples - 1 ).
+ * @param x The index of a sample in the local z axis. It is a value
+ * in the range zero to ( nDepthSamples - 1 ).
+ *
+ * @return The sample height which is then scaled and offset using the
+ * values specified when the heightfield data was created.
+ *
+ * @ingroup collide
+ */
+typedef dReal dHeightfieldGetHeight( void* p_user_data, int x, int z );
+
+
+
+/**
+ * @brief Creates a heightfield geom.
+ *
+ * Uses the information in the given dHeightfieldDataID to construct
+ * a geom representing a heightfield in a collision space.
+ *
+ * @param space The space to add the geom to.
+ * @param data The dHeightfieldDataID created by dGeomHeightfieldDataCreate and
+ * setup by dGeomHeightfieldDataBuildCallback, dGeomHeightfieldDataBuildByte,
+ * dGeomHeightfieldDataBuildShort or dGeomHeightfieldDataBuildFloat.
+ * @param bPlaceable If non-zero this geom can be transformed in the world using the
+ * usual functions such as dGeomSetPosition and dGeomSetRotation. If the geom is
+ * not set as placeable, then it uses a fixed orientation where the global y axis
+ * represents the dynamic 'height' of the heightfield.
+ *
+ * @return A geom id to reference this geom in other calls.
+ *
+ * @ingroup collide
+ */
+ODE_API dGeomID dCreateHeightfield( dSpaceID space,
+					dHeightfieldDataID data, int bPlaceable );
+
+
+/**
+ * @brief Creates a new empty dHeightfieldDataID.
+ *
+ * Allocates a new dHeightfieldDataID and returns it. You must call
+ * dGeomHeightfieldDataDestroy to destroy it after the geom has been removed.
+ * The dHeightfieldDataID value is used when specifying a data format type.
+ *
+ * @return A dHeightfieldDataID for use with dGeomHeightfieldDataBuildCallback,
+ * dGeomHeightfieldDataBuildByte, dGeomHeightfieldDataBuildShort or
+ * dGeomHeightfieldDataBuildFloat.
+ * @ingroup collide
+ */
+ODE_API dHeightfieldDataID dGeomHeightfieldDataCreate();
+
+
+/**
+ * @brief Destroys a dHeightfieldDataID.
+ *
+ * Deallocates a given dHeightfieldDataID and all managed resources.
+ *
+ * @param d A dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataDestroy( dHeightfieldDataID d );
+
+
+
+/**
+ * @brief Configures a dHeightfieldDataID to use a callback to
+ * retrieve height data.
+ *
+ * Before a dHeightfieldDataID can be used by a geom it must be
+ * configured to specify the format of the height data.
+ * This call specifies that the heightfield data is computed by
+ * the user and it should use the given callback when determining
+ * the height of a given element of it's shape.
+ *
+ * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ *
+ * @param width Specifies the total 'width' of the heightfield along
+ * the geom's local x axis.
+ * @param depth Specifies the total 'depth' of the heightfield along
+ * the geom's local z axis.
+ *
+ * @param widthSamples Specifies the number of vertices to sample
+ * along the width of the heightfield. Each vertex has a corresponding
+ * height value which forms the overall shape.
+ * Naturally this value must be at least two or more.
+ * @param depthSamples Specifies the number of vertices to sample
+ * along the depth of the heightfield.
+ *
+ * @param scale A uniform scale applied to all raw height data.
+ * @param offset An offset applied to the scaled height data.
+ *
+ * @param thickness A value subtracted from the lowest height
+ * value which in effect adds an additional cuboid to the base of the
+ * heightfield. This is used to prevent geoms from looping under the
+ * desired terrain and not registering as a collision. Note that the
+ * thickness is not affected by the scale or offset parameters.
+ *
+ * @param bWrap If non-zero the heightfield will infinitely tile in both
+ * directions along the local x and z axes. If zero the heightfield is
+ * bounded from zero to width in the local x axis, and zero to depth in
+ * the local z axis.
+ *
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataBuildCallback( dHeightfieldDataID d,
+				void* pUserData, dHeightfieldGetHeight* pCallback,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap );
+
+/**
+ * @brief Configures a dHeightfieldDataID to use height data in byte format.
+ *
+ * Before a dHeightfieldDataID can be used by a geom it must be
+ * configured to specify the format of the height data.
+ * This call specifies that the heightfield data is stored as a rectangular
+ * array of bytes (8 bit unsigned) representing the height at each sample point.
+ *
+ * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ *
+ * @param pHeightData A pointer to the height data.
+ * @param bCopyHeightData When non-zero the height data is copied to an
+ * internal store. When zero the height data is accessed by reference and
+ * so must persist throughout the lifetime of the heightfield.
+ *
+ * @param width Specifies the total 'width' of the heightfield along
+ * the geom's local x axis.
+ * @param depth Specifies the total 'depth' of the heightfield along
+ * the geom's local z axis.
+ *
+ * @param widthSamples Specifies the number of vertices to sample
+ * along the width of the heightfield. Each vertex has a corresponding
+ * height value which forms the overall shape.
+ * Naturally this value must be at least two or more.
+ * @param depthSamples Specifies the number of vertices to sample
+ * along the depth of the heightfield.
+ *
+ * @param scale A uniform scale applied to all raw height data.
+ * @param offset An offset applied to the scaled height data.
+ *
+ * @param thickness A value subtracted from the lowest height
+ * value which in effect adds an additional cuboid to the base of the
+ * heightfield. This is used to prevent geoms from looping under the
+ * desired terrain and not registering as a collision. Note that the
+ * thickness is not affected by the scale or offset parameters.
+ *
+ * @param bWrap If non-zero the heightfield will infinitely tile in both
+ * directions along the local x and z axes. If zero the heightfield is
+ * bounded from zero to width in the local x axis, and zero to depth in
+ * the local z axis.
+ *
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataBuildByte( dHeightfieldDataID d,
+				const unsigned char* pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness,	int bWrap );
+
+/**
+ * @brief Configures a dHeightfieldDataID to use height data in short format.
+ *
+ * Before a dHeightfieldDataID can be used by a geom it must be
+ * configured to specify the format of the height data.
+ * This call specifies that the heightfield data is stored as a rectangular
+ * array of shorts (16 bit signed) representing the height at each sample point.
+ *
+ * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ *
+ * @param pHeightData A pointer to the height data.
+ * @param bCopyHeightData When non-zero the height data is copied to an
+ * internal store. When zero the height data is accessed by reference and
+ * so must persist throughout the lifetime of the heightfield.
+ *
+ * @param width Specifies the total 'width' of the heightfield along
+ * the geom's local x axis.
+ * @param depth Specifies the total 'depth' of the heightfield along
+ * the geom's local z axis.
+ *
+ * @param widthSamples Specifies the number of vertices to sample
+ * along the width of the heightfield. Each vertex has a corresponding
+ * height value which forms the overall shape.
+ * Naturally this value must be at least two or more.
+ * @param depthSamples Specifies the number of vertices to sample
+ * along the depth of the heightfield.
+ *
+ * @param scale A uniform scale applied to all raw height data.
+ * @param offset An offset applied to the scaled height data.
+ *
+ * @param thickness A value subtracted from the lowest height
+ * value which in effect adds an additional cuboid to the base of the
+ * heightfield. This is used to prevent geoms from looping under the
+ * desired terrain and not registering as a collision. Note that the
+ * thickness is not affected by the scale or offset parameters.
+ *
+ * @param bWrap If non-zero the heightfield will infinitely tile in both
+ * directions along the local x and z axes. If zero the heightfield is
+ * bounded from zero to width in the local x axis, and zero to depth in
+ * the local z axis.
+ *
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataBuildShort( dHeightfieldDataID d,
+				const short* pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap );
+
+/**
+ * @brief Configures a dHeightfieldDataID to use height data in 
+ * single precision floating point format.
+ *
+ * Before a dHeightfieldDataID can be used by a geom it must be
+ * configured to specify the format of the height data.
+ * This call specifies that the heightfield data is stored as a rectangular
+ * array of single precision floats representing the height at each
+ * sample point.
+ *
+ * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ *
+ * @param pHeightData A pointer to the height data.
+ * @param bCopyHeightData When non-zero the height data is copied to an
+ * internal store. When zero the height data is accessed by reference and
+ * so must persist throughout the lifetime of the heightfield.
+ *
+ * @param width Specifies the total 'width' of the heightfield along
+ * the geom's local x axis.
+ * @param depth Specifies the total 'depth' of the heightfield along
+ * the geom's local z axis.
+ *
+ * @param widthSamples Specifies the number of vertices to sample
+ * along the width of the heightfield. Each vertex has a corresponding
+ * height value which forms the overall shape.
+ * Naturally this value must be at least two or more.
+ * @param depthSamples Specifies the number of vertices to sample
+ * along the depth of the heightfield.
+ *
+ * @param scale A uniform scale applied to all raw height data.
+ * @param offset An offset applied to the scaled height data.
+ *
+ * @param thickness A value subtracted from the lowest height
+ * value which in effect adds an additional cuboid to the base of the
+ * heightfield. This is used to prevent geoms from looping under the
+ * desired terrain and not registering as a collision. Note that the
+ * thickness is not affected by the scale or offset parameters.
+ *
+ * @param bWrap If non-zero the heightfield will infinitely tile in both
+ * directions along the local x and z axes. If zero the heightfield is
+ * bounded from zero to width in the local x axis, and zero to depth in
+ * the local z axis.
+ *
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataBuildSingle( dHeightfieldDataID d,
+				const float* pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap );
+
+/**
+ * @brief Configures a dHeightfieldDataID to use height data in 
+ * double precision floating point format.
+ *
+ * Before a dHeightfieldDataID can be used by a geom it must be
+ * configured to specify the format of the height data.
+ * This call specifies that the heightfield data is stored as a rectangular
+ * array of double precision floats representing the height at each
+ * sample point.
+ *
+ * @param d A new dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ *
+ * @param pHeightData A pointer to the height data.
+ * @param bCopyHeightData When non-zero the height data is copied to an
+ * internal store. When zero the height data is accessed by reference and
+ * so must persist throughout the lifetime of the heightfield.
+ *
+ * @param width Specifies the total 'width' of the heightfield along
+ * the geom's local x axis.
+ * @param depth Specifies the total 'depth' of the heightfield along
+ * the geom's local z axis.
+ *
+ * @param widthSamples Specifies the number of vertices to sample
+ * along the width of the heightfield. Each vertex has a corresponding
+ * height value which forms the overall shape.
+ * Naturally this value must be at least two or more.
+ * @param depthSamples Specifies the number of vertices to sample
+ * along the depth of the heightfield.
+ *
+ * @param scale A uniform scale applied to all raw height data.
+ * @param offset An offset applied to the scaled height data.
+ *
+ * @param thickness A value subtracted from the lowest height
+ * value which in effect adds an additional cuboid to the base of the
+ * heightfield. This is used to prevent geoms from looping under the
+ * desired terrain and not registering as a collision. Note that the
+ * thickness is not affected by the scale or offset parameters.
+ *
+ * @param bWrap If non-zero the heightfield will infinitely tile in both
+ * directions along the local x and z axes. If zero the heightfield is
+ * bounded from zero to width in the local x axis, and zero to depth in
+ * the local z axis.
+ *
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataBuildDouble( dHeightfieldDataID d,
+				const double* pHeightData, int bCopyHeightData,
+				dReal width, dReal depth, int widthSamples, int depthSamples,
+				dReal scale, dReal offset, dReal thickness, int bWrap );
+
+/**
+ * @brief Manually set the minimum and maximum height bounds.
+ *
+ * This call allows you to set explicit min / max values after initial
+ * creation typically for callback heightfields which default to +/- infinity,
+ * or those whose data has changed. This must be set prior to binding with a
+ * geom, as the the AABB is not recomputed after it's first generation.
+ *
+ * @remarks The minimum and maximum values are used to compute the AABB
+ * for the heightfield which is used for early rejection of collisions.
+ * A close fit will yield a more efficient collision check.
+ *
+ * @param d A dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ * @param min_height The new minimum height value. Scale, offset and thickness is then applied.
+ * @param max_height The new maximum height value. Scale and offset is then applied.
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldDataSetBounds( dHeightfieldDataID d,
+				dReal minHeight, dReal maxHeight );
+
+
+/**
+ * @brief Assigns a dHeightfieldDataID to a heightfield geom.
+ *
+ * Associates the given dHeightfieldDataID with a heightfield geom.
+ * This is done without affecting the GEOM_PLACEABLE flag.
+ *
+ * @param g A geom created by dCreateHeightfield
+ * @param d A dHeightfieldDataID created by dGeomHeightfieldDataCreate
+ * @ingroup collide
+ */
+ODE_API void dGeomHeightfieldSetHeightfieldData( dGeomID g, dHeightfieldDataID d );
+
+
+/**
+ * @brief Gets the dHeightfieldDataID bound to a heightfield geom.
+ *
+ * Returns the dHeightfieldDataID associated with a heightfield geom.
+ *
+ * @param g A geom created by dCreateHeightfield
+ * @return The dHeightfieldDataID which may be NULL if none was assigned.
+ * @ingroup collide
+ */
+ODE_API dHeightfieldDataID dGeomHeightfieldGetHeightfieldData( dGeomID g );
+
+
+
+/* ************************************************************************ */
+/* utility functions */
+
+ODE_API void dClosestLineSegmentPoints (const dVector3 a1, const dVector3 a2,
+				const dVector3 b1, const dVector3 b2,
+				dVector3 cp1, dVector3 cp2);
+
+ODE_API int dBoxTouchesBox (const dVector3 _p1, const dMatrix3 R1,
+		    const dVector3 side1, const dVector3 _p2,
+		    const dMatrix3 R2, const dVector3 side2);
+
+// The meaning of flags parameter is the same as in dCollide()
+ODE_API int dBoxBox (const dVector3 p1, const dMatrix3 R1,
+	     const dVector3 side1, const dVector3 p2,
+	     const dMatrix3 R2, const dVector3 side2,
+	     dVector3 normal, dReal *depth, int *return_code,
+	     int flags, dContactGeom *contact, int skip);
+
+ODE_API void dInfiniteAABB (dGeomID geom, dReal aabb[6]);
+ODE_API void dInitODE(void);
+ODE_API void dCloseODE(void);
+
+/* ************************************************************************ */
+/* custom classes */
+
+typedef void dGetAABBFn (dGeomID, dReal aabb[6]);
+typedef int dColliderFn (dGeomID o1, dGeomID o2,
+			 int flags, dContactGeom *contact, int skip);
+typedef dColliderFn * dGetColliderFnFn (int num);
+typedef void dGeomDtorFn (dGeomID o);
+typedef int dAABBTestFn (dGeomID o1, dGeomID o2, dReal aabb[6]);
+
+typedef struct dGeomClass {
+  int bytes;
+  dGetColliderFnFn *collider;
+  dGetAABBFn *aabb;
+  dAABBTestFn *aabb_test;
+  dGeomDtorFn *dtor;
+} dGeomClass;
+
+ODE_API int dCreateGeomClass (const dGeomClass *classptr);
+ODE_API void * dGeomGetClassData (dGeomID);
+ODE_API dGeomID dCreateGeom (int classnum);
+
+/* ************************************************************************ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/collision_space.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/collision_space.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/collision_space.h	(revision 216)
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_COLLISION_SPACE_H_
+#define _ODE_COLLISION_SPACE_H_
+
+#include <ode/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dContactGeom;
+
+/**
+ * @brief User callback for geom-geom collision testing.
+ *
+ * @param data The user data object, as passed to dSpaceCollide.
+ * @param o1   The first geom being tested.
+ * @param o2   The second geom being test.
+ *
+ * @remarks The callback function can call dCollide on o1 and o2 to generate 
+ * contact points between each pair. Then these contact points may be added 
+ * to the simulation as contact joints. The user's callback function can of 
+ * course chose not to call dCollide for any pair, e.g. if the user decides 
+ * that those pairs should not interact.
+ *
+ * @ingroup collide
+ */
+typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2);
+
+
+ODE_API dSpaceID dSimpleSpaceCreate (dSpaceID space);
+ODE_API dSpaceID dHashSpaceCreate (dSpaceID space);
+ODE_API dSpaceID dQuadTreeSpaceCreate (dSpaceID space, dVector3 Center, dVector3 Extents, int Depth);
+
+ODE_API void dSpaceDestroy (dSpaceID);
+
+ODE_API void dHashSpaceSetLevels (dSpaceID space, int minlevel, int maxlevel);
+ODE_API void dHashSpaceGetLevels (dSpaceID space, int *minlevel, int *maxlevel);
+
+ODE_API void dSpaceSetCleanup (dSpaceID space, int mode);
+ODE_API int dSpaceGetCleanup (dSpaceID space);
+
+ODE_API void dSpaceAdd (dSpaceID, dGeomID);
+ODE_API void dSpaceRemove (dSpaceID, dGeomID);
+ODE_API int dSpaceQuery (dSpaceID, dGeomID);
+ODE_API void dSpaceClean (dSpaceID);
+ODE_API int dSpaceGetNumGeoms (dSpaceID);
+ODE_API dGeomID dSpaceGetGeom (dSpaceID, int i);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/collision_trimesh.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/collision_trimesh.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/collision_trimesh.h	(revision 216)
@@ -0,0 +1,205 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+ * TriMesh code by Erwin de Vries.
+ *
+ * Trimesh data.
+ * This is where the actual vertexdata (pointers), and BV tree is stored.
+ * Vertices should be single precision!
+ * This should be more sophisticated, so that the user can easyly implement
+ * another collision library, but this is a lot of work, and also costs some
+ * performance because some data has to be copied.
+ */
+
+#ifndef _ODE_COLLISION_TRIMESH_H_
+#define _ODE_COLLISION_TRIMESH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Data storage for triangle meshes.
+ */
+struct dxTriMeshData;
+typedef struct dxTriMeshData* dTriMeshDataID;
+
+/*
+ * These dont make much sense now, but they will later when we add more
+ * features.
+ */
+ODE_API dTriMeshDataID dGeomTriMeshDataCreate(void);
+ODE_API void dGeomTriMeshDataDestroy(dTriMeshDataID g);
+
+
+
+enum { TRIMESH_FACE_NORMALS };
+ODE_API void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void* in_data);
+ODE_API void* dGeomTriMeshDataGet(dTriMeshDataID g, int data_id);
+
+
+
+/**
+ * We need to set the last transform after each time step for 
+ * accurate collision response. These functions get and set that transform.
+ * It is stored per geom instance, rather than per dTriMeshDataID.
+ */
+ODE_API void dGeomTriMeshSetLastTransform( dGeomID g, dMatrix4 last_trans );
+ODE_API dReal* dGeomTriMeshGetLastTransform( dGeomID g );
+
+/*
+ * Build TriMesh data with single precision used in vertex data .
+ */
+ODE_API void dGeomTriMeshDataBuildSingle(dTriMeshDataID g,
+                                 const void* Vertices, int VertexStride, int VertexCount, 
+                                 const void* Indices, int IndexCount, int TriStride);
+/* same again with a normals array (used as trimesh-trimesh optimization) */
+ODE_API void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g,
+                                  const void* Vertices, int VertexStride, int VertexCount, 
+                                  const void* Indices, int IndexCount, int TriStride,
+                                  const void* Normals);
+/*
+* Build TriMesh data with double pricision used in vertex data .
+*/
+ODE_API void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, 
+                                 const void* Vertices,  int VertexStride, int VertexCount, 
+                                 const void* Indices, int IndexCount, int TriStride);
+/* same again with a normals array (used as trimesh-trimesh optimization) */
+ODE_API void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g, 
+                                  const void* Vertices,  int VertexStride, int VertexCount, 
+                                  const void* Indices, int IndexCount, int TriStride,
+                                  const void* Normals);
+
+/*
+ * Simple build. Single/double precision based on dSINGLE/dDOUBLE!
+ */
+ODE_API void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
+                                 const dReal* Vertices, int VertexCount,
+                                 const int* Indices, int IndexCount);
+/* same again with a normals array (used as trimesh-trimesh optimization) */
+ODE_API void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g,
+                                  const dReal* Vertices, int VertexCount,
+                                  const int* Indices, int IndexCount,
+                                  const int* Normals);
+
+/* Preprocess the trimesh data to remove mark unnecessary edges and vertices */
+ODE_API void dGeomTriMeshDataPreprocess(dTriMeshDataID g);
+/* Get and set the internal preprocessed trimesh data buffer, for loading and saving */
+ODE_API void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char** buf, int* bufLen);
+ODE_API void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf);
+
+
+/*
+ * Per triangle callback. Allows the user to say if he wants a collision with
+ * a particular triangle.
+ */
+typedef int dTriCallback(dGeomID TriMesh, dGeomID RefObject, int TriangleIndex);
+ODE_API void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback);
+ODE_API dTriCallback* dGeomTriMeshGetCallback(dGeomID g);
+
+/*
+ * Per object callback. Allows the user to get the list of triangles in 1
+ * shot. Maybe we should remove this one.
+ */
+typedef void dTriArrayCallback(dGeomID TriMesh, dGeomID RefObject, const int* TriIndices, int TriCount);
+ODE_API void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback);
+ODE_API dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g);
+
+/*
+ * Ray callback.
+ * Allows the user to say if a ray collides with a triangle on barycentric
+ * coords. The user can for example sample a texture with alpha transparency
+ * to determine if a collision should occur.
+ */
+typedef int dTriRayCallback(dGeomID TriMesh, dGeomID Ray, int TriangleIndex, dReal u, dReal v);
+ODE_API void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback);
+ODE_API dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g);
+
+/*
+ * Trimesh class
+ * Construction. Callbacks are optional.
+ */
+ODE_API dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback);
+
+ODE_API void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data);
+ODE_API dTriMeshDataID dGeomTriMeshGetData(dGeomID g);
+
+
+// enable/disable/check temporal coherence
+ODE_API void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable);
+ODE_API int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass);
+
+/*
+ * Clears the internal temporal coherence caches. When a geom has its
+ * collision checked with a trimesh once, data is stored inside the trimesh.
+ * With large worlds with lots of seperate objects this list could get huge.
+ * We should be able to do this automagically.
+ */
+ODE_API void dGeomTriMeshClearTCCache(dGeomID g);
+
+
+/*
+ * returns the TriMeshDataID
+ */
+ODE_API dTriMeshDataID dGeomTriMeshGetTriMeshDataID(dGeomID g);
+
+/*
+ * Gets a triangle.
+ */
+ODE_API void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2);
+
+/*
+ * Gets the point on the requested triangle and the given barycentric
+ * coordinates.
+ */
+ODE_API void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out);
+
+/*
+
+This is how the strided data works:
+
+struct StridedVertex{
+	dVector3 Vertex;
+	// Userdata
+};
+int VertexStride = sizeof(StridedVertex);
+
+struct StridedTri{
+	int Indices[3];
+	// Userdata
+};
+int TriStride = sizeof(StridedTri);
+
+*/
+
+
+ODE_API int dGeomTriMeshGetTriangleCount (dGeomID g);
+
+ODE_API void dGeomTriMeshDataUpdate(dTriMeshDataID g);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _ODE_COLLISION_TRIMESH_H_ */
+
Index: /code/branches/ode/ode-0.9/include/ode/common.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/common.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/common.h	(revision 216)
@@ -0,0 +1,388 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_COMMON_H_
+#define _ODE_COMMON_H_
+#include <ode/config.h>
+#include <ode/error.h>
+#include <math.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* configuration stuff */
+
+/* the efficient alignment. most platforms align data structures to some
+ * number of bytes, but this is not always the most efficient alignment.
+ * for example, many x86 compilers align to 4 bytes, but on a pentium it
+ * is important to align doubles to 8 byte boundaries (for speed), and
+ * the 4 floats in a SIMD register to 16 byte boundaries. many other
+ * platforms have similar behavior. setting a larger alignment can waste
+ * a (very) small amount of memory. NOTE: this number must be a power of
+ * two. this is set to 16 by default.
+ */
+#define EFFICIENT_ALIGNMENT 16
+
+
+/* constants */
+
+/* pi and 1/sqrt(2) are defined here if necessary because they don't get
+ * defined in <math.h> on some platforms (like MS-Windows)
+ */
+
+#ifndef M_PI
+#define M_PI REAL(3.1415926535897932384626433832795029)
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 REAL(0.7071067811865475244008443621048490)
+#endif
+
+
+/* debugging:
+ *   IASSERT  is an internal assertion, i.e. a consistency check. if it fails
+ *            we want to know where.
+ *   UASSERT  is a user assertion, i.e. if it fails a nice error message
+ *            should be printed for the user.
+ *   AASSERT  is an arguments assertion, i.e. if it fails "bad argument(s)"
+ *            is printed.
+ *   DEBUGMSG just prints out a message
+ */
+
+#ifndef dNODEBUG
+#ifdef __GNUC__
+#define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \
+  "assertion \"" #a "\" failed in %s() [%s]",__FUNCTION__,__FILE__);
+#define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \
+  msg " in %s()", __FUNCTION__);
+#define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT,				\
+msg " in %s() File %s Line %d", __FUNCTION__, __FILE__,__LINE__);
+#else
+#define dIASSERT(a) if (!(a)) dDebug (d_ERR_IASSERT, \
+  "assertion \"" #a "\" failed in %s:%d",__FILE__,__LINE__);
+#define dUASSERT(a,msg) if (!(a)) dDebug (d_ERR_UASSERT, \
+  msg " (%s:%d)", __FILE__,__LINE__);
+#define dDEBUGMSG(msg) dMessage (d_ERR_UASSERT, \
+  msg " (%s:%d)", __FILE__,__LINE__);
+#endif
+#else
+#define dIASSERT(a) ;
+#define dUASSERT(a,msg) ;
+#define dDEBUGMSG(msg) ;
+#endif
+#define dAASSERT(a) dUASSERT(a,"Bad argument(s)")
+
+// Macro used to suppress unused variable warning
+#define dVARIABLEUSED(a) ((void)a)
+
+/* floating point data type, vector, matrix and quaternion types */
+
+#if defined(dSINGLE)
+typedef float dReal;
+#ifdef dDOUBLE
+#error You can only #define dSINGLE or dDOUBLE, not both.
+#endif // dDOUBLE
+#elif defined(dDOUBLE)
+typedef double dReal;
+#else
+#error You must #define dSINGLE or dDOUBLE
+#endif
+
+// Detect if we've got both trimesh engines enabled.
+#if dTRIMESH_ENABLED
+#if dTRIMESH_OPCODE && dTRIMESH_GIMPACT
+#error You can only #define dTRIMESH_OPCODE or dTRIMESH_GIMPACT, not both.
+#endif
+#endif // dTRIMESH_ENABLED
+
+/* round an integer up to a multiple of 4, except that 0 and 1 are unmodified
+ * (used to compute matrix leading dimensions)
+ */
+#define dPAD(a) (((a) > 1) ? ((((a)-1)|3)+1) : (a))
+
+/* these types are mainly just used in headers */
+typedef dReal dVector3[4];
+typedef dReal dVector4[4];
+typedef dReal dMatrix3[4*3];
+typedef dReal dMatrix4[4*4];
+typedef dReal dMatrix6[8*6];
+typedef dReal dQuaternion[4];
+
+
+/* precision dependent scalar math functions */
+
+#if defined(dSINGLE)
+
+#define REAL(x) (x ## f)					/* form a constant */
+#define dRecip(x) ((1.0f/(x)))				/* reciprocal */
+#define dSqrt(x) (sqrtf(x))			/* square root */
+#define dRecipSqrt(x) ((1.0f/sqrtf(x)))		/* reciprocal square root */
+#define dSin(x) (sinf(x))				/* sine */
+#define dCos(x) (cosf(x))				/* cosine */
+#define dFabs(x) (fabsf(x))			/* absolute value */
+#define dAtan2(y,x) (atan2f(y,x))		/* arc tangent with 2 args */
+#define dFMod(a,b) (fmodf(a,b))		/* modulo */
+#define dFloor(x) floorf(x)			/* floor */
+
+#ifdef HAVE___ISNANF
+#define dIsNan(x) (__isnanf(x))
+#elif defined(HAVE__ISNANF)
+#define dIsNan(x) (_isnanf(x))
+#elif defined(HAVE_ISNANF)
+#define dIsNan(x) (isnanf(x))
+#else
+  /*
+     fall back to _isnan which is the VC way,
+     this may seem redundant since we already checked
+     for _isnan before, but if isnan is detected by
+     configure but is not found during compilation
+     we should always make sure we check for __isnanf,
+     _isnanf and isnanf in that order before falling
+     back to a default
+  */
+#define dIsNan(x) (_isnan(x))
+#endif
+
+#define dCopySign(a,b) ((dReal)copysignf(a,b))
+
+#elif defined(dDOUBLE)
+
+#define REAL(x) (x)
+#define dRecip(x) (1.0/(x))
+#define dSqrt(x) sqrt(x)
+#define dRecipSqrt(x) (1.0/sqrt(x))
+#define dSin(x) sin(x)
+#define dCos(x) cos(x)
+#define dFabs(x) fabs(x)
+#define dAtan2(y,x) atan2((y),(x))
+#define dFMod(a,b) (fmod((a),(b)))
+#define dFloor(x) floor(x)
+
+#ifdef HAVE___ISNAN
+#define dIsNan(x) (__isnan(x))
+#elif defined(HAVE__ISNAN)
+#define dIsNan(x) (_isnan(x))
+#elif defined(HAVE_ISNAN)
+#define dIsNan(x) (isnan(x))
+#else
+#define dIsNan(x) (_isnan(x))
+#endif
+
+#define dCopySign(a,b) (copysign((a),(b)))
+
+#else
+#error You must #define dSINGLE or dDOUBLE
+#endif
+
+
+/* utility */
+
+
+/* round something up to be a multiple of the EFFICIENT_ALIGNMENT */
+
+#define dEFFICIENT_SIZE(x) ((((x)-1)|(EFFICIENT_ALIGNMENT-1))+1)
+
+
+/* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste
+ * up to 15 bytes per allocation, depending on what alloca() returns.
+ */
+
+#define dALLOCA16(n) \
+  ((char*)dEFFICIENT_SIZE(((size_t)(alloca((n)+(EFFICIENT_ALIGNMENT-1))))))
+
+
+// Use the error-checking memory allocation system.  Because this system uses heap
+//  (malloc) instead of stack (alloca), it is slower.  However, it allows you to
+//  simulate larger scenes, as well as handle out-of-memory errors in a somewhat
+//  graceful manner
+
+// #define dUSE_MALLOC_FOR_ALLOCA
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+enum {
+  d_MEMORY_OK = 0,		/* no memory errors */
+  d_MEMORY_OUT_OF_MEMORY	/* malloc failed due to out of memory error */
+};
+
+#endif
+
+
+
+/* internal object types (all prefixed with `dx') */
+
+struct dxWorld;		/* dynamics world */
+struct dxSpace;		/* collision space */
+struct dxBody;		/* rigid body (dynamics object) */
+struct dxGeom;		/* geometry (collision object) */
+struct dxJoint;
+struct dxJointNode;
+struct dxJointGroup;
+
+typedef struct dxWorld *dWorldID;
+typedef struct dxSpace *dSpaceID;
+typedef struct dxBody *dBodyID;
+typedef struct dxGeom *dGeomID;
+typedef struct dxJoint *dJointID;
+typedef struct dxJointGroup *dJointGroupID;
+
+
+/* error numbers */
+
+enum {
+  d_ERR_UNKNOWN = 0,		/* unknown error */
+  d_ERR_IASSERT,		/* internal assertion failed */
+  d_ERR_UASSERT,		/* user assertion failed */
+  d_ERR_LCP			/* user assertion failed */
+};
+
+
+/* joint type numbers */
+
+enum {
+  dJointTypeNone = 0,		/* or "unknown" */
+  dJointTypeBall,
+  dJointTypeHinge,
+  dJointTypeSlider,
+  dJointTypeContact,
+  dJointTypeUniversal,
+  dJointTypeHinge2,
+  dJointTypeFixed,
+  dJointTypeNull,
+  dJointTypeAMotor,
+  dJointTypeLMotor,
+  dJointTypePlane2D,
+  dJointTypePR
+};
+
+
+/* an alternative way of setting joint parameters, using joint parameter
+ * structures and member constants. we don't actually do this yet.
+ */
+
+/*
+typedef struct dLimot {
+  int mode;
+  dReal lostop, histop;
+  dReal vel, fmax;
+  dReal fudge_factor;
+  dReal bounce, soft;
+  dReal suspension_erp, suspension_cfm;
+} dLimot;
+
+enum {
+  dLimotLoStop		= 0x0001,
+  dLimotHiStop		= 0x0002,
+  dLimotVel		= 0x0004,
+  dLimotFMax		= 0x0008,
+  dLimotFudgeFactor	= 0x0010,
+  dLimotBounce		= 0x0020,
+  dLimotSoft		= 0x0040
+};
+*/
+
+
+/* standard joint parameter names. why are these here? - because we don't want
+ * to include all the joint function definitions in joint.cpp. hmmmm.
+ * MSVC complains if we call D_ALL_PARAM_NAMES_X with a blank second argument,
+ * which is why we have the D_ALL_PARAM_NAMES macro as well. please copy and
+ * paste between these two.
+ */
+
+#define D_ALL_PARAM_NAMES(start) \
+  /* parameters for limits and motors */ \
+  dParamLoStop = start, \
+  dParamHiStop, \
+  dParamVel, \
+  dParamFMax, \
+  dParamFudgeFactor, \
+  dParamBounce, \
+  dParamCFM, \
+  dParamStopERP, \
+  dParamStopCFM, \
+  /* parameters for suspension */ \
+  dParamSuspensionERP, \
+  dParamSuspensionCFM, \
+  dParamERP, \
+
+#define D_ALL_PARAM_NAMES_X(start,x) \
+  /* parameters for limits and motors */ \
+  dParamLoStop ## x = start, \
+  dParamHiStop ## x, \
+  dParamVel ## x, \
+  dParamFMax ## x, \
+  dParamFudgeFactor ## x, \
+  dParamBounce ## x, \
+  dParamCFM ## x, \
+  dParamStopERP ## x, \
+  dParamStopCFM ## x, \
+  /* parameters for suspension */ \
+  dParamSuspensionERP ## x, \
+  dParamSuspensionCFM ## x, \
+  dParamERP ## x,
+
+enum {
+  D_ALL_PARAM_NAMES(0)
+  D_ALL_PARAM_NAMES_X(0x100,2)
+  D_ALL_PARAM_NAMES_X(0x200,3)
+
+  /* add a multiple of this constant to the basic parameter numbers to get
+   * the parameters for the second, third etc axes.
+   */
+  dParamGroup=0x100
+};
+
+
+/* angular motor mode numbers */
+
+enum{
+  dAMotorUser = 0,
+  dAMotorEuler = 1
+};
+
+
+/* joint force feedback information */
+
+typedef struct dJointFeedback {
+  dVector3 f1;		/* force applied to body 1 */
+  dVector3 t1;		/* torque applied to body 1 */
+  dVector3 f2;		/* force applied to body 2 */
+  dVector3 t2;		/* torque applied to body 2 */
+} dJointFeedback;
+
+
+/* private functions that must be implemented by the collision library:
+ * (1) indicate that a geom has moved, (2) get the next geom in a body list.
+ * these functions are called whenever the position of geoms connected to a
+ * body have changed, e.g. with dBodySetPosition(), dBodySetRotation(), or
+ * when the ODE step function updates the body state.
+ */
+
+void dGeomMoved (dGeomID);
+dGeomID dGeomGetBodyNext (dGeomID);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/compatibility.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/compatibility.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/compatibility.h	(revision 216)
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_COMPATIBILITY_H_
+#define _ODE_COMPATIBILITY_H_
+
+/*
+ * ODE's backward compatibility system ensures that as ODE's API
+ * evolves, user code will not break.
+ */
+
+/*
+ * These new rotation function names are more consistent with the
+ * rest of the API.
+ */
+#define dQtoR(q,R) dRfromQ((R),(q))
+#define dRtoQ(R,q) dQfromR((q),(R))
+#define dWtoDQ(w,q,dq) dDQfromW((dq),(w),(q))
+
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/config.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/config.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/config.h	(revision 216)
@@ -0,0 +1,176 @@
+/* This file was autogenerated by Premake */
+#ifndef _ODE_CONFIG_H_
+#define _ODE_CONFIG_H_
+
+
+/******************************************************************
+ * CONFIGURATON SETTINGS - you can change these, and then rebuild
+ *   ODE to modify the behavior of the library.
+ *
+ *   dSINGLE/dDOUBLE   - force ODE to use single-precision (float)
+ *                       or double-precision (double) for numbers.
+ *                       Only one should be defined.
+ *
+ *   dTRIMESH_ENABLED  - enable/disable trimesh support
+ *   dTRIMESH_OPCODE   - use the OPCODE trimesh engine
+ *   dTRIMESH_GIMPACT  - use the GIMPACT trimesh engine
+ *                       Only one trimesh engine should be enabled.
+ *
+ *   dUSE_MALLOC_FOR_ALLOCA (experimental)-
+ *                       Use malloc() instead of alloca(). Slower,
+ *                       but allows for larger systems and more
+ *                       graceful out-of-memory handling.
+ *
+ *   dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER (experimental)-
+ *                       Use an alternative trimesh-trimesh collider
+ *                       which should yield better results.
+ *
+ ******************************************************************/
+
+#define dSINGLE
+/* #define dDOUBLE */
+
+#define dTRIMESH_ENABLED 1
+#define dTRIMESH_OPCODE 1
+
+#define dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER 0
+
+/* #define dUSE_MALLOC_FOR_ALLOCA */
+
+
+/******************************************************************
+ * SYSTEM SETTINGS - you shouldn't need to change these. If you
+ *   run into an issue with these settings, please report it to
+ *   the ODE bug tracker at:
+ *      http://sf.net/tracker/?group_id=24884&atid=382799
+ ******************************************************************/
+
+/* Try to identify the platform */
+#if defined(_XENON)
+  #define ODE_PLATFORM_XBOX360
+#elif defined(SN_TARGET_PSP_HW)
+  #define ODE_PLATFORM_PSP
+#elif defined(SN_TARGET_PS3)
+  #define ODE_PLATFORM_PS3
+#elif defined(_MSC_VER) || defined(__CYGWIN32__) || defined(__MINGW32__)
+  #define ODE_PLATFORM_WINDOWS
+#elif defined(__linux__)
+  #define ODE_PLATFORM_LINUX
+#elif defined(__APPLE__) && defined(__MACH__)
+  #define ODE_PLATFORM_OSX
+#else
+  #error "Need some help identifying the platform!"
+#endif
+
+/* Additional platform defines used in the code */
+#if defined(ODE_PLATFORM_WINDOWS) && !defined(WIN32)
+  #define WIN32
+#endif
+
+#if defined(__CYGWIN32__) || defined(__MINGW32__)
+  #define CYGWIN
+#endif
+
+#if defined(ODE_PLATFORM_OSX)
+  #define macintosh
+#endif
+
+
+/* Define a DLL export symbol for those platforms that need it */
+#if defined(ODE_PLATFORM_WINDOWS)
+  #if defined(ODE_DLL)
+    #define ODE_API __declspec(dllexport)
+  #elif !defined(ODE_LIB)
+    #define ODE_DLL_API __declspec(dllimport)
+  #endif
+#endif
+
+#if !defined(ODE_API)
+  #define ODE_API
+#endif
+
+
+/* Pull in the standard headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <math.h>
+#include <string.h>
+#include <float.h>
+
+#if !defined(ODE_PLATFORM_PS3)
+  #include <malloc.h>
+#endif
+
+#if !defined(ODE_PLATFORM_WINDOWS)
+  #include <alloca.h>
+#endif
+
+
+/* Visual C does not define these functions */
+#if defined(_MSC_VER)
+  #define copysignf _copysign
+  #define copysign _copysign
+#endif
+
+
+/* Define a value for infinity */
+#if defined(HUGE_VALF)
+	#define ODE_INFINITY4 HUGE_VALF
+	#define ODE_INFINITY8 HUGE_VAL
+#elif defined(FLT_MAX)
+	#define ODE_INFINITY4 FLT_MAX
+	#define ODE_INFINITY8 DBL_MAX
+#else
+	static union { unsigned char __c[4]; float  __f; }  __ode_huge_valf = {{0,0,0x80,0x7f}};
+	static union { unsigned char __c[8]; double __d; }  __ode_huge_val  = {{0,0,0,0,0,0,0xf0,0x7f}};
+	#define ODE_INFINITY4 (__ode_huge_valf.__f)
+	#define ODE_INFINITY8 (__ode_huge_val.__d)
+#endif
+
+#ifdef dSINGLE
+	#define dInfinity ODE_INFINITY4
+	#define dEpsilon  FLT_EPSILON
+#else
+	#define dInfinity ODE_INFINITY8
+	#define dEpsilon  DBL_EPSILON
+#endif
+
+
+/* Well-defined common data types...need to define for 64 bit systems */
+#if defined(_M_IA64) || defined(__ia64__) || defined(_M_AMD64) || defined(__x86_64__)
+  #define X86_64_SYSTEM   1
+  typedef int             int32;
+  typedef unsigned int    uint32;
+  typedef short           int16;
+  typedef unsigned short  uint16;
+  typedef char            int8;
+  typedef unsigned char   uint8;
+#else
+  typedef int             int32;
+  typedef unsigned int    uint32;
+  typedef short           int16;
+  typedef unsigned short  uint16;
+  typedef char            int8;
+  typedef unsigned char   uint8;
+#endif
+
+/* An integer type that can be safely cast to a pointer. This definition
+ * should be safe even on 64-bit systems */
+typedef size_t intP;
+
+
+/* The efficient alignment. most platforms align data structures to some
+ * number of bytes, but this is not always the most efficient alignment.
+ * for example, many x86 compilers align to 4 bytes, but on a pentium it is
+ * important to align doubles to 8 byte boundaries (for speed), and the 4
+ * floats in a SIMD register to 16 byte boundaries. many other platforms have
+ * similar behavior. setting a larger alignment can waste a (very) small
+ * amount of memory. NOTE: this number must be a power of two. */
+#define EFFICIENT_ALIGNMENT 16
+
+
+/* Define this if your system supports anonymous memory maps (linux does) */
+#define MMAP_ANONYMOUS
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/config.h.in
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/config.h.in	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/config.h.in	(revision 216)
@@ -0,0 +1,377 @@
+/* include/ode/config.h.in.  Generated from configure.in by autoheader.  */
+
+
+#ifndef ODE_CONFIG_H
+#define ODE_CONFIG_H
+
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Use the Apple OpenGL framework. */
+#undef HAVE_APPLE_OPENGL_FRAMEWORK
+
+/* Define to 1 if you have the `atan2f' function. */
+#undef HAVE_ATAN2F
+
+/* Define to 1 if you have the `copysign' function. */
+#undef HAVE_COPYSIGN
+
+/* Define to 1 if you have the `copysignf' function. */
+#undef HAVE_COPYSIGNF
+
+/* Define to 1 if you have the `cosf' function. */
+#undef HAVE_COSF
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the `fabsf' function. */
+#undef HAVE_FABSF
+
+/* Define to 1 if you have the <float.h> header file. */
+#undef HAVE_FLOAT_H
+
+/* Define to 1 if you have the `floor' function. */
+#undef HAVE_FLOOR
+
+/* Define to 1 if you have the `fmodf' function. */
+#undef HAVE_FMODF
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the <GL/glext.h> header file. */
+#undef HAVE_GL_GLEXT_H
+
+/* Define to 1 if you have the <GL/glu.h> header file. */
+#undef HAVE_GL_GLU_H
+
+/* Define to 1 if you have the <GL/gl.h> header file. */
+#undef HAVE_GL_GL_H
+
+/* Define to 1 if you have the <ieeefp.h> header file. */
+#undef HAVE_IEEEFP_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `isnan' function. */
+#undef HAVE_ISNAN
+
+/* Define to 1 if you have the `isnanf' function. */
+#undef HAVE_ISNANF
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if libc includes obstacks. */
+#undef HAVE_OBSTACK
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+   and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `sinf' function. */
+#undef HAVE_SINF
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `sqrt' function. */
+#undef HAVE_SQRT
+
+/* Define to 1 if you have the `sqrtf' function. */
+#undef HAVE_SQRTF
+
+/* Use SSE Optimizations */
+#undef HAVE_SSE
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <values.h> header file. */
+#undef HAVE_VALUES_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if you have the `_isnan' function. */
+#undef HAVE__ISNAN
+
+/* Define to 1 if you have the `_isnanf' function. */
+#undef HAVE__ISNANF
+
+/* Define to 1 if you have the `__isnan' function. */
+#undef HAVE___ISNAN
+
+/* Define to 1 if you have the `__isnanf' function. */
+#undef HAVE___ISNANF
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* is this a pentium on a gcc-based platform? */
+#undef PENTIUM
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* The size of `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long int', as computed by sizeof. */
+#undef SIZEOF_LONG_INT
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `void*', as computed by sizeof. */
+#undef SIZEOF_VOIDP
+
+/* The extension for shared libraries. */
+#undef SO_EXT
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* is this a X86_64 system on a gcc-based platform? */
+#undef X86_64_SYSTEM
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Use double precision */
+#undef dDOUBLE
+
+/* dEpsilon Constant */
+#undef dEpsilon
+
+/* Use gyroscopic terms */
+#undef dGYROSCOPIC
+
+/* dInfinity Constant */
+#undef dInfinity
+
+/* Disable debug output */
+#undef dNODEBUG
+
+/* Use single precision */
+#undef dSINGLE
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
+
+
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#if defined(HAVE_IEEEFP_H) && !defined(__CYGWIN__)
+// This header creates conflicts with math.h in Cygwin.
+#include <ieeefp.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#if SIZEOF_CHAR == 1
+typedef char int8;
+typedef unsigned char uint8;
+#else
+#error "expecting sizeof(char) == 1"
+#endif
+#if SIZEOF_SHORT == 2
+typedef short int16;
+typedef unsigned short uint16;
+#else
+#error "can not find 2 byte integer type"
+#endif
+/* integer types (we assume int >= 32 bits) */
+#if SIZEOF_INT == 4
+typedef short int32;
+typedef unsigned short uint32;
+#else
+#error "can not find 4 byte integer type"
+#endif
+/* an integer type that we can safely cast a pointer to and
+ * from without loss of bits.
+ */
+#if SIZEOF_SHORT == SIZEOF_VOIDP
+typedef unsigned short intP;
+#elif SIZEOF_INT == SIZEOF_VOIDP
+typedef unsigned int intP;
+#elif SIZEOF_LONG_INT == SIZEOF_VOIDP
+typedef unsigned long int intP;
+#endif
+
+/* 
+Handle Windows DLL odities
+Its easier to export all symbols using the -shared flag
+for MinGW than differentiating with declspec,
+so only do it for MSVC
+*/
+#if defined(ODE_DLL) && defined(WIN32) && defined(_MSC_VER)
+#define ODE_API __declspec( dllexport )
+#elif !defined(ODE_DLL) && defined(WIN32) && defined(MSC_VER)
+#define ODE_API __declspec( dllimport )
+#else
+#define ODE_API
+#endif
+
+#endif /* #define ODE_CONFIG_H */
+
Index: /code/branches/ode/ode-0.9/include/ode/contact.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/contact.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/contact.h	(revision 216)
@@ -0,0 +1,103 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_CONTACT_H_
+#define _ODE_CONTACT_H_
+
+#include <ode/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum {
+  dContactMu2		= 0x001,
+  dContactFDir1		= 0x002,
+  dContactBounce	= 0x004,
+  dContactSoftERP	= 0x008,
+  dContactSoftCFM	= 0x010,
+  dContactMotion1	= 0x020,
+  dContactMotion2	= 0x040,
+  dContactSlip1		= 0x080,
+  dContactSlip2		= 0x100,
+
+  dContactApprox0	= 0x0000,
+  dContactApprox1_1	= 0x1000,
+  dContactApprox1_2	= 0x2000,
+  dContactApprox1	= 0x3000
+};
+
+
+typedef struct dSurfaceParameters {
+  /* must always be defined */
+  int mode;
+  dReal mu;
+
+  /* only defined if the corresponding flag is set in mode */
+  dReal mu2;
+  dReal bounce;
+  dReal bounce_vel;
+  dReal soft_erp;
+  dReal soft_cfm;
+  dReal motion1,motion2;
+  dReal slip1,slip2;
+} dSurfaceParameters;
+
+
+/**
+ * @brief Describe the contact point between two geoms.
+ *
+ * If two bodies touch, or if a body touches a static feature in its 
+ * environment, the contact is represented by one or more "contact 
+ * points", described by dContactGeom.
+ *
+ * The convention is that if body 1 is moved along the normal vector by 
+ * a distance depth (or equivalently if body 2 is moved the same distance 
+ * in the opposite direction) then the contact depth will be reduced to 
+ * zero. This means that the normal vector points "in" to body 1.
+ *
+ * @ingroup collide
+ */
+typedef struct dContactGeom {
+  dVector3 pos;          ///< contact position
+  dVector3 normal;       ///< normal vector
+  dReal depth;           ///< penetration depth
+  dGeomID g1,g2;         ///< the colliding geoms
+  int side1,side2;       ///< (to be documented)
+} dContactGeom;
+
+
+/* contact info used by contact joint */
+
+typedef struct dContact {
+  dSurfaceParameters surface;
+  dContactGeom geom;
+  dVector3 fdir1;
+} dContact;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/error.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/error.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/error.h	(revision 216)
@@ -0,0 +1,63 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* this comes from the `reuse' library. copy any changes back to the source */
+
+#ifndef _ODE_ERROR_H_
+#define _ODE_ERROR_H_
+
+#include <ode/config.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* all user defined error functions have this type. error and debug functions
+ * should not return.
+ */
+typedef void dMessageFunction (int errnum, const char *msg, va_list ap);
+
+/* set a new error, debug or warning handler. if fn is 0, the default handlers
+ * are used.
+ */
+ODE_API void dSetErrorHandler (dMessageFunction *fn);
+ODE_API void dSetDebugHandler (dMessageFunction *fn);
+ODE_API void dSetMessageHandler (dMessageFunction *fn);
+
+/* return the current error, debug or warning handler. if the return value is
+ * 0, the default handlers are in place.
+ */
+ODE_API dMessageFunction *dGetErrorHandler(void);
+ODE_API dMessageFunction *dGetDebugHandler(void);
+ODE_API dMessageFunction *dGetMessageHandler(void);
+
+/* generate a fatal error, debug trap or a message. */
+ODE_API void dError (int num, const char *msg, ...);
+ODE_API void dDebug (int num, const char *msg, ...);
+ODE_API void dMessage (int num, const char *msg, ...);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/export-dif.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/export-dif.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/export-dif.h	(revision 216)
@@ -0,0 +1,32 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_EXPORT_DIF_
+#define _ODE_EXPORT_DIF_
+
+#include <ode/common.h>
+
+
+ODE_API void dWorldExportDIF (dWorldID w, FILE *file, const char *world_name);
+
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/mass.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/mass.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/mass.h	(revision 216)
@@ -0,0 +1,125 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_MASS_H_
+#define _ODE_MASS_H_
+
+#include <ode/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dMass;
+typedef struct dMass dMass;
+
+/**
+ * Check if a mass structure has valid value.
+ * The function check if the mass and innertia matrix are positive definits
+ *
+ * @param m A mass structure to check
+ *
+ * @return 1 if both codition are met
+ */
+ODE_API int dMassCheck(const dMass *m);
+
+ODE_API void dMassSetZero (dMass *);
+
+ODE_API void dMassSetParameters (dMass *, dReal themass,
+			 dReal cgx, dReal cgy, dReal cgz,
+			 dReal I11, dReal I22, dReal I33,
+			 dReal I12, dReal I13, dReal I23);
+
+ODE_API void dMassSetSphere (dMass *, dReal density, dReal radius);
+ODE_API void dMassSetSphereTotal (dMass *, dReal total_mass, dReal radius);
+
+ODE_API void dMassSetCapsule (dMass *, dReal density, int direction,
+		  	dReal radius, dReal length);
+ODE_API void dMassSetCapsuleTotal (dMass *, dReal total_mass, int direction,
+			dReal radius, dReal length);
+
+ODE_API void dMassSetCylinder (dMass *, dReal density, int direction,
+		       dReal radius, dReal length);
+ODE_API void dMassSetCylinderTotal (dMass *, dReal total_mass, int direction,
+			    dReal radius, dReal length);
+
+ODE_API void dMassSetBox (dMass *, dReal density,
+		  dReal lx, dReal ly, dReal lz);
+ODE_API void dMassSetBoxTotal (dMass *, dReal total_mass,
+		       dReal lx, dReal ly, dReal lz);
+
+ODE_API void dMassSetTrimesh (dMass *, dReal density, dGeomID g);
+
+ODE_API void dMassSetTrimeshTotal (dMass *m, dReal total_mass, dGeomID g);
+
+ODE_API void dMassAdjust (dMass *, dReal newmass);
+
+ODE_API void dMassTranslate (dMass *, dReal x, dReal y, dReal z);
+
+ODE_API void dMassRotate (dMass *, const dMatrix3 R);
+
+ODE_API void dMassAdd (dMass *a, const dMass *b);
+
+// Backwards compatible API
+#define dMassSetCappedCylinder dMassSetCapsule
+#define dMassSetCappedCylinderTotal dMassSetCapsuleTotal
+
+
+struct dMass {
+  dReal mass;
+  dVector4 c;
+  dMatrix3 I;
+
+#ifdef __cplusplus
+  dMass()
+    { dMassSetZero (this); }
+  void setZero()
+    { dMassSetZero (this); }
+  void setParameters (dReal themass, dReal cgx, dReal cgy, dReal cgz,
+		      dReal I11, dReal I22, dReal I33,
+		      dReal I12, dReal I13, dReal I23)
+    { dMassSetParameters (this,themass,cgx,cgy,cgz,I11,I22,I33,I12,I13,I23); }
+  void setSphere (dReal density, dReal radius)
+    { dMassSetSphere (this,density,radius); }
+  void setCapsule (dReal density, int direction, dReal a, dReal b)
+    { dMassSetCappedCylinder (this,density,direction,a,b); }
+  void setCappedCylinder (dReal density, int direction, dReal a, dReal b)
+    { setCapsule(density, direction, a, b); }
+  void setBox (dReal density, dReal lx, dReal ly, dReal lz)
+    { dMassSetBox (this,density,lx,ly,lz); }
+  void adjust (dReal newmass)
+    { dMassAdjust (this,newmass); }
+  void translate (dReal x, dReal y, dReal z)
+    { dMassTranslate (this,x,y,z); }
+  void rotate (const dMatrix3 R)
+    { dMassRotate (this,R); }
+  void add (const dMass *b)
+    { dMassAdd (this,b); }
+#endif
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/matrix.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/matrix.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/matrix.h	(revision 216)
@@ -0,0 +1,194 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* optimized and unoptimized vector and matrix functions */
+
+#ifndef _ODE_MATRIX_H_
+#define _ODE_MATRIX_H_
+
+#include <ode/common.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* set a vector/matrix of size n to all zeros, or to a specific value. */
+
+ODE_API void dSetZero (dReal *a, int n);
+ODE_API void dSetValue (dReal *a, int n, dReal value);
+
+
+/* get the dot product of two n*1 vectors. if n <= 0 then
+ * zero will be returned (in which case a and b need not be valid).
+ */
+
+ODE_API dReal dDot (const dReal *a, const dReal *b, int n);
+
+
+/* get the dot products of (a0,b), (a1,b), etc and return them in outsum.
+ * all vectors are n*1. if n <= 0 then zeroes will be returned (in which case
+ * the input vectors need not be valid). this function is somewhat faster
+ * than calling dDot() for all of the combinations separately.
+ */
+
+/* NOT INCLUDED in the library for now.
+void dMultidot2 (const dReal *a0, const dReal *a1,
+		 const dReal *b, dReal *outsum, int n);
+*/
+
+
+/* matrix multiplication. all matrices are stored in standard row format.
+ * the digit refers to the argument that is transposed:
+ *   0:   A = B  * C   (sizes: A:p*r B:p*q C:q*r)
+ *   1:   A = B' * C   (sizes: A:p*r B:q*p C:q*r)
+ *   2:   A = B  * C'  (sizes: A:p*r B:p*q C:r*q)
+ * case 1,2 are equivalent to saying that the operation is A=B*C but
+ * B or C are stored in standard column format.
+ */
+
+ODE_API void dMultiply0 (dReal *A, const dReal *B, const dReal *C, int p,int q,int r);
+ODE_API void dMultiply1 (dReal *A, const dReal *B, const dReal *C, int p,int q,int r);
+ODE_API void dMultiply2 (dReal *A, const dReal *B, const dReal *C, int p,int q,int r);
+
+
+/* do an in-place cholesky decomposition on the lower triangle of the n*n
+ * symmetric matrix A (which is stored by rows). the resulting lower triangle
+ * will be such that L*L'=A. return 1 on success and 0 on failure (on failure
+ * the matrix is not positive definite).
+ */
+
+ODE_API int dFactorCholesky (dReal *A, int n);
+
+
+/* solve for x: L*L'*x = b, and put the result back into x.
+ * L is size n*n, b is size n*1. only the lower triangle of L is considered.
+ */
+
+ODE_API void dSolveCholesky (const dReal *L, dReal *b, int n);
+
+
+/* compute the inverse of the n*n positive definite matrix A and put it in
+ * Ainv. this is not especially fast. this returns 1 on success (A was
+ * positive definite) or 0 on failure (not PD).
+ */
+
+ODE_API int dInvertPDMatrix (const dReal *A, dReal *Ainv, int n);
+
+
+/* check whether an n*n matrix A is positive definite, return 1/0 (yes/no).
+ * positive definite means that x'*A*x > 0 for any x. this performs a
+ * cholesky decomposition of A. if the decomposition fails then the matrix
+ * is not positive definite. A is stored by rows. A is not altered.
+ */
+
+ODE_API int dIsPositiveDefinite (const dReal *A, int n);
+
+
+/* factorize a matrix A into L*D*L', where L is lower triangular with ones on
+ * the diagonal, and D is diagonal.
+ * A is an n*n matrix stored by rows, with a leading dimension of n rounded
+ * up to 4. L is written into the strict lower triangle of A (the ones are not
+ * written) and the reciprocal of the diagonal elements of D are written into
+ * d.
+ */
+ODE_API void dFactorLDLT (dReal *A, dReal *d, int n, int nskip);
+
+
+/* solve L*x=b, where L is n*n lower triangular with ones on the diagonal,
+ * and x,b are n*1. b is overwritten with x.
+ * the leading dimension of L is `nskip'.
+ */
+ODE_API void dSolveL1 (const dReal *L, dReal *b, int n, int nskip);
+
+
+/* solve L'*x=b, where L is n*n lower triangular with ones on the diagonal,
+ * and x,b are n*1. b is overwritten with x.
+ * the leading dimension of L is `nskip'.
+ */
+ODE_API void dSolveL1T (const dReal *L, dReal *b, int n, int nskip);
+
+
+/* in matlab syntax: a(1:n) = a(1:n) .* d(1:n) */
+
+ODE_API void dVectorScale (dReal *a, const dReal *d, int n);
+
+
+/* given `L', a n*n lower triangular matrix with ones on the diagonal,
+ * and `d', a n*1 vector of the reciprocal diagonal elements of an n*n matrix
+ * D, solve L*D*L'*x=b where x,b are n*1. x overwrites b.
+ * the leading dimension of L is `nskip'.
+ */
+
+ODE_API void dSolveLDLT (const dReal *L, const dReal *d, dReal *b, int n, int nskip);
+
+
+/* given an L*D*L' factorization of an n*n matrix A, return the updated
+ * factorization L2*D2*L2' of A plus the following "top left" matrix:
+ *
+ *    [ b a' ]     <-- b is a[0]
+ *    [ a 0  ]     <-- a is a[1..n-1]
+ *
+ *   - L has size n*n, its leading dimension is nskip. L is lower triangular
+ *     with ones on the diagonal. only the lower triangle of L is referenced.
+ *   - d has size n. d contains the reciprocal diagonal elements of D.
+ *   - a has size n.
+ * the result is written into L, except that the left column of L and d[0]
+ * are not actually modified. see ldltaddTL.m for further comments. 
+ */
+ODE_API void dLDLTAddTL (dReal *L, dReal *d, const dReal *a, int n, int nskip);
+
+
+/* given an L*D*L' factorization of a permuted matrix A, produce a new
+ * factorization for row and column `r' removed.
+ *   - A has size n1*n1, its leading dimension in nskip. A is symmetric and
+ *     positive definite. only the lower triangle of A is referenced.
+ *     A itself may actually be an array of row pointers.
+ *   - L has size n2*n2, its leading dimension in nskip. L is lower triangular
+ *     with ones on the diagonal. only the lower triangle of L is referenced.
+ *   - d has size n2. d contains the reciprocal diagonal elements of D.
+ *   - p is a permutation vector. it contains n2 indexes into A. each index
+ *     must be in the range 0..n1-1.
+ *   - r is the row/column of L to remove.
+ * the new L will be written within the old L, i.e. will have the same leading
+ * dimension. the last row and column of L, and the last element of d, are
+ * undefined on exit.
+ *
+ * a fast O(n^2) algorithm is used. see ldltremove.m for further comments.
+ */
+ODE_API void dLDLTRemove (dReal **A, const int *p, dReal *L, dReal *d,
+		  int n1, int n2, int r, int nskip);
+
+
+/* given an n*n matrix A (with leading dimension nskip), remove the r'th row
+ * and column by moving elements. the new matrix will have the same leading
+ * dimension. the last row and column of A are untouched on exit.
+ */
+ODE_API void dRemoveRowCol (dReal *A, int n, int nskip, int r);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/memory.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/memory.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/memory.h	(revision 216)
@@ -0,0 +1,59 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* this comes from the `reuse' library. copy any changes back to the source */
+
+#ifndef _ODE_MEMORY_H_
+#define _ODE_MEMORY_H_
+
+#include "ode/config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* function types to allocate and free memory */
+typedef void * dAllocFunction (size_t size);
+typedef void * dReallocFunction (void *ptr, size_t oldsize, size_t newsize);
+typedef void dFreeFunction (void *ptr, size_t size);
+
+/* set new memory management functions. if fn is 0, the default handlers are
+ * used. */
+ODE_API void dSetAllocHandler (dAllocFunction *fn);
+ODE_API void dSetReallocHandler (dReallocFunction *fn);
+ODE_API void dSetFreeHandler (dFreeFunction *fn);
+
+/* get current memory management functions */
+ODE_API dAllocFunction *dGetAllocHandler (void);
+ODE_API dReallocFunction *dGetReallocHandler (void);
+ODE_API dFreeFunction *dGetFreeHandler (void);
+
+/* allocate and free memory. */
+ODE_API void * dAlloc (size_t size);
+ODE_API void * dRealloc (void *ptr, size_t oldsize, size_t newsize);
+ODE_API void dFree (void *ptr, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/misc.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/misc.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/misc.h	(revision 216)
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* miscellaneous math functions. these are mostly useful for testing */
+
+#ifndef _ODE_MISC_H_
+#define _ODE_MISC_H_
+
+#include <ode/common.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* return 1 if the random number generator is working. */
+ODE_API int dTestRand(void);
+
+/* return next 32 bit random number. this uses a not-very-random linear
+ * congruential method.
+ */
+ODE_API unsigned long dRand(void);
+
+/* get and set the current random number seed. */
+ODE_API unsigned long  dRandGetSeed(void);
+ODE_API void dRandSetSeed (unsigned long s);
+
+/* return a random integer between 0..n-1. the distribution will get worse
+ * as n approaches 2^32.
+ */
+ODE_API int dRandInt (int n);
+
+/* return a random real number between 0..1 */
+ODE_API dReal dRandReal(void);
+
+/* print out a matrix */
+#ifdef __cplusplus
+ODE_API void dPrintMatrix (const dReal *A, int n, int m, char *fmt = "%10.4f ",
+		   FILE *f=stdout);
+#else
+ODE_API void dPrintMatrix (const dReal *A, int n, int m, char *fmt, FILE *f);
+#endif
+
+/* make a random vector with entries between +/- range. A has n elements. */
+ODE_API void dMakeRandomVector (dReal *A, int n, dReal range);
+
+/* make a random matrix with entries between +/- range. A has size n*m. */
+ODE_API void dMakeRandomMatrix (dReal *A, int n, int m, dReal range);
+
+/* clear the upper triangle of a square matrix */
+ODE_API void dClearUpperTriangle (dReal *A, int n);
+
+/* return the maximum element difference between the two n*m matrices */
+ODE_API dReal dMaxDifference (const dReal *A, const dReal *B, int n, int m);
+
+/* return the maximum element difference between the lower triangle of two
+ * n*n matrices */
+ODE_API dReal dMaxDifferenceLowerTriangle (const dReal *A, const dReal *B, int n);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/objects.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/objects.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/objects.h	(revision 216)
@@ -0,0 +1,1966 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_OBJECTS_H_
+#define _ODE_OBJECTS_H_
+
+#include <ode/common.h>
+#include <ode/mass.h>
+#include <ode/contact.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup world World
+ *
+ * The world object is a container for rigid bodies and joints. Objects in
+ * different worlds can not interact, for example rigid bodies from two
+ * different worlds can not collide.
+ *
+ * All the objects in a world exist at the same point in time, thus one
+ * reason to use separate worlds is to simulate systems at different rates.
+ * Most applications will only need one world.
+ */
+
+
+/**
+ * @brief Create a new, empty world and return its ID number.
+ * @return an identifier
+ * @ingroup world
+ */
+ODE_API dWorldID dWorldCreate(void);
+
+
+/**
+ * @brief Destroy a world and everything in it.
+ *
+ * This includes all bodies, and all joints that are not part of a joint
+ * group. Joints that are part of a joint group will be deactivated, and
+ * can be destroyed by calling, for example, dJointGroupEmpty().
+ * @ingroup world
+ * @param world the identifier for the world the be destroyed.
+ */
+ODE_API void dWorldDestroy (dWorldID world);
+
+
+/**
+ * @brief Set the world's global gravity vector.
+ *
+ * The units are m/s^2, so Earth's gravity vector would be (0,0,-9.81),
+ * assuming that +z is up. The default is no gravity, i.e. (0,0,0).
+ *
+ * @ingroup world
+ */
+ODE_API void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z);
+
+
+/**
+ * @brief Get the gravity vector for a given world.
+ * @ingroup world
+ */
+ODE_API void dWorldGetGravity (dWorldID, dVector3 gravity);
+
+
+/**
+ * @brief Set the global ERP value, that controls how much error
+ * correction is performed in each time step.
+ * @ingroup world
+ * @param dWorldID the identifier of the world.
+ * @param erp Typical values are in the range 0.1--0.8. The default is 0.2.
+ */
+ODE_API void dWorldSetERP (dWorldID, dReal erp);
+
+/**
+ * @brief Get the error reduction parameter.
+ * @ingroup world
+ * @return ERP value
+ */
+ODE_API dReal dWorldGetERP (dWorldID);
+
+
+/**
+ * @brief Set the global CFM (constraint force mixing) value.
+ * @ingroup world
+ * @param cfm Typical values are in the range @m{10^{-9}} -- 1.
+ * The default is 10^-5 if single precision is being used, or 10^-10
+ * if double precision is being used.
+ */
+ODE_API void dWorldSetCFM (dWorldID, dReal cfm);
+
+/**
+ * @brief Get the constraint force mixing value.
+ * @ingroup world
+ * @return CFM value
+ */
+ODE_API dReal dWorldGetCFM (dWorldID);
+
+
+/**
+ * @brief Step the world.
+ *
+ * This uses a "big matrix" method that takes time on the order of m^3
+ * and memory on the order of m^2, where m is the total number of constraint
+ * rows. For large systems this will use a lot of memory and can be very slow,
+ * but this is currently the most accurate method.
+ * @ingroup world
+ * @param stepsize The number of seconds that the simulation has to advance.
+ */
+ODE_API void dWorldStep (dWorldID, dReal stepsize);
+
+
+/**
+ * @brief Converts an impulse to a force.
+ * @ingroup world
+ * @remarks
+ * If you want to apply a linear or angular impulse to a rigid body,
+ * instead of a force or a torque, then you can use this function to convert
+ * the desired impulse into a force/torque vector before calling the
+ * BodyAdd... function.
+ * The current algorithm simply scales the impulse by 1/stepsize,
+ * where stepsize is the step size for the next step that will be taken.
+ * This function is given a dWorldID because, in the future, the force
+ * computation may depend on integrator parameters that are set as
+ * properties of the world.
+ */
+ODE_API void dWorldImpulseToForce
+(
+  dWorldID, dReal stepsize,
+  dReal ix, dReal iy, dReal iz, dVector3 force
+);
+
+
+/**
+ * @brief Step the world.
+ * @ingroup world
+ * @remarks
+ * This uses an iterative method that takes time on the order of m*N
+ * and memory on the order of m, where m is the total number of constraint
+ * rows N is the number of iterations.
+ * For large systems this is a lot faster than dWorldStep(),
+ * but it is less accurate.
+ * @remarks
+ * QuickStep is great for stacks of objects especially when the
+ * auto-disable feature is used as well.
+ * However, it has poor accuracy for near-singular systems.
+ * Near-singular systems can occur when using high-friction contacts, motors,
+ * or certain articulated structures. For example, a robot with multiple legs
+ * sitting on the ground may be near-singular.
+ * @remarks
+ * There are ways to help overcome QuickStep's inaccuracy problems:
+ * \li Increase CFM.
+ * \li Reduce the number of contacts in your system (e.g. use the minimum
+ *     number of contacts for the feet of a robot or creature).
+ * \li Don't use excessive friction in the contacts.
+ * \li Use contact slip if appropriate
+ * \li Avoid kinematic loops (however, kinematic loops are inevitable in
+ *     legged creatures).
+ * \li Don't use excessive motor strength.
+ * \liUse force-based motors instead of velocity-based motors.
+ *
+ * Increasing the number of QuickStep iterations may help a little bit, but
+ * it is not going to help much if your system is really near singular.
+ */
+ODE_API void dWorldQuickStep (dWorldID w, dReal stepsize);
+
+
+/**
+ * @brief Set the number of iterations that the QuickStep method performs per
+ *        step.
+ * @ingroup world
+ * @remarks
+ * More iterations will give a more accurate solution, but will take
+ * longer to compute.
+ * @param num The default is 20 iterations.
+ */
+ODE_API void dWorldSetQuickStepNumIterations (dWorldID, int num);
+
+
+/**
+ * @brief Get the number of iterations that the QuickStep method performs per
+ *        step.
+ * @ingroup world
+ * @return nr of iterations
+ */
+ODE_API int dWorldGetQuickStepNumIterations (dWorldID);
+
+/**
+ * @brief Set the SOR over-relaxation parameter
+ * @ingroup world
+ * @param over_relaxation value to use by SOR
+ */
+ODE_API void dWorldSetQuickStepW (dWorldID, dReal over_relaxation);
+
+/**
+ * @brief Get the SOR over-relaxation parameter
+ * @ingroup world
+ * @returns the over-relaxation setting
+ */
+ODE_API dReal dWorldGetQuickStepW (dWorldID);
+
+/* World contact parameter functions */
+
+/**
+ * @brief Set the maximum correcting velocity that contacts are allowed
+ * to generate.
+ * @ingroup world
+ * @param vel The default value is infinity (i.e. no limit).
+ * @remarks
+ * Reducing this value can help prevent "popping" of deeply embedded objects.
+ */
+ODE_API void dWorldSetContactMaxCorrectingVel (dWorldID, dReal vel);
+
+/**
+ * @brief Get the maximum correcting velocity that contacts are allowed
+ * to generated.
+ * @ingroup world
+ */
+ODE_API dReal dWorldGetContactMaxCorrectingVel (dWorldID);
+
+/**
+ * @brief Set the depth of the surface layer around all geometry objects.
+ * @ingroup world
+ * @remarks
+ * Contacts are allowed to sink into the surface layer up to the given
+ * depth before coming to rest.
+ * @param depth The default value is zero.
+ * @remarks
+ * Increasing this to some small value (e.g. 0.001) can help prevent
+ * jittering problems due to contacts being repeatedly made and broken.
+ */
+ODE_API void dWorldSetContactSurfaceLayer (dWorldID, dReal depth);
+
+/**
+ * @brief Get the depth of the surface layer around all geometry objects.
+ * @ingroup world
+ * @returns the depth
+ */
+ODE_API dReal dWorldGetContactSurfaceLayer (dWorldID);
+
+/* StepFast1 functions */
+
+/**
+ * @brief Step the world using the StepFast1 algorithm.
+ * @param stepsize the nr of seconds to advance the simulation.
+ * @param maxiterations The number of iterations to perform.
+ * @ingroup world
+ */
+ODE_API void dWorldStepFast1(dWorldID, dReal stepsize, int maxiterations);
+
+
+/**
+ * @defgroup disable Automatic Enabling and Disabling
+ *
+ * Every body can be enabled or disabled. Enabled bodies participate in the
+ * simulation, while disabled bodies are turned off and do not get updated
+ * during a simulation step. New bodies are always created in the enabled state.
+ *
+ * A disabled body that is connected through a joint to an enabled body will be
+ * automatically re-enabled at the next simulation step.
+ *
+ * Disabled bodies do not consume CPU time, therefore to speed up the simulation
+ * bodies should be disabled when they come to rest. This can be done automatically
+ * with the auto-disable feature.
+ *
+ * If a body has its auto-disable flag turned on, it will automatically disable
+ * itself when
+ *   @li It has been idle for a given number of simulation steps.
+ *   @li It has also been idle for a given amount of simulation time.
+ *
+ * A body is considered to be idle when the magnitudes of both its
+ * linear average velocity and angular average velocity are below given thresholds.
+ * The sample size for the average defaults to one and can be disabled by setting
+ * to zero with 
+ *
+ * Thus, every body has six auto-disable parameters: an enabled flag, a idle step
+ * count, an idle time, linear/angular average velocity thresholds, and the
+ * average samples count.
+ *
+ * Newly created bodies get these parameters from world.
+ */
+
+/**
+ * @brief Set the AutoEnableDepth parameter used by the StepFast1 algorithm.
+ * @ingroup disable
+ */
+ODE_API void dWorldSetAutoEnableDepthSF1(dWorldID, int autoEnableDepth);
+
+/**
+ * @brief Get the AutoEnableDepth parameter used by the StepFast1 algorithm.
+ * @ingroup disable
+ */
+ODE_API int dWorldGetAutoEnableDepthSF1(dWorldID);
+
+/**
+ * @brief Get auto disable linear threshold for newly created bodies.
+ * @ingroup disable
+ * @return the threshold
+ */
+ODE_API dReal dWorldGetAutoDisableLinearThreshold (dWorldID);
+
+/**
+ * @brief Set auto disable linear threshold for newly created bodies.
+ * @param linear_threshold default is 0.01
+ * @ingroup disable
+ */
+ODE_API void  dWorldSetAutoDisableLinearThreshold (dWorldID, dReal linear_threshold);
+
+/**
+ * @brief Get auto disable angular threshold for newly created bodies.
+ * @ingroup disable
+ * @return the threshold
+ */
+ODE_API dReal dWorldGetAutoDisableAngularThreshold (dWorldID);
+
+/**
+ * @brief Set auto disable angular threshold for newly created bodies.
+ * @param linear_threshold default is 0.01
+ * @ingroup disable
+ */
+ODE_API void dWorldSetAutoDisableAngularThreshold (dWorldID, dReal angular_threshold);
+
+/**
+ * @brief Get auto disable linear average threshold for newly created bodies.
+ * @ingroup disable
+ * @return the threshold
+ */
+ODE_API dReal dWorldGetAutoDisableLinearAverageThreshold (dWorldID);
+
+/**
+ * @brief Set auto disable linear average threshold for newly created bodies.
+ * @param linear_average_threshold default is 0.01
+ * @ingroup disable
+ */
+ODE_API void  dWorldSetAutoDisableLinearAverageThreshold (dWorldID, dReal linear_average_threshold);
+
+/**
+ * @brief Get auto disable angular average threshold for newly created bodies.
+ * @ingroup disable
+ * @return the threshold
+ */
+ODE_API dReal dWorldGetAutoDisableAngularAverageThreshold (dWorldID);
+
+/**
+ * @brief Set auto disable angular average threshold for newly created bodies.
+ * @param linear_average_threshold default is 0.01
+ * @ingroup disable
+ */
+ODE_API void dWorldSetAutoDisableAngularAverageThreshold (dWorldID, dReal angular_average_threshold);
+
+/**
+ * @brief Get auto disable sample count for newly created bodies.
+ * @ingroup disable
+ * @return number of samples used
+ */
+ODE_API int dWorldGetAutoDisableAverageSamplesCount (dWorldID);
+
+/**
+ * @brief Set auto disable average sample count for newly created bodies.
+ * @ingroup disable
+ * @param average_samples_count Default is 1, meaning only instantaneous velocity is used.
+ * Set to zero to disable sampling and thus prevent any body from auto-disabling.
+ */
+ODE_API void dWorldSetAutoDisableAverageSamplesCount (dWorldID, unsigned int average_samples_count );
+
+/**
+ * @brief Get auto disable steps for newly created bodies.
+ * @ingroup disable
+ * @return nr of steps
+ */
+ODE_API int dWorldGetAutoDisableSteps (dWorldID);
+
+/**
+ * @brief Set auto disable steps for newly created bodies.
+ * @ingroup disable
+ * @param steps default is 10
+ */
+ODE_API void dWorldSetAutoDisableSteps (dWorldID, int steps);
+
+/**
+ * @brief Get auto disable time for newly created bodies.
+ * @ingroup disable
+ * @return nr of seconds
+ */
+ODE_API dReal dWorldGetAutoDisableTime (dWorldID);
+
+/**
+ * @brief Set auto disable time for newly created bodies.
+ * @ingroup disable
+ * @param time default is 0 seconds
+ */
+ODE_API void dWorldSetAutoDisableTime (dWorldID, dReal time);
+
+/**
+ * @brief Get auto disable flag for newly created bodies.
+ * @ingroup disable
+ * @return 0 or 1
+ */
+ODE_API int dWorldGetAutoDisableFlag (dWorldID);
+
+/**
+ * @brief Set auto disable flag for newly created bodies.
+ * @ingroup disable
+ * @param do_auto_disable default is false.
+ */
+ODE_API void dWorldSetAutoDisableFlag (dWorldID, int do_auto_disable);
+
+
+
+/**
+ * @defgroup bodies Rigid Bodies
+ *
+ * A rigid body has various properties from the point of view of the
+ * simulation. Some properties change over time:
+ *
+ *  @li Position vector (x,y,z) of the body's point of reference.
+ *      Currently the point of reference must correspond to the body's center of mass.
+ *  @li Linear velocity of the point of reference, a vector (vx,vy,vz).
+ *  @li Orientation of a body, represented by a quaternion (qs,qx,qy,qz) or
+ *      a 3x3 rotation matrix.
+ *  @li Angular velocity vector (wx,wy,wz) which describes how the orientation
+ *      changes over time.
+ *
+ * Other body properties are usually constant over time:
+ *
+ *  @li Mass of the body.
+ *  @li Position of the center of mass with respect to the point of reference.
+ *      In the current implementation the center of mass and the point of
+ *      reference must coincide.
+ *  @li Inertia matrix. This is a 3x3 matrix that describes how the body's mass
+ *      is distributed around the center of mass. Conceptually each body has an
+ *      x-y-z coordinate frame embedded in it that moves and rotates with the body.
+ *
+ * The origin of this coordinate frame is the body's point of reference. Some values
+ * in ODE (vectors, matrices etc) are relative to the body coordinate frame, and others
+ * are relative to the global coordinate frame.
+ *
+ * Note that the shape of a rigid body is not a dynamical property (except insofar as
+ * it influences the various mass properties). It is only collision detection that cares
+ * about the detailed shape of the body.
+ */
+
+
+/**
+ * @brief Get auto disable linear average threshold.
+ * @ingroup bodies
+ * @return the threshold
+ */
+ODE_API dReal dBodyGetAutoDisableLinearThreshold (dBodyID);
+
+/**
+ * @brief Set auto disable linear average threshold.
+ * @ingroup bodies
+ * @return the threshold
+ */
+ODE_API void  dBodySetAutoDisableLinearThreshold (dBodyID, dReal linear_average_threshold);
+
+/**
+ * @brief Get auto disable angular average threshold.
+ * @ingroup bodies
+ * @return the threshold
+ */
+ODE_API dReal dBodyGetAutoDisableAngularThreshold (dBodyID);
+
+/**
+ * @brief Set auto disable angular average threshold.
+ * @ingroup bodies
+ * @return the threshold
+ */
+ODE_API void  dBodySetAutoDisableAngularThreshold (dBodyID, dReal angular_average_threshold);
+
+/**
+ * @brief Get auto disable average size (samples count).
+ * @ingroup bodies
+ * @return the nr of steps/size.
+ */
+ODE_API int dBodyGetAutoDisableAverageSamplesCount (dBodyID);
+
+/**
+ * @brief Set auto disable average buffer size (average steps).
+ * @ingroup bodies
+ * @param average_samples_count the nr of samples to review.
+ */
+ODE_API void dBodySetAutoDisableAverageSamplesCount (dBodyID, unsigned int average_samples_count);
+
+
+/**
+ * @brief Get auto steps a body must be thought of as idle to disable
+ * @ingroup bodies
+ * @return the nr of steps
+ */
+ODE_API int dBodyGetAutoDisableSteps (dBodyID);
+
+/**
+ * @brief Set auto disable steps.
+ * @ingroup bodies
+ * @param steps the nr of steps.
+ */
+ODE_API void dBodySetAutoDisableSteps (dBodyID, int steps);
+
+/**
+ * @brief Get auto disable time.
+ * @ingroup bodies
+ * @return nr of seconds
+ */
+ODE_API dReal dBodyGetAutoDisableTime (dBodyID);
+
+/**
+ * @brief Set auto disable time.
+ * @ingroup bodies
+ * @param time nr of seconds.
+ */
+ODE_API void  dBodySetAutoDisableTime (dBodyID, dReal time);
+
+/**
+ * @brief Get auto disable flag.
+ * @ingroup bodies
+ * @return 0 or 1
+ */
+ODE_API int dBodyGetAutoDisableFlag (dBodyID);
+
+/**
+ * @brief Set auto disable flag.
+ * @ingroup bodies
+ * @param do_auto_disable 0 or 1
+ */
+ODE_API void dBodySetAutoDisableFlag (dBodyID, int do_auto_disable);
+
+/**
+ * @brief Set auto disable defaults.
+ * @remarks
+ * Set the values for the body to those set as default for the world.
+ * @ingroup bodies
+ */
+ODE_API void  dBodySetAutoDisableDefaults (dBodyID);
+
+
+/**
+ * @brief Retrives the world attached to te given body.
+ * @remarks
+ * 
+ * @ingroup bodies
+ */
+ODE_API dWorldID dBodyGetWorld (dBodyID);
+
+/**
+ * @brief Create a body in given world.
+ * @remarks
+ * Default mass parameters are at position (0,0,0).
+ * @ingroup bodies
+ */
+ODE_API dBodyID dBodyCreate (dWorldID);
+
+/**
+ * @brief Destroy a body.
+ * @remarks
+ * All joints that are attached to this body will be put into limbo:
+ * i.e. unattached and not affecting the simulation, but they will NOT be
+ * deleted.
+ * @ingroup bodies
+ */
+ODE_API void dBodyDestroy (dBodyID);
+
+/**
+ * @brief Set the body's user-data pointer.
+ * @ingroup bodies
+ * @param data arbitraty pointer
+ */
+ODE_API void  dBodySetData (dBodyID, void *data);
+
+/**
+ * @brief Get the body's user-data pointer.
+ * @ingroup bodies
+ * @return a pointer to the user's data.
+ */
+ODE_API void *dBodyGetData (dBodyID);
+
+/**
+ * @brief Set position of a body.
+ * @remarks
+ * After setting, the outcome of the simulation is undefined
+ * if the new configuration is inconsistent with the joints/constraints
+ * that are present.
+ * @ingroup bodies
+ */
+ODE_API void dBodySetPosition   (dBodyID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Set the orientation of a body.
+ * @ingroup bodies
+ * @remarks
+ * After setting, the outcome of the simulation is undefined
+ * if the new configuration is inconsistent with the joints/constraints
+ * that are present.
+ */
+ODE_API void dBodySetRotation   (dBodyID, const dMatrix3 R);
+
+/**
+ * @brief Set the orientation of a body.
+ * @ingroup bodies
+ * @remarks
+ * After setting, the outcome of the simulation is undefined
+ * if the new configuration is inconsistent with the joints/constraints
+ * that are present.
+ */
+ODE_API void dBodySetQuaternion (dBodyID, const dQuaternion q);
+
+/**
+ * @brief Set the linear velocity of a body.
+ * @ingroup bodies
+ */
+ODE_API void dBodySetLinearVel  (dBodyID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Set the angular velocity of a body.
+ * @ingroup bodies
+ */
+ODE_API void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Get the position of a body.
+ * @ingroup bodies
+ * @remarks
+ * When getting, the returned values are pointers to internal data structures,
+ * so the vectors are valid until any changes are made to the rigid body
+ * system structure.
+ * @sa dBodyCopyPosition
+ */
+ODE_API const dReal * dBodyGetPosition   (dBodyID);
+
+
+/**
+ * @brief Copy the position of a body into a vector.
+ * @ingroup bodies
+ * @param body  the body to query
+ * @param pos   a copy of the body position
+ * @sa dBodyGetPosition
+ */
+ODE_API void dBodyCopyPosition (dBodyID body, dVector3 pos);
+
+
+/**
+ * @brief Get the rotation of a body.
+ * @ingroup bodies
+ * @return pointer to a 4x3 rotation matrix.
+ */
+ODE_API const dReal * dBodyGetRotation   (dBodyID);
+
+
+/**
+ * @brief Copy the rotation of a body.
+ * @ingroup bodies
+ * @param body   the body to query
+ * @param R      a copy of the rotation matrix
+ * @sa dBodyGetRotation
+ */
+ODE_API void dBodyCopyRotation (dBodyID, dMatrix3 R);
+
+
+/**
+ * @brief Get the rotation of a body.
+ * @ingroup bodies
+ * @return pointer to 4 scalars that represent the quaternion.
+ */
+ODE_API const dReal * dBodyGetQuaternion (dBodyID);
+
+
+/**
+ * @brief Copy the orientation of a body into a quaternion.
+ * @ingroup bodies
+ * @param body  the body to query
+ * @param quat  a copy of the orientation quaternion
+ * @sa dBodyGetQuaternion
+ */
+ODE_API void dBodyCopyQuaternion(dBodyID body, dQuaternion quat);
+
+
+/**
+ * @brief Get the linear velocity of a body.
+ * @ingroup bodies
+ */
+ODE_API const dReal * dBodyGetLinearVel  (dBodyID);
+
+/**
+ * @brief Get the angular velocity of a body.
+ * @ingroup bodies
+ */
+ODE_API const dReal * dBodyGetAngularVel (dBodyID);
+
+/**
+ * @brief Set the mass of a body.
+ * @ingroup bodies
+ */
+ODE_API void dBodySetMass (dBodyID, const dMass *mass);
+
+/**
+ * @brief Get the mass of a body.
+ * @ingroup bodies
+ */
+ODE_API void dBodyGetMass (dBodyID, dMass *mass);
+
+/**
+ * @brief Add force at centre of mass of body in absolute coordinates.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddForce            (dBodyID, dReal fx, dReal fy, dReal fz);
+
+/**
+ * @brief Add torque at centre of mass of body in absolute coordinates.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddTorque           (dBodyID, dReal fx, dReal fy, dReal fz);
+
+/**
+ * @brief Add force at centre of mass of body in coordinates relative to body.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddRelForce         (dBodyID, dReal fx, dReal fy, dReal fz);
+
+/**
+ * @brief Add torque at centre of mass of body in coordinates relative to body.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddRelTorque        (dBodyID, dReal fx, dReal fy, dReal fz);
+
+/**
+ * @brief Add force at specified point in body in global coordinates.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddForceAtPos       (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+/**
+ * @brief Add force at specified point in body in local coordinates.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddForceAtRelPos    (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+/**
+ * @brief Add force at specified point in body in global coordinates.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddRelForceAtPos    (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+/**
+ * @brief Add force at specified point in body in local coordinates.
+ * @ingroup bodies
+ */
+ODE_API void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz,
+			                dReal px, dReal py, dReal pz);
+
+/**
+ * @brief Return the current accumulated force vector.
+ * @return points to an array of 3 reals.
+ * @remarks
+ * The returned values are pointers to internal data structures, so
+ * the vectors are only valid until any changes are made to the rigid
+ * body system.
+ * @ingroup bodies
+ */
+ODE_API const dReal * dBodyGetForce   (dBodyID);
+
+/**
+ * @brief Return the current accumulated torque vector.
+ * @return points to an array of 3 reals.
+ * @remarks
+ * The returned values are pointers to internal data structures, so
+ * the vectors are only valid until any changes are made to the rigid
+ * body system.
+ * @ingroup bodies
+ */
+ODE_API const dReal * dBodyGetTorque  (dBodyID);
+
+/**
+ * @brief Set the body force accumulation vector.
+ * @remarks
+ * This is mostly useful to zero the force and torque for deactivated bodies
+ * before they are reactivated, in the case where the force-adding functions
+ * were called on them while they were deactivated.
+ * @ingroup bodies
+ */
+ODE_API void dBodySetForce  (dBodyID b, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Set the body torque accumulation vector.
+ * @remarks
+ * This is mostly useful to zero the force and torque for deactivated bodies
+ * before they are reactivated, in the case where the force-adding functions
+ * were called on them while they were deactivated.
+ * @ingroup bodies
+ */
+ODE_API void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Get world position of a relative point on body.
+ * @ingroup bodies
+ * @param result will contain the result.
+ */
+ODE_API void dBodyGetRelPointPos
+(
+  dBodyID, dReal px, dReal py, dReal pz,
+  dVector3 result
+);
+
+/**
+ * @brief Get velocity vector in global coords of a relative point on body.
+ * @ingroup bodies
+ * @param result will contain the result.
+ */
+ODE_API void dBodyGetRelPointVel
+(
+  dBodyID, dReal px, dReal py, dReal pz,
+  dVector3 result
+);
+
+/**
+ * @brief Get velocity vector in global coords of a globally
+ * specified point on a body.
+ * @ingroup bodies
+ * @param result will contain the result.
+ */
+ODE_API void dBodyGetPointVel
+(
+  dBodyID, dReal px, dReal py, dReal pz,
+  dVector3 result
+);
+
+/**
+ * @brief takes a point in global coordinates and returns
+ * the point's position in body-relative coordinates.
+ * @remarks
+ * This is the inverse of dBodyGetRelPointPos()
+ * @ingroup bodies
+ * @param result will contain the result.
+ */
+ODE_API void dBodyGetPosRelPoint
+(
+  dBodyID, dReal px, dReal py, dReal pz,
+  dVector3 result
+);
+
+/**
+ * @brief Convert from local to world coordinates.
+ * @ingroup bodies
+ * @param result will contain the result.
+ */
+ODE_API void dBodyVectorToWorld
+(
+  dBodyID, dReal px, dReal py, dReal pz,
+  dVector3 result
+);
+
+/**
+ * @brief Convert from world to local coordinates.
+ * @ingroup bodies
+ * @param result will contain the result.
+ */
+ODE_API void dBodyVectorFromWorld
+(
+  dBodyID, dReal px, dReal py, dReal pz,
+  dVector3 result
+);
+
+/**
+ * @brief controls the way a body's orientation is updated at each timestep.
+ * @ingroup bodies
+ * @param mode can be 0 or 1:
+ * \li 0: An ``infinitesimal'' orientation update is used.
+ * This is fast to compute, but it can occasionally cause inaccuracies
+ * for bodies that are rotating at high speed, especially when those
+ * bodies are joined to other bodies.
+ * This is the default for every new body that is created.
+ * \li 1: A ``finite'' orientation update is used.
+ * This is more costly to compute, but will be more accurate for high
+ * speed rotations.
+ * @remarks
+ * Note however that high speed rotations can result in many types of
+ * error in a simulation, and the finite mode will only fix one of those
+ * sources of error.
+ */
+ODE_API void dBodySetFiniteRotationMode (dBodyID, int mode);
+
+/**
+ * @brief sets the finite rotation axis for a body.
+ * @ingroup bodies
+ * @remarks
+ * This is axis only has meaning when the finite rotation mode is set
+ * If this axis is zero (0,0,0), full finite rotations are performed on
+ * the body.
+ * If this axis is nonzero, the body is rotated by performing a partial finite
+ * rotation along the axis direction followed by an infinitesimal rotation
+ * along an orthogonal direction.
+ * @remarks
+ * This can be useful to alleviate certain sources of error caused by quickly
+ * spinning bodies. For example, if a car wheel is rotating at high speed
+ * you can call this function with the wheel's hinge axis as the argument to
+ * try and improve its behavior.
+ */
+ODE_API void dBodySetFiniteRotationAxis (dBodyID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Get the way a body's orientation is updated each timestep.
+ * @ingroup bodies
+ * @return the mode 0 (infitesimal) or 1 (finite).
+ */
+ODE_API int dBodyGetFiniteRotationMode (dBodyID);
+
+/**
+ * @brief Get the finite rotation axis.
+ * @param result will contain the axis.
+ * @ingroup bodies
+ */
+ODE_API void dBodyGetFiniteRotationAxis (dBodyID, dVector3 result);
+
+/**
+ * @brief Get the number of joints that are attached to this body.
+ * @ingroup bodies
+ * @return nr of joints
+ */
+ODE_API int dBodyGetNumJoints (dBodyID b);
+
+/**
+ * @brief Return a joint attached to this body, given by index.
+ * @ingroup bodies
+ * @param index valid range is  0 to n-1 where n is the value returned by
+ * dBodyGetNumJoints().
+ */
+ODE_API dJointID dBodyGetJoint (dBodyID, int index);
+
+/**
+ * @brief Manually enable a body.
+ * @param dBodyID identification of body.
+ * @ingroup bodies
+ */
+ODE_API void dBodyEnable (dBodyID);
+
+/**
+ * @brief Manually disable a body.
+ * @ingroup bodies
+ * @remarks
+ * A disabled body that is connected through a joint to an enabled body will
+ * be automatically re-enabled at the next simulation step.
+ */
+ODE_API void dBodyDisable (dBodyID);
+
+/**
+ * @brief Check wether a body is enabled.
+ * @ingroup bodies
+ * @return 1 if a body is currently enabled or 0 if it is disabled.
+ */
+ODE_API int dBodyIsEnabled (dBodyID);
+
+/**
+ * @brief Set whether the body is influenced by the world's gravity or not.
+ * @ingroup bodies
+ * @param mode when nonzero gravity affects this body.
+ * @remarks
+ * Newly created bodies are always influenced by the world's gravity.
+ */
+ODE_API void dBodySetGravityMode (dBodyID b, int mode);
+
+/**
+ * @brief Get whether the body is influenced by the world's gravity or not.
+ * @ingroup bodies
+ * @return nonzero means gravity affects this body.
+ */
+ODE_API int dBodyGetGravityMode (dBodyID b);
+
+
+
+/**
+ * @defgroup joints Joints
+ *
+ * In real life a joint is something like a hinge, that is used to connect two
+ * objects.
+ * In ODE a joint is very similar: It is a relationship that is enforced between
+ * two bodies so that they can only have certain positions and orientations
+ * relative to each other.
+ * This relationship is called a constraint -- the words joint and
+ * constraint are often used interchangeably.
+ *
+ * A joint has a set of parameters that can be set. These include:
+ *
+ *
+ * \li  dParamLoStop Low stop angle or position. Setting this to
+ *	-dInfinity (the default value) turns off the low stop.
+ *	For rotational joints, this stop must be greater than -pi to be
+ *	effective.
+ * \li  dParamHiStop High stop angle or position. Setting this to
+ *	dInfinity (the default value) turns off the high stop.
+ *	For rotational joints, this stop must be less than pi to be
+ *	effective.
+ *	If the high stop is less than the low stop then both stops will
+ *	be ineffective.
+ * \li  dParamVel Desired motor velocity (this will be an angular or
+ *	linear velocity).
+ * \li  dParamFMax The maximum force or torque that the motor will use to
+ *	achieve the desired velocity.
+ *	This must always be greater than or equal to zero.
+ *	Setting this to zero (the default value) turns off the motor.
+ * \li  dParamFudgeFactor The current joint stop/motor implementation has
+ *	a small problem:
+ *	when the joint is at one stop and the motor is set to move it away
+ *	from the stop, too much force may be applied for one time step,
+ *	causing a ``jumping'' motion.
+ *	This fudge factor is used to scale this excess force.
+ *	It should have a value between zero and one (the default value).
+ *	If the jumping motion is too visible in a joint, the value can be
+ *	reduced.
+ *	Making this value too small can prevent the motor from being able to
+ *	move the joint away from a stop.
+ * \li  dParamBounce The bouncyness of the stops.
+ *	This is a restitution parameter in the range 0..1.
+ *	0 means the stops are not bouncy at all, 1 means maximum bouncyness.
+ * \li  dParamCFM The constraint force mixing (CFM) value used when not
+ *	at a stop.
+ * \li  dParamStopERP The error reduction parameter (ERP) used by the
+ *	stops.
+ * \li  dParamStopCFM The constraint force mixing (CFM) value used by the
+ *	stops. Together with the ERP value this can be used to get spongy or
+ *	soft stops.
+ *	Note that this is intended for unpowered joints, it does not really
+ *	work as expected when a powered joint reaches its limit.
+ * \li  dParamSuspensionERP Suspension error reduction parameter (ERP).
+ *	Currently this is only implemented on the hinge-2 joint.
+ * \li  dParamSuspensionCFM Suspension constraint force mixing (CFM) value.
+ *	Currently this is only implemented on the hinge-2 joint.
+ *
+ * If a particular parameter is not implemented by a given joint, setting it
+ * will have no effect.
+ * These parameter names can be optionally followed by a digit (2 or 3)
+ * to indicate the second or third set of parameters, e.g. for the second axis
+ * in a hinge-2 joint, or the third axis in an AMotor joint.
+ */
+
+
+/**
+ * @brief Create a new joint of the ball type.
+ * @ingroup joints
+ * @remarks
+ * The joint is initially in "limbo" (i.e. it has no effect on the simulation)
+ * because it does not connect to any bodies.
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateBall (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the hinge type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateHinge (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the slider type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateSlider (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the contact type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateContact (dWorldID, dJointGroupID, const dContact *);
+
+/**
+ * @brief Create a new joint of the hinge2 type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateHinge2 (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the universal type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateUniversal (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the PR (Prismatic and Rotoide) type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreatePR (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the fixed type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateFixed (dWorldID, dJointGroupID);
+
+ODE_API dJointID dJointCreateNull (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the A-motor type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateAMotor (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the L-motor type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreateLMotor (dWorldID, dJointGroupID);
+
+/**
+ * @brief Create a new joint of the plane-2d type.
+ * @ingroup joints
+ * @param dJointGroupID set to 0 to allocate the joint normally.
+ * If it is nonzero the joint is allocated in the given joint group.
+ */
+ODE_API dJointID dJointCreatePlane2D (dWorldID, dJointGroupID);
+
+/**
+ * @brief Destroy a joint.
+ * @ingroup joints
+ *
+ * disconnects it from its attached bodies and removing it from the world.
+ * However, if the joint is a member of a group then this function has no
+ * effect - to destroy that joint the group must be emptied or destroyed.
+ */
+ODE_API void dJointDestroy (dJointID);
+
+
+/**
+ * @brief Create a joint group
+ * @ingroup joints
+ * @param max_size deprecated. Set to 0.
+ */
+ODE_API dJointGroupID dJointGroupCreate (int max_size);
+
+/**
+ * @brief Destroy a joint group.
+ * @ingroup joints
+ *
+ * All joints in the joint group will be destroyed.
+ */
+ODE_API void dJointGroupDestroy (dJointGroupID);
+
+/**
+ * @brief Empty a joint group.
+ * @ingroup joints
+ *
+ * All joints in the joint group will be destroyed,
+ * but the joint group itself will not be destroyed.
+ */
+ODE_API void dJointGroupEmpty (dJointGroupID);
+
+/**
+ * @brief Attach the joint to some new bodies.
+ * @ingroup joints
+ *
+ * If the joint is already attached, it will be detached from the old bodies
+ * first.
+ * To attach this joint to only one body, set body1 or body2 to zero - a zero
+ * body refers to the static environment.
+ * Setting both bodies to zero puts the joint into "limbo", i.e. it will
+ * have no effect on the simulation.
+ * @remarks
+ * Some joints, like hinge-2 need to be attached to two bodies to work.
+ */
+ODE_API void dJointAttach (dJointID, dBodyID body1, dBodyID body2);
+
+/**
+ * @brief Set the user-data pointer
+ * @ingroup joints
+ */
+ODE_API void dJointSetData (dJointID, void *data);
+
+/**
+ * @brief Get the user-data pointer
+ * @ingroup joints
+ */
+ODE_API void *dJointGetData (dJointID);
+
+/**
+ * @brief Get the type of the joint
+ * @ingroup joints
+ * @return the type, being one of these:
+ * \li JointTypeBall
+ * \li JointTypeHinge
+ * \li JointTypeSlider
+ * \li JointTypeContact
+ * \li JointTypeUniversal
+ * \li JointTypeHinge2
+ * \li JointTypeFixed
+ * \li JointTypeAMotor
+ * \li JointTypeLMotor
+ */
+ODE_API int dJointGetType (dJointID);
+
+/**
+ * @brief Return the bodies that this joint connects.
+ * @ingroup joints
+ * @param index return the first (0) or second (1) body.
+ * @remarks
+ * If one of these returned body IDs is zero, the joint connects the other body
+ * to the static environment.
+ * If both body IDs are zero, the joint is in ``limbo'' and has no effect on
+ * the simulation.
+ */
+ODE_API dBodyID dJointGetBody (dJointID, int index);
+
+/**
+ * @brief Sets the datastructure that is to receive the feedback.
+ *
+ * The feedback can be used by the user, so that it is known how
+ * much force an individual joint exerts.
+ * @ingroup joints
+ */
+ODE_API void dJointSetFeedback (dJointID, dJointFeedback *);
+
+/**
+ * @brief Gets the datastructure that is to receive the feedback.
+ * @ingroup joints
+ */
+ODE_API dJointFeedback *dJointGetFeedback (dJointID);
+
+/**
+ * @brief Set the joint anchor point.
+ * @ingroup joints
+ *
+ * The joint will try to keep this point on each body
+ * together. The input is specified in world coordinates.
+ */
+ODE_API void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Set the joint anchor point.
+ * @ingroup joints
+ */
+ODE_API void dJointSetBallAnchor2 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief Param setting for Ball joints
+ * @ingroup joints
+ */
+ODE_API void dJointSetBallParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Set hinge anchor parameter.
+ * @ingroup joints
+ */
+ODE_API void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z);
+
+ODE_API void dJointSetHingeAnchorDelta (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
+
+/**
+ * @brief Set hinge axis.
+ * @ingroup joints
+ */
+ODE_API void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ */
+ODE_API void dJointSetHingeParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Applies the torque about the hinge axis.
+ *
+ * That is, it applies a torque with specified magnitude in the direction
+ * of the hinge axis, to body 1, and with the same magnitude but in opposite
+ * direction to body 2. This function is just a wrapper for dBodyAddTorque()}
+ * @ingroup joints
+ */
+ODE_API void dJointAddHingeTorque(dJointID joint, dReal torque);
+
+/**
+ * @brief set the joint axis
+ * @ingroup joints
+ */
+ODE_API void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @ingroup joints
+ */
+ODE_API void dJointSetSliderAxisDelta (dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ */
+ODE_API void dJointSetSliderParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Applies the given force in the slider's direction.
+ *
+ * That is, it applies a force with specified magnitude, in the direction of
+ * slider's axis, to body1, and with the same magnitude but opposite
+ * direction to body2.  This function is just a wrapper for dBodyAddForce().
+ * @ingroup joints
+ */
+ODE_API void dJointAddSliderForce(dJointID joint, dReal force);
+
+/**
+ * @brief set anchor
+ * @ingroup joints
+ */
+ODE_API void dJointSetHinge2Anchor (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set axis
+ * @ingroup joints
+ */
+ODE_API void dJointSetHinge2Axis1 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set axis
+ * @ingroup joints
+ */
+ODE_API void dJointSetHinge2Axis2 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ */
+ODE_API void dJointSetHinge2Param (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Applies torque1 about the hinge2's axis 1, torque2 about the
+ * hinge2's axis 2.
+ * @remarks  This function is just a wrapper for dBodyAddTorque().
+ * @ingroup joints
+ */
+ODE_API void dJointAddHinge2Torques(dJointID joint, dReal torque1, dReal torque2);
+
+/**
+ * @brief set anchor
+ * @ingroup joints
+ */
+ODE_API void dJointSetUniversalAnchor (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set axis
+ * @ingroup joints
+ */
+ODE_API void dJointSetUniversalAxis1 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set axis
+ * @ingroup joints
+ */
+ODE_API void dJointSetUniversalAxis2 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ */
+ODE_API void dJointSetUniversalParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Applies torque1 about the universal's axis 1, torque2 about the
+ * universal's axis 2.
+ * @remarks This function is just a wrapper for dBodyAddTorque().
+ * @ingroup joints
+ */
+ODE_API void dJointAddUniversalTorques(dJointID joint, dReal torque1, dReal torque2);
+
+
+/**
+ * @brief set anchor
+ * @ingroup joints
+ */
+ODE_API void dJointSetPRAnchor (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set the axis for the prismatic articulation
+ * @ingroup joints
+ */
+ODE_API void dJointSetPRAxis1 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set the axis for the rotoide articulation
+ * @ingroup joints
+ */
+ODE_API void dJointSetPRAxis2 (dJointID, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ *
+ * @note parameterX where X equal 2 refer to parameter for the rotoide articulation
+ */
+ODE_API void dJointSetPRParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Applies the torque about the rotoide axis of the PR joint
+ *
+ * That is, it applies a torque with specified magnitude in the direction 
+ * of the rotoide axis, to body 1, and with the same magnitude but in opposite
+ * direction to body 2. This function is just a wrapper for dBodyAddTorque()}
+ * @ingroup joints
+ */
+ODE_API void dJointAddPRTorque (dJointID j, dReal torque);
+
+
+/**
+ * @brief Call this on the fixed joint after it has been attached to
+ * remember the current desired relative offset and desired relative
+ * rotation between the bodies.
+ * @ingroup joints
+ */
+ODE_API void dJointSetFixed (dJointID);
+
+/*
+ * @brief Sets joint parameter
+ *
+ * @ingroup joints
+ */
+ODE_API void dJointSetFixedParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief set the nr of axes
+ * @param num 0..3
+ * @ingroup joints
+ */
+ODE_API void dJointSetAMotorNumAxes (dJointID, int num);
+
+/**
+ * @brief set axis
+ * @ingroup joints
+ */
+ODE_API void dJointSetAMotorAxis (dJointID, int anum, int rel,
+			  dReal x, dReal y, dReal z);
+
+/**
+ * @brief Tell the AMotor what the current angle is along axis anum.
+ *
+ * This function should only be called in dAMotorUser mode, because in this
+ * mode the AMotor has no other way of knowing the joint angles.
+ * The angle information is needed if stops have been set along the axis,
+ * but it is not needed for axis motors.
+ * @ingroup joints
+ */
+ODE_API void dJointSetAMotorAngle (dJointID, int anum, dReal angle);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ */
+ODE_API void dJointSetAMotorParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief set mode
+ * @ingroup joints
+ */
+ODE_API void dJointSetAMotorMode (dJointID, int mode);
+
+/**
+ * @brief Applies torque0 about the AMotor's axis 0, torque1 about the
+ * AMotor's axis 1, and torque2 about the AMotor's axis 2.
+ * @remarks
+ * If the motor has fewer than three axes, the higher torques are ignored.
+ * This function is just a wrapper for dBodyAddTorque().
+ * @ingroup joints
+ */
+ODE_API void dJointAddAMotorTorques (dJointID, dReal torque1, dReal torque2, dReal torque3);
+
+/**
+ * @brief Set the number of axes that will be controlled by the LMotor.
+ * @param num can range from 0 (which effectively deactivates the joint) to 3.
+ * @ingroup joints
+ */
+ODE_API void dJointSetLMotorNumAxes (dJointID, int num);
+
+/**
+ * @brief Set the AMotor axes.
+ * @param anum selects the axis to change (0,1 or 2).
+ * @param rel Each axis can have one of three ``relative orientation'' modes
+ * \li 0: The axis is anchored to the global frame.
+ * \li 1: The axis is anchored to the first body.
+ * \li 2: The axis is anchored to the second body.
+ * @remarks The axis vector is always specified in global coordinates
+ * regardless of the setting of rel.
+ * @ingroup joints
+ */
+ODE_API void dJointSetLMotorAxis (dJointID, int anum, int rel, dReal x, dReal y, dReal z);
+
+/**
+ * @brief set joint parameter
+ * @ingroup joints
+ */
+ODE_API void dJointSetLMotorParam (dJointID, int parameter, dReal value);
+
+/**
+ * @ingroup joints
+ */
+ODE_API void dJointSetPlane2DXParam (dJointID, int parameter, dReal value);
+
+/**
+ * @ingroup joints
+ */
+
+ODE_API void dJointSetPlane2DYParam (dJointID, int parameter, dReal value);
+
+/**
+ * @ingroup joints
+ */
+ODE_API void dJointSetPlane2DAngleParam (dJointID, int parameter, dReal value);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ *
+ * This returns the point on body 1. If the joint is perfectly satisfied,
+ * this will be the same as the point on body 2.
+ */
+ODE_API void dJointGetBallAnchor (dJointID, dVector3 result);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ *
+ * This returns the point on body 2. You can think of a ball and socket
+ * joint as trying to keep the result of dJointGetBallAnchor() and
+ * dJointGetBallAnchor2() the same.  If the joint is perfectly satisfied,
+ * this function will return the same value as dJointGetBallAnchor() to
+ * within roundoff errors. dJointGetBallAnchor2() can be used, along with
+ * dJointGetBallAnchor(), to see how far the joint has come apart.
+ */
+ODE_API void dJointGetBallAnchor2 (dJointID, dVector3 result);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetBallParam (dJointID, int parameter);
+
+/**
+ * @brief Get the hinge anchor point, in world coordinates.
+ *
+ * This returns the point on body 1. If the joint is perfectly satisfied,
+ * this will be the same as the point on body 2.
+ * @ingroup joints
+ */
+ODE_API void dJointGetHingeAnchor (dJointID, dVector3 result);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ * @return The point on body 2. If the joint is perfectly satisfied,
+ * this will return the same value as dJointGetHingeAnchor().
+ * If not, this value will be slightly different.
+ * This can be used, for example, to see how far the joint has come apart.
+ * @ingroup joints
+ */
+ODE_API void dJointGetHingeAnchor2 (dJointID, dVector3 result);
+
+/**
+ * @brief get axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetHingeAxis (dJointID, dVector3 result);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHingeParam (dJointID, int parameter);
+
+/**
+ * @brief Get the hinge angle.
+ *
+ * The angle is measured between the two bodies, or between the body and
+ * the static environment.
+ * The angle will be between -pi..pi.
+ * When the hinge anchor or axis is set, the current position of the attached
+ * bodies is examined and that position will be the zero angle.
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHingeAngle (dJointID);
+
+/**
+ * @brief Get the hinge angle time derivative.
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHingeAngleRate (dJointID);
+
+/**
+ * @brief Get the slider linear position (i.e. the slider's extension)
+ *
+ * When the axis is set, the current position of the attached bodies is
+ * examined and that position will be the zero position.
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetSliderPosition (dJointID);
+
+/**
+ * @brief Get the slider linear position's time derivative.
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetSliderPositionRate (dJointID);
+
+/**
+ * @brief Get the slider axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetSliderAxis (dJointID, dVector3 result);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetSliderParam (dJointID, int parameter);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ * @return the point on body 1.  If the joint is perfectly satisfied,
+ * this will be the same as the point on body 2.
+ * @ingroup joints
+ */
+ODE_API void dJointGetHinge2Anchor (dJointID, dVector3 result);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ * This returns the point on body 2. If the joint is perfectly satisfied,
+ * this will return the same value as dJointGetHinge2Anchor.
+ * If not, this value will be slightly different.
+ * This can be used, for example, to see how far the joint has come apart.
+ * @ingroup joints
+ */
+ODE_API void dJointGetHinge2Anchor2 (dJointID, dVector3 result);
+
+/**
+ * @brief Get joint axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetHinge2Axis1 (dJointID, dVector3 result);
+
+/**
+ * @brief Get joint axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetHinge2Axis2 (dJointID, dVector3 result);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHinge2Param (dJointID, int parameter);
+
+/**
+ * @brief Get angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHinge2Angle1 (dJointID);
+
+/**
+ * @brief Get time derivative of angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHinge2Angle1Rate (dJointID);
+
+/**
+ * @brief Get time derivative of angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetHinge2Angle2Rate (dJointID);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ * @return the point on body 1. If the joint is perfectly satisfied,
+ * this will be the same as the point on body 2.
+ * @ingroup joints
+ */
+ODE_API void dJointGetUniversalAnchor (dJointID, dVector3 result);
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ * @return This returns the point on body 2.
+ * @remarks
+ * You can think of the ball and socket part of a universal joint as
+ * trying to keep the result of dJointGetBallAnchor() and
+ * dJointGetBallAnchor2() the same. If the joint is
+ * perfectly satisfied, this function will return the same value
+ * as dJointGetUniversalAnchor() to within roundoff errors.
+ * dJointGetUniversalAnchor2() can be used, along with
+ * dJointGetUniversalAnchor(), to see how far the joint has come apart.
+ * @ingroup joints
+ */
+ODE_API void dJointGetUniversalAnchor2 (dJointID, dVector3 result);
+
+/**
+ * @brief Get axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetUniversalAxis1 (dJointID, dVector3 result);
+
+/**
+ * @brief Get axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetUniversalAxis2 (dJointID, dVector3 result);
+
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetUniversalParam (dJointID, int parameter);
+
+/**
+ * @brief Get both angles at the same time.
+ * @ingroup joints
+ *
+ * @param joint   The universal joint for which we want to calculate the angles
+ * @param angle1  The angle between the body1 and the axis 1
+ * @param angle2  The angle between the body2 and the axis 2
+ *
+ * @note This function combine getUniversalAngle1 and getUniversalAngle2 together
+ *       and try to avoid redundant calculation
+ */
+ODE_API void dJointGetUniversalAngles (dJointID, dReal *angle1, dReal *angle2);
+
+/**
+ * @brief Get angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetUniversalAngle1 (dJointID);
+
+/**
+ * @brief Get angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetUniversalAngle2 (dJointID);
+
+/**
+ * @brief Get time derivative of angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetUniversalAngle1Rate (dJointID);
+
+/**
+ * @brief Get time derivative of angle
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetUniversalAngle2Rate (dJointID);
+
+
+
+/**
+ * @brief Get the joint anchor point, in world coordinates.
+ * @return the point on body 1. If the joint is perfectly satisfied, 
+ * this will be the same as the point on body 2.
+ * @ingroup joints
+ */
+ODE_API void dJointGetPRAnchor (dJointID, dVector3 result);
+
+/**
+ * @brief Get the PR linear position (i.e. the prismatic's extension)
+ *
+ * When the axis is set, the current position of the attached bodies is
+ * examined and that position will be the zero position.
+ *
+ * The position is the "oriented" length between the
+ * position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)]
+ *
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetPRPosition (dJointID);
+
+/**
+ * @brief Get the PR linear position's time derivative
+ *
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetPRPositionRate (dJointID);
+
+
+/**
+ * @brief Get the prismatic axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetPRAxis1 (dJointID, dVector3 result);
+
+/**
+ * @brief Get the Rotoide axis
+ * @ingroup joints
+ */
+ODE_API void dJointGetPRAxis2 (dJointID, dVector3 result);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetPRParam (dJointID, int parameter);
+
+
+
+/**
+ * @brief Get the number of angular axes that will be controlled by the
+ * AMotor.
+ * @param num can range from 0 (which effectively deactivates the
+ * joint) to 3.
+ * This is automatically set to 3 in dAMotorEuler mode.
+ * @ingroup joints
+ */
+ODE_API int dJointGetAMotorNumAxes (dJointID);
+
+/**
+ * @brief Get the AMotor axes.
+ * @param anum selects the axis to change (0,1 or 2).
+ * @param rel Each axis can have one of three ``relative orientation'' modes.
+ * \li 0: The axis is anchored to the global frame.
+ * \li 1: The axis is anchored to the first body.
+ * \li 2: The axis is anchored to the second body.
+ * @ingroup joints
+ */
+ODE_API void dJointGetAMotorAxis (dJointID, int anum, dVector3 result);
+
+/**
+ * @brief Get axis
+ * @remarks
+ * The axis vector is always specified in global coordinates regardless
+ * of the setting of rel.
+ * There are two GetAMotorAxis functions, one to return the axis and one to
+ * return the relative mode.
+ *
+ * For dAMotorEuler mode:
+ * \li	Only axes 0 and 2 need to be set. Axis 1 will be determined
+	automatically at each time step.
+ * \li	Axes 0 and 2 must be perpendicular to each other.
+ * \li	Axis 0 must be anchored to the first body, axis 2 must be anchored
+	to the second body.
+ * @ingroup joints
+ */
+ODE_API int dJointGetAMotorAxisRel (dJointID, int anum);
+
+/**
+ * @brief Get the current angle for axis.
+ * @remarks
+ * In dAMotorUser mode this is simply the value that was set with
+ * dJointSetAMotorAngle().
+ * In dAMotorEuler mode this is the corresponding euler angle.
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetAMotorAngle (dJointID, int anum);
+
+/**
+ * @brief Get the current angle rate for axis anum.
+ * @remarks
+ * In dAMotorUser mode this is always zero, as not enough information is
+ * available.
+ * In dAMotorEuler mode this is the corresponding euler angle rate.
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetAMotorAngleRate (dJointID, int anum);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetAMotorParam (dJointID, int parameter);
+
+/**
+ * @brief Get the angular motor mode.
+ * @param mode must be one of the following constants:
+ * \li dAMotorUser The AMotor axes and joint angle settings are entirely
+ * controlled by the user.  This is the default mode.
+ * \li dAMotorEuler Euler angles are automatically computed.
+ * The axis a1 is also automatically computed.
+ * The AMotor axes must be set correctly when in this mode,
+ * as described below.
+ * When this mode is initially set the current relative orientations
+ * of the bodies will correspond to all euler angles at zero.
+ * @ingroup joints
+ */
+ODE_API int dJointGetAMotorMode (dJointID);
+
+/**
+ * @brief Get nr of axes.
+ * @ingroup joints
+ */
+ODE_API int dJointGetLMotorNumAxes (dJointID);
+
+/**
+ * @brief Get axis.
+ * @ingroup joints
+ */
+ODE_API void dJointGetLMotorAxis (dJointID, int anum, dVector3 result);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetLMotorParam (dJointID, int parameter);
+
+/**
+ * @brief get joint parameter
+ * @ingroup joints
+ */
+ODE_API dReal dJointGetFixedParam (dJointID, int parameter);
+
+
+/**
+ * @ingroup joints
+ */
+ODE_API dJointID dConnectingJoint (dBodyID, dBodyID);
+
+/**
+ * @ingroup joints
+ */
+ODE_API int dConnectingJointList (dBodyID, dBodyID, dJointID*);
+
+/**
+ * @brief Utility function
+ * @return 1 if the two bodies are connected together by
+ * a joint, otherwise return 0.
+ * @ingroup joints
+ */
+ODE_API int dAreConnected (dBodyID, dBodyID);
+
+/**
+ * @brief Utility function
+ * @return 1 if the two bodies are connected together by
+ * a joint that does not have type @arg{joint_type}, otherwise return 0.
+ * @param body1 A body to check.
+ * @param body2 A body to check.
+ * @param joint_type is a dJointTypeXXX constant.
+ * This is useful for deciding whether to add contact joints between two bodies:
+ * if they are already connected by non-contact joints then it may not be
+ * appropriate to add contacts, however it is okay to add more contact between-
+ * bodies that already have contacts.
+ * @ingroup joints
+ */
+ODE_API int dAreConnectedExcluding (dBodyID body1, dBodyID body2, int joint_type);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/ode.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/ode.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/ode.h	(revision 216)
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_ODE_H_
+#define _ODE_ODE_H_
+
+/* include *everything* here */
+
+#include <ode/config.h>
+#include <ode/compatibility.h>
+#include <ode/common.h>
+#include <ode/contact.h>
+#include <ode/error.h>
+#include <ode/memory.h>
+#include <ode/odemath.h>
+#include <ode/matrix.h>
+#include <ode/timer.h>
+#include <ode/rotation.h>
+#include <ode/mass.h>
+#include <ode/misc.h>
+#include <ode/objects.h>
+#include <ode/odecpp.h>
+#include <ode/collision_space.h>
+#include <ode/collision.h>
+#include <ode/odecpp_collision.h>
+#include <ode/export-dif.h>
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/odecpp.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/odecpp.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/odecpp.h	(revision 216)
@@ -0,0 +1,712 @@
+/*************************************************************************
+ *									 *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.	 *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org 	 *
+ *									 *
+ * This library is free software; you can redistribute it and/or	 *
+ * modify it under the terms of EITHER: 				 *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *	 Software Foundation; either version 2.1 of the License, or (at  *
+ *	 your option) any later version. The text of the GNU Lesser	 *
+ *	 General Public License is included with this library in the	 *
+ *	 file LICENSE.TXT.						 *
+ *   (2) The BSD-style license that is included with this library in	 *
+ *	 the file LICENSE-BSD.TXT.					 *
+ *									 *
+ * This library is distributed in the hope that it will be useful,	 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of	 *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files	 *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.			 *
+ *									 *
+ *************************************************************************/
+
+/* C++ interface for non-collision stuff */
+
+
+#ifndef _ODE_ODECPP_H_
+#define _ODE_ODECPP_H_
+#ifdef __cplusplus
+
+#include <ode/error.h>
+
+
+class dWorld {
+  dWorldID _id;
+
+  // intentionally undefined, don't use these
+  dWorld (const dWorld &);
+  void operator= (const dWorld &);
+
+public:
+  dWorld()
+    { _id = dWorldCreate(); }
+  ~dWorld()
+    { dWorldDestroy (_id); }
+
+  dWorldID id() const
+    { return _id; }
+  operator dWorldID() const
+    { return _id; }
+
+  void setGravity (dReal x, dReal y, dReal z)
+    { dWorldSetGravity (_id,x,y,z); }
+  void getGravity (dVector3 g) const
+    { dWorldGetGravity (_id,g); }
+
+  void setERP (dReal erp)
+    { dWorldSetERP(_id, erp); }
+  dReal getERP() const
+    { return dWorldGetERP(_id); }
+
+  void setCFM (dReal cfm)
+    { dWorldSetCFM(_id, cfm); }
+  dReal getCFM() const
+    { return dWorldGetCFM(_id); }
+
+  void step (dReal stepsize)
+    { dWorldStep (_id,stepsize); }
+
+  void stepFast1 (dReal stepsize, int maxiterations)
+    { dWorldStepFast1 (_id,stepsize,maxiterations); }
+  void setAutoEnableDepthSF1(dWorldID, int depth)
+    { dWorldSetAutoEnableDepthSF1 (_id, depth); }
+  int getAutoEnableDepthSF1(dWorldID)
+    { return dWorldGetAutoEnableDepthSF1 (_id); }
+
+  void  setAutoDisableLinearThreshold (dReal threshold) 
+    { dWorldSetAutoDisableLinearThreshold (_id,threshold); }
+  dReal getAutoDisableLinearThreshold()
+    { return dWorldGetAutoDisableLinearThreshold (_id); }
+  void setAutoDisableAngularThreshold (dReal threshold)
+    { dWorldSetAutoDisableAngularThreshold (_id,threshold); }
+  dReal getAutoDisableAngularThreshold()
+    { return dWorldGetAutoDisableAngularThreshold (_id); }
+  void setAutoDisableSteps (int steps)
+    { dWorldSetAutoDisableSteps (_id,steps); }
+  int getAutoDisableSteps()
+    { return dWorldGetAutoDisableSteps (_id); }
+  void setAutoDisableTime (dReal time)
+    { dWorldSetAutoDisableTime (_id,time); }
+  dReal getAutoDisableTime()
+    { return dWorldGetAutoDisableTime (_id); }
+  void setAutoDisableFlag (int do_auto_disable)
+    { dWorldSetAutoDisableFlag (_id,do_auto_disable); }
+  int getAutoDisableFlag()
+    { return dWorldGetAutoDisableFlag (_id); }
+
+  void impulseToForce (dReal stepsize, dReal ix, dReal iy, dReal iz,
+		       dVector3 force)
+    { dWorldImpulseToForce (_id,stepsize,ix,iy,iz,force); }
+};
+
+
+class dBody {
+  dBodyID _id;
+
+  // intentionally undefined, don't use these
+  dBody (const dBody &);
+  void operator= (const dBody &);
+
+public:
+  dBody()
+    { _id = 0; }
+  dBody (dWorldID world)
+    { _id = dBodyCreate (world); }
+  ~dBody()
+    { if (_id) dBodyDestroy (_id); }
+
+  void create (dWorldID world) {
+    if (_id) dBodyDestroy (_id);
+    _id = dBodyCreate (world);
+  }
+
+  dBodyID id() const
+    { return _id; }
+  operator dBodyID() const
+    { return _id; }
+
+  void setData (void *data)
+    { dBodySetData (_id,data); }
+  void *getData() const
+    { return dBodyGetData (_id); }
+
+  void setPosition (dReal x, dReal y, dReal z)
+    { dBodySetPosition (_id,x,y,z); }
+  void setRotation (const dMatrix3 R)
+    { dBodySetRotation (_id,R); }
+  void setQuaternion (const dQuaternion q)
+    { dBodySetQuaternion (_id,q); }
+  void setLinearVel  (dReal x, dReal y, dReal z)
+    { dBodySetLinearVel (_id,x,y,z); }
+  void setAngularVel (dReal x, dReal y, dReal z)
+    { dBodySetAngularVel (_id,x,y,z); }
+
+  const dReal * getPosition() const
+    { return dBodyGetPosition (_id); }
+  const dReal * getRotation() const
+    { return dBodyGetRotation (_id); }
+  const dReal * getQuaternion() const
+    { return dBodyGetQuaternion (_id); }
+  const dReal * getLinearVel() const
+    { return dBodyGetLinearVel (_id); }
+  const dReal * getAngularVel() const
+    { return dBodyGetAngularVel (_id); }
+
+  void setMass (const dMass *mass)
+    { dBodySetMass (_id,mass); }
+  void getMass (dMass *mass) const
+    { dBodyGetMass (_id,mass); }
+
+  void addForce (dReal fx, dReal fy, dReal fz)
+    { dBodyAddForce (_id, fx, fy, fz); }
+  void addTorque (dReal fx, dReal fy, dReal fz)
+    { dBodyAddTorque (_id, fx, fy, fz); }
+  void addRelForce (dReal fx, dReal fy, dReal fz)
+    { dBodyAddRelForce (_id, fx, fy, fz); }
+  void addRelTorque (dReal fx, dReal fy, dReal fz)
+    { dBodyAddRelTorque (_id, fx, fy, fz); }
+  void addForceAtPos (dReal fx, dReal fy, dReal fz,
+		      dReal px, dReal py, dReal pz)
+    { dBodyAddForceAtPos (_id, fx, fy, fz, px, py, pz); }
+  void addForceAtRelPos (dReal fx, dReal fy, dReal fz,
+		      dReal px, dReal py, dReal pz)
+    { dBodyAddForceAtRelPos (_id, fx, fy, fz, px, py, pz); }
+  void addRelForceAtPos (dReal fx, dReal fy, dReal fz,
+			 dReal px, dReal py, dReal pz)
+    { dBodyAddRelForceAtPos (_id, fx, fy, fz, px, py, pz); }
+  void addRelForceAtRelPos (dReal fx, dReal fy, dReal fz,
+			    dReal px, dReal py, dReal pz)
+    { dBodyAddRelForceAtRelPos (_id, fx, fy, fz, px, py, pz); }
+
+  const dReal * getForce() const
+    { return dBodyGetForce(_id); }
+  const dReal * getTorque() const
+    { return dBodyGetTorque(_id); }
+  void setForce (dReal x, dReal y, dReal z)
+    { dBodySetForce (_id,x,y,z); }
+  void setTorque (dReal x, dReal y, dReal z)
+    { dBodySetTorque (_id,x,y,z); }
+
+  void enable()
+    { dBodyEnable (_id); }
+  void disable()
+    { dBodyDisable (_id); }
+  int isEnabled() const
+    { return dBodyIsEnabled (_id); }
+
+  void getRelPointPos (dReal px, dReal py, dReal pz, dVector3 result) const
+    { dBodyGetRelPointPos (_id, px, py, pz, result); }
+  void getRelPointVel (dReal px, dReal py, dReal pz, dVector3 result) const
+    { dBodyGetRelPointVel (_id, px, py, pz, result); }
+  void getPointVel (dReal px, dReal py, dReal pz, dVector3 result) const
+    { dBodyGetPointVel (_id,px,py,pz,result); }
+  void getPosRelPoint (dReal px, dReal py, dReal pz, dVector3 result) const
+    { dBodyGetPosRelPoint (_id,px,py,pz,result); }
+  void vectorToWorld (dReal px, dReal py, dReal pz, dVector3 result) const
+    { dBodyVectorToWorld (_id,px,py,pz,result); }
+  void vectorFromWorld (dReal px, dReal py, dReal pz, dVector3 result) const
+    { dBodyVectorFromWorld (_id,px,py,pz,result); }
+
+  void setFiniteRotationMode (int mode)
+    { dBodySetFiniteRotationMode (_id, mode); }
+  void setFiniteRotationAxis (dReal x, dReal y, dReal z)
+    { dBodySetFiniteRotationAxis (_id, x, y, z); }
+
+  int getFiniteRotationMode() const
+    { return dBodyGetFiniteRotationMode (_id); }
+  void getFiniteRotationAxis (dVector3 result) const
+    { dBodyGetFiniteRotationAxis (_id, result); }
+
+  int getNumJoints() const
+    { return dBodyGetNumJoints (_id); }
+  dJointID getJoint (int index) const
+    { return dBodyGetJoint (_id, index); }
+
+  void setGravityMode (int mode)
+    { dBodySetGravityMode (_id,mode); }
+  int getGravityMode() const
+    { return dBodyGetGravityMode (_id); }
+
+  int isConnectedTo (dBodyID body) const
+    { return dAreConnected (_id, body); }
+
+  void  setAutoDisableLinearThreshold (dReal threshold) 
+    { dBodySetAutoDisableLinearThreshold (_id,threshold); }
+  dReal getAutoDisableLinearThreshold()
+    { return dBodyGetAutoDisableLinearThreshold (_id); }
+  void setAutoDisableAngularThreshold (dReal threshold)
+    { dBodySetAutoDisableAngularThreshold (_id,threshold); }
+  dReal getAutoDisableAngularThreshold()
+    { return dBodyGetAutoDisableAngularThreshold (_id); }
+  void setAutoDisableSteps (int steps)
+    { dBodySetAutoDisableSteps (_id,steps); }
+  int getAutoDisableSteps()
+    { return dBodyGetAutoDisableSteps (_id); }
+  void setAutoDisableTime (dReal time)
+    { dBodySetAutoDisableTime (_id,time); }
+  dReal getAutoDisableTime()
+    { return dBodyGetAutoDisableTime (_id); }
+  void setAutoDisableFlag (int do_auto_disable)
+    { dBodySetAutoDisableFlag (_id,do_auto_disable); }
+  int getAutoDisableFlag()
+    { return dBodyGetAutoDisableFlag (_id); }
+};
+
+
+class dJointGroup {
+  dJointGroupID _id;
+
+  // intentionally undefined, don't use these
+  dJointGroup (const dJointGroup &);
+  void operator= (const dJointGroup &);
+
+public:
+  dJointGroup (int dummy_arg=0)
+    { _id = dJointGroupCreate (0); }
+  ~dJointGroup()
+    { dJointGroupDestroy (_id); }
+  void create (int dummy_arg=0) {
+    if (_id) dJointGroupDestroy (_id);
+    _id = dJointGroupCreate (0);
+  }
+
+  dJointGroupID id() const
+    { return _id; }
+  operator dJointGroupID() const
+    { return _id; }
+
+  void empty()
+    { dJointGroupEmpty (_id); }
+};
+
+
+class dJoint {
+private:
+  // intentionally undefined, don't use these
+  dJoint (const dJoint &) ;
+  void operator= (const dJoint &);
+
+protected:
+  dJointID _id;
+
+public:
+  dJoint()
+    { _id = 0; }
+  ~dJoint()
+    { if (_id) dJointDestroy (_id); }
+
+  dJointID id() const
+    { return _id; }
+  operator dJointID() const
+    { return _id; }
+
+  void attach (dBodyID body1, dBodyID body2)
+    { dJointAttach (_id, body1, body2); }
+
+  void setData (void *data)
+    { dJointSetData (_id, data); }
+  void *getData() const
+    { return dJointGetData (_id); }
+
+  int getType() const
+    { return dJointGetType (_id); }
+
+  dBodyID getBody (int index) const
+    { return dJointGetBody (_id, index); }
+
+  void setFeedback(dJointFeedback *fb)
+    { dJointSetFeedback(_id, fb); }
+  dJointFeedback *getFeedback() const
+    { return dJointGetFeedback(_id); }
+};
+
+
+class dBallJoint : public dJoint {
+private:
+  // intentionally undefined, don't use these
+  dBallJoint (const dBallJoint &);
+  void operator= (const dBallJoint &);
+
+public:
+  dBallJoint() { }
+  dBallJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateBall (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateBall (world, group);
+  }
+
+  void setAnchor (dReal x, dReal y, dReal z)
+    { dJointSetBallAnchor (_id, x, y, z); }
+  void getAnchor (dVector3 result) const
+    { dJointGetBallAnchor (_id, result); }
+  void getAnchor2 (dVector3 result) const
+    { dJointGetBallAnchor2 (_id, result); }
+  void setParam (int parameter, dReal value)
+    { dJointSetBallParam (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetBallParam (_id, parameter); }
+} ;
+
+
+class dHingeJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dHingeJoint (const dHingeJoint &);
+  void operator = (const dHingeJoint &);
+
+public:
+  dHingeJoint() { }
+  dHingeJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateHinge (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateHinge (world, group);
+  }
+
+  void setAnchor (dReal x, dReal y, dReal z)
+    { dJointSetHingeAnchor (_id, x, y, z); }
+  void getAnchor (dVector3 result) const
+    { dJointGetHingeAnchor (_id, result); }
+  void getAnchor2 (dVector3 result) const
+    { dJointGetHingeAnchor2 (_id, result); }
+
+  void setAxis (dReal x, dReal y, dReal z)
+    { dJointSetHingeAxis (_id, x, y, z); }
+  void getAxis (dVector3 result) const
+    { dJointGetHingeAxis (_id, result); }
+
+  dReal getAngle() const
+    { return dJointGetHingeAngle (_id); }
+  dReal getAngleRate() const
+    { return dJointGetHingeAngleRate (_id); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetHingeParam (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetHingeParam (_id, parameter); }
+
+  void addTorque (dReal torque)
+	{ dJointAddHingeTorque(_id, torque); }
+};
+
+
+class dSliderJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dSliderJoint (const dSliderJoint &);
+  void operator = (const dSliderJoint &);
+
+public:
+  dSliderJoint() { }
+  dSliderJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateSlider (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateSlider (world, group);
+  }
+
+  void setAxis (dReal x, dReal y, dReal z)
+    { dJointSetSliderAxis (_id, x, y, z); }
+  void getAxis (dVector3 result) const
+    { dJointGetSliderAxis (_id, result); }
+
+  dReal getPosition() const
+    { return dJointGetSliderPosition (_id); }
+  dReal getPositionRate() const
+    { return dJointGetSliderPositionRate (_id); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetSliderParam (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetSliderParam (_id, parameter); }
+
+  void addForce (dReal force)
+	{ dJointAddSliderForce(_id, force); }
+};
+
+
+class dUniversalJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dUniversalJoint (const dUniversalJoint &);
+  void operator = (const dUniversalJoint &);
+
+public:
+  dUniversalJoint() { }
+  dUniversalJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateUniversal (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateUniversal (world, group);
+  }
+
+  void setAnchor (dReal x, dReal y, dReal z)
+    { dJointSetUniversalAnchor (_id, x, y, z); }
+  void setAxis1 (dReal x, dReal y, dReal z)
+    { dJointSetUniversalAxis1 (_id, x, y, z); }
+  void setAxis2 (dReal x, dReal y, dReal z)
+    { dJointSetUniversalAxis2 (_id, x, y, z); }
+  void setParam (int parameter, dReal value)
+    { dJointSetUniversalParam (_id, parameter, value); }
+
+  void getAnchor (dVector3 result) const
+    { dJointGetUniversalAnchor (_id, result); }
+  void getAnchor2 (dVector3 result) const
+    { dJointGetUniversalAnchor2 (_id, result); }
+  void getAxis1 (dVector3 result) const
+    { dJointGetUniversalAxis1 (_id, result); }
+  void getAxis2 (dVector3 result) const
+    { dJointGetUniversalAxis2 (_id, result); }
+  dReal getParam (int parameter) const
+    { return dJointGetUniversalParam (_id, parameter); }
+ void getAngles(dReal *angle1, dReal *angle2) const
+    { dJointGetUniversalAngles (_id, angle1, angle2); }
+
+  dReal getAngle1() const
+    { return dJointGetUniversalAngle1 (_id); }
+  dReal getAngle1Rate() const
+    { return dJointGetUniversalAngle1Rate (_id); }
+  dReal getAngle2() const
+    { return dJointGetUniversalAngle2 (_id); }
+  dReal getAngle2Rate() const
+    { return dJointGetUniversalAngle2Rate (_id); }
+
+  void addTorques (dReal torque1, dReal torque2)
+	{ dJointAddUniversalTorques(_id, torque1, torque2); }
+};
+
+
+class dHinge2Joint : public dJoint {
+  // intentionally undefined, don't use these
+  dHinge2Joint (const dHinge2Joint &);
+  void operator = (const dHinge2Joint &);
+
+public:
+  dHinge2Joint() { }
+  dHinge2Joint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateHinge2 (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateHinge2 (world, group);
+  }
+
+  void setAnchor (dReal x, dReal y, dReal z)
+    { dJointSetHinge2Anchor (_id, x, y, z); }
+  void setAxis1 (dReal x, dReal y, dReal z)
+    { dJointSetHinge2Axis1 (_id, x, y, z); }
+  void setAxis2 (dReal x, dReal y, dReal z)
+    { dJointSetHinge2Axis2 (_id, x, y, z); }
+
+  void getAnchor (dVector3 result) const
+    { dJointGetHinge2Anchor (_id, result); }
+  void getAnchor2 (dVector3 result) const
+    { dJointGetHinge2Anchor2 (_id, result); }
+  void getAxis1 (dVector3 result) const
+    { dJointGetHinge2Axis1 (_id, result); }
+  void getAxis2 (dVector3 result) const
+    { dJointGetHinge2Axis2 (_id, result); }
+
+  dReal getAngle1() const
+    { return dJointGetHinge2Angle1 (_id); }
+  dReal getAngle1Rate() const
+    { return dJointGetHinge2Angle1Rate (_id); }
+  dReal getAngle2Rate() const
+    { return dJointGetHinge2Angle2Rate (_id); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetHinge2Param (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetHinge2Param (_id, parameter); }
+
+  void addTorques(dReal torque1, dReal torque2)
+	{ dJointAddHinge2Torques(_id, torque1, torque2); }
+};
+
+
+class dPRJoint : public dJoint {
+  dPRJoint (const dPRJoint &);
+  void operator = (const dPRJoint &);
+
+public:
+  dPRJoint() { }
+  dPRJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreatePR (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreatePR (world, group);
+  }
+
+  void setAnchor (dReal x, dReal y, dReal z)
+    { dJointSetPRAnchor (_id, x, y, z); }
+  void setAxis1 (dReal x, dReal y, dReal z)
+    { dJointSetPRAxis1 (_id, x, y, z); }
+  void setAxis2 (dReal x, dReal y, dReal z)
+    { dJointSetPRAxis2 (_id, x, y, z); }
+
+  void getAnchor (dVector3 result) const
+    { dJointGetPRAnchor (_id, result); }
+  void getAxis1 (dVector3 result) const
+    { dJointGetPRAxis1 (_id, result); }
+  void getAxis2 (dVector3 result) const
+    { dJointGetPRAxis2 (_id, result); }
+
+  dReal getPosition() const
+    { return dJointGetPRPosition (_id); }
+  dReal getPositionRate() const
+    { return dJointGetPRPositionRate (_id); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetPRParam (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetPRParam (_id, parameter); }
+};
+
+
+class dFixedJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dFixedJoint (const dFixedJoint &);
+  void operator = (const dFixedJoint &);
+
+public:
+  dFixedJoint() { }
+  dFixedJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateFixed (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateFixed (world, group);
+  }
+
+  void set()
+    { dJointSetFixed (_id); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetFixedParam (_id, parameter, value); }
+
+  dReal getParam (int parameter) const
+    { return dJointGetFixedParam (_id, parameter); }
+};
+
+
+class dContactJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dContactJoint (const dContactJoint &);
+  void operator = (const dContactJoint &);
+
+public:
+  dContactJoint() { }
+  dContactJoint (dWorldID world, dJointGroupID group, dContact *contact)
+    { _id = dJointCreateContact (world, group, contact); }
+
+  void create (dWorldID world, dJointGroupID group, dContact *contact) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateContact (world, group, contact);
+  }
+};
+
+
+class dNullJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dNullJoint (const dNullJoint &);
+  void operator = (const dNullJoint &);
+
+public:
+  dNullJoint() { }
+  dNullJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateNull (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateNull (world, group);
+  }
+};
+
+
+class dAMotorJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dAMotorJoint (const dAMotorJoint &);
+  void operator = (const dAMotorJoint &);
+
+public:
+  dAMotorJoint() { }
+  dAMotorJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateAMotor (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateAMotor (world, group);
+  }
+
+  void setMode (int mode)
+    { dJointSetAMotorMode (_id, mode); }
+  int getMode() const
+    { return dJointGetAMotorMode (_id); }
+
+  void setNumAxes (int num)
+    { dJointSetAMotorNumAxes (_id, num); }
+  int getNumAxes() const
+    { return dJointGetAMotorNumAxes (_id); }
+
+  void setAxis (int anum, int rel, dReal x, dReal y, dReal z)
+    { dJointSetAMotorAxis (_id, anum, rel, x, y, z); }
+  void getAxis (int anum, dVector3 result) const
+    { dJointGetAMotorAxis (_id, anum, result); }
+  int getAxisRel (int anum) const
+    { return dJointGetAMotorAxisRel (_id, anum); }
+
+  void setAngle (int anum, dReal angle)
+    { dJointSetAMotorAngle (_id, anum, angle); }
+  dReal getAngle (int anum) const
+    { return dJointGetAMotorAngle (_id, anum); }
+  dReal getAngleRate (int anum)
+    { return dJointGetAMotorAngleRate (_id,anum); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetAMotorParam (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetAMotorParam (_id, parameter); }
+
+  void addTorques(dReal torque1, dReal torque2, dReal torque3)
+	{ dJointAddAMotorTorques(_id, torque1, torque2, torque3); }
+};
+
+
+class dLMotorJoint : public dJoint {
+  // intentionally undefined, don't use these
+  dLMotorJoint (const dLMotorJoint &);
+  void operator = (const dLMotorJoint &);
+
+public:
+  dLMotorJoint() { }
+  dLMotorJoint (dWorldID world, dJointGroupID group=0)
+    { _id = dJointCreateLMotor (world, group); }
+
+  void create (dWorldID world, dJointGroupID group=0) {
+    if (_id) dJointDestroy (_id);
+    _id = dJointCreateLMotor (world, group);
+  }
+
+  void setNumAxes (int num)
+    { dJointSetLMotorNumAxes (_id, num); }
+  int getNumAxes() const
+    { return dJointGetLMotorNumAxes (_id); }
+
+  void setAxis (int anum, int rel, dReal x, dReal y, dReal z)
+    { dJointSetLMotorAxis (_id, anum, rel, x, y, z); }
+  void getAxis (int anum, dVector3 result) const
+    { dJointGetLMotorAxis (_id, anum, result); }
+
+  void setParam (int parameter, dReal value)
+    { dJointSetLMotorParam (_id, parameter, value); }
+  dReal getParam (int parameter) const
+    { return dJointGetLMotorParam (_id, parameter); }
+};
+
+
+
+#endif
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/odecpp_collision.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/odecpp_collision.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/odecpp_collision.h	(revision 216)
@@ -0,0 +1,346 @@
+/*************************************************************************
+ *									 *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.	 *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org 	 *
+ *									 *
+ * This library is free software; you can redistribute it and/or	 *
+ * modify it under the terms of EITHER: 				 *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *	 Software Foundation; either version 2.1 of the License, or (at  *
+ *	 your option) any later version. The text of the GNU Lesser	 *
+ *	 General Public License is included with this library in the	 *
+ *	 file LICENSE.TXT.						 *
+ *   (2) The BSD-style license that is included with this library in	 *
+ *	 the file LICENSE-BSD.TXT.					 *
+ *									 *
+ * This library is distributed in the hope that it will be useful,	 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of	 *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files	 *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.			 *
+ *									 *
+ *************************************************************************/
+
+/* C++ interface for new collision API */
+
+
+#ifndef _ODE_ODECPP_COLLISION_H_
+#define _ODE_ODECPP_COLLISION_H_
+#ifdef __cplusplus
+
+#include <ode/error.h>
+
+
+class dGeom {
+  // intentionally undefined, don't use these
+  dGeom (dGeom &);
+  void operator= (dGeom &);
+
+protected:
+  dGeomID _id;
+
+public:
+  dGeom()
+    { _id = 0; }
+  ~dGeom()
+    { if (_id) dGeomDestroy (_id); }
+
+  dGeomID id() const
+    { return _id; }
+  operator dGeomID() const
+    { return _id; }
+
+  void destroy() {
+    if (_id) dGeomDestroy (_id);
+    _id = 0;
+  }
+
+  int getClass() const
+    { return dGeomGetClass (_id); }
+
+  dSpaceID getSpace() const
+    { return dGeomGetSpace (_id); }
+
+  void setData (void *data)
+    { dGeomSetData (_id,data); }
+  void *getData() const
+    { return dGeomGetData (_id); }
+
+  void setBody (dBodyID b)
+    { dGeomSetBody (_id,b); }
+  dBodyID getBody() const
+    { return dGeomGetBody (_id); }
+
+  void setPosition (dReal x, dReal y, dReal z)
+    { dGeomSetPosition (_id,x,y,z); }
+  const dReal * getPosition() const
+    { return dGeomGetPosition (_id); }
+
+  void setRotation (const dMatrix3 R)
+    { dGeomSetRotation (_id,R); }
+  const dReal * getRotation() const
+    { return dGeomGetRotation (_id); }
+    
+  void setQuaternion (const dQuaternion quat)
+    { dGeomSetQuaternion (_id,quat); }
+  void getQuaternion (dQuaternion quat) const
+    { dGeomGetQuaternion (_id,quat); }
+
+  void getAABB (dReal aabb[6]) const
+    { dGeomGetAABB (_id, aabb); }
+
+  int isSpace()
+    { return dGeomIsSpace (_id); }
+
+  void setCategoryBits (unsigned long bits)
+    { dGeomSetCategoryBits (_id, bits); }
+  void setCollideBits (unsigned long bits)
+    { dGeomSetCollideBits (_id, bits); }
+  unsigned long getCategoryBits()
+    { return dGeomGetCategoryBits (_id); }
+  unsigned long getCollideBits()
+    { return dGeomGetCollideBits (_id); }
+
+  void enable()
+    { dGeomEnable (_id); }
+  void disable()
+    { dGeomDisable (_id); }
+  int isEnabled()
+    { return dGeomIsEnabled (_id); }
+
+  void collide2 (dGeomID g, void *data, dNearCallback *callback)
+    { dSpaceCollide2 (_id,g,data,callback); }
+};
+
+
+class dSpace : public dGeom {
+  // intentionally undefined, don't use these
+  dSpace (dSpace &);
+  void operator= (dSpace &);
+
+protected:
+  // the default constructor is protected so that you
+  // can't instance this class. you must instance one
+  // of its subclasses instead.
+  dSpace () { _id = 0; }
+
+public:
+  dSpaceID id() const
+    { return (dSpaceID) _id; }
+  operator dSpaceID() const
+    { return (dSpaceID) _id; }
+
+  void setCleanup (int mode)
+    { dSpaceSetCleanup (id(), mode); }
+  int getCleanup()
+    { return dSpaceGetCleanup (id()); }
+
+  void add (dGeomID x)
+    { dSpaceAdd (id(), x); }
+  void remove (dGeomID x)
+    { dSpaceRemove (id(), x); }
+  int query (dGeomID x)
+    { return dSpaceQuery (id(),x); }
+
+  int getNumGeoms()
+    { return dSpaceGetNumGeoms (id()); }
+  dGeomID getGeom (int i)
+    { return dSpaceGetGeom (id(),i); }
+
+  void collide (void *data, dNearCallback *callback)
+    { dSpaceCollide (id(),data,callback); }
+};
+
+
+class dSimpleSpace : public dSpace {
+  // intentionally undefined, don't use these
+  dSimpleSpace (dSimpleSpace &);
+  void operator= (dSimpleSpace &);
+
+public:
+  dSimpleSpace (dSpaceID space)
+    { _id = (dGeomID) dSimpleSpaceCreate (space); }
+};
+
+
+class dHashSpace : public dSpace {
+  // intentionally undefined, don't use these
+  dHashSpace (dHashSpace &);
+  void operator= (dHashSpace &);
+
+public:
+  dHashSpace (dSpaceID space)
+    { _id = (dGeomID) dHashSpaceCreate (space); }
+  void setLevels (int minlevel, int maxlevel)
+    { dHashSpaceSetLevels (id(),minlevel,maxlevel); }
+};
+
+
+class dQuadTreeSpace : public dSpace {
+  // intentionally undefined, don't use these
+  dQuadTreeSpace (dQuadTreeSpace &);
+  void operator= (dQuadTreeSpace &);
+
+public:
+  dQuadTreeSpace (dSpaceID space, dVector3 center, dVector3 extents, int depth)
+    { _id = (dGeomID) dQuadTreeSpaceCreate (space,center,extents,depth); }
+};
+
+
+class dSphere : public dGeom {
+  // intentionally undefined, don't use these
+  dSphere (dSphere &);
+  void operator= (dSphere &);
+
+public:
+  dSphere () { }
+  dSphere (dSpaceID space, dReal radius)
+    { _id = dCreateSphere (space, radius); }
+
+  void create (dSpaceID space, dReal radius) {
+    if (_id) dGeomDestroy (_id);
+    _id = dCreateSphere (space, radius);
+  }
+
+  void setRadius (dReal radius)
+    { dGeomSphereSetRadius (_id, radius); }
+  dReal getRadius() const
+    { return dGeomSphereGetRadius (_id); }
+};
+
+
+class dBox : public dGeom {
+  // intentionally undefined, don't use these
+  dBox (dBox &);
+  void operator= (dBox &);
+
+public:
+  dBox () { }
+  dBox (dSpaceID space, dReal lx, dReal ly, dReal lz)
+    { _id = dCreateBox (space,lx,ly,lz); }
+
+  void create (dSpaceID space, dReal lx, dReal ly, dReal lz) {
+    if (_id) dGeomDestroy (_id);
+    _id = dCreateBox (space,lx,ly,lz);
+  }
+
+  void setLengths (dReal lx, dReal ly, dReal lz)
+    { dGeomBoxSetLengths (_id, lx, ly, lz); }
+  void getLengths (dVector3 result) const
+    { dGeomBoxGetLengths (_id,result); }
+};
+
+
+class dPlane : public dGeom {
+  // intentionally undefined, don't use these
+  dPlane (dPlane &);
+  void operator= (dPlane &);
+
+public:
+  dPlane() { }
+  dPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d)
+    { _id = dCreatePlane (space,a,b,c,d); }
+
+  void create (dSpaceID space, dReal a, dReal b, dReal c, dReal d) {
+    if (_id) dGeomDestroy (_id);
+    _id = dCreatePlane (space,a,b,c,d);
+  }
+
+  void setParams (dReal a, dReal b, dReal c, dReal d)
+    { dGeomPlaneSetParams (_id, a, b, c, d); }
+  void getParams (dVector4 result) const
+    { dGeomPlaneGetParams (_id,result); }
+};
+
+
+class dCapsule : public dGeom {
+  // intentionally undefined, don't use these
+  dCapsule (dCapsule &);
+  void operator= (dCapsule &);
+
+public:
+  dCapsule() { }
+  dCapsule (dSpaceID space, dReal radius, dReal length)
+    { _id = dCreateCapsule (space,radius,length); }
+
+  void create (dSpaceID space, dReal radius, dReal length) {
+    if (_id) dGeomDestroy (_id);
+    _id = dCreateCapsule (space,radius,length);
+  }
+
+  void setParams (dReal radius, dReal length)
+    { dGeomCapsuleSetParams (_id, radius, length); }
+  void getParams (dReal *radius, dReal *length) const
+    { dGeomCapsuleGetParams (_id,radius,length); }
+};
+
+
+class dRay : public dGeom {
+  // intentionally undefined, don't use these
+  dRay (dRay &);
+  void operator= (dRay &);
+
+public:
+  dRay() { }
+  dRay (dSpaceID space, dReal length)
+    { _id = dCreateRay (space,length); }
+
+  void create (dSpaceID space, dReal length) {
+    if (_id) dGeomDestroy (_id);
+    _id = dCreateRay (space,length);
+  }
+
+  void setLength (dReal length)
+    { dGeomRaySetLength (_id, length); }
+  dReal getLength()
+    { return dGeomRayGetLength (_id); }
+
+  void set (dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz)
+    { dGeomRaySet (_id, px, py, pz, dx, dy, dz); }
+  void get (dVector3 start, dVector3 dir)
+    { dGeomRayGet (_id, start, dir); }
+
+  void setParams (int firstContact, int backfaceCull)
+    { dGeomRaySetParams (_id, firstContact, backfaceCull); }
+  void getParams (int *firstContact, int *backfaceCull)
+    { dGeomRayGetParams (_id, firstContact, backfaceCull); }
+  void setClosestHit (int closestHit)
+    { dGeomRaySetClosestHit (_id, closestHit); }
+  int getClosestHit()
+    { return dGeomRayGetClosestHit (_id); }
+};
+
+
+class dGeomTransform : public dGeom {
+  // intentionally undefined, don't use these
+  dGeomTransform (dGeomTransform &);
+  void operator= (dGeomTransform &);
+
+public:
+  dGeomTransform() { }
+  dGeomTransform (dSpaceID space)
+    { _id = dCreateGeomTransform (space); }
+
+  void create (dSpaceID space=0) {
+    if (_id) dGeomDestroy (_id);
+    _id = dCreateGeomTransform (space);
+  }
+
+  void setGeom (dGeomID geom)
+    { dGeomTransformSetGeom (_id, geom); }
+  dGeomID getGeom() const
+    { return dGeomTransformGetGeom (_id); }
+
+  void setCleanup (int mode)
+    { dGeomTransformSetCleanup (_id,mode); }
+  int getCleanup ()
+    { return dGeomTransformGetCleanup (_id); }
+
+  void setInfo (int mode)
+    { dGeomTransformSetInfo (_id,mode); }
+  int getInfo()
+    { return dGeomTransformGetInfo (_id); }
+};
+
+
+#endif
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/odemath.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/odemath.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/odemath.h	(revision 216)
@@ -0,0 +1,330 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_ODEMATH_H_
+#define _ODE_ODEMATH_H_
+
+#include <ode/common.h>
+
+#ifdef __GNUC__
+#define PURE_INLINE extern inline
+#else
+#define PURE_INLINE inline
+#endif
+
+/*
+ * macro to access elements i,j in an NxM matrix A, independent of the
+ * matrix storage convention.
+ */
+#define dACCESS33(A,i,j) ((A)[(i)*4+(j)])
+
+/*
+ * Macro to test for valid floating point values
+ */
+#define dVALIDVEC3(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2])))
+#define dVALIDVEC4(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3])))
+#define dVALIDMAT3(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11])))
+#define dVALIDMAT4(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11]) || dIsNan(m[12]) || dIsNan(m[13]) || dIsNan(m[14]) || dIsNan(m[15]) ))
+
+
+
+/*
+ * General purpose vector operations with other vectors or constants.
+ */
+
+#define dOP(a,op,b,c) \
+    (a)[0] = ((b)[0]) op ((c)[0]); \
+    (a)[1] = ((b)[1]) op ((c)[1]); \
+    (a)[2] = ((b)[2]) op ((c)[2]);
+#define dOPC(a,op,b,c) \
+    (a)[0] = ((b)[0]) op (c); \
+    (a)[1] = ((b)[1]) op (c); \
+    (a)[2] = ((b)[2]) op (c);
+#define dOPE(a,op,b) \
+    (a)[0] op ((b)[0]); \
+    (a)[1] op ((b)[1]); \
+    (a)[2] op ((b)[2]);
+#define dOPEC(a,op,c) \
+    (a)[0] op (c); \
+    (a)[1] op (c); \
+    (a)[2] op (c);
+
+
+/*
+ * Length, and squared length helpers. dLENGTH returns the length of a dVector3.
+ * dLENGTHSQUARED return the squared length of a dVector3.
+ */
+
+#define dLENGTHSQUARED(a) (((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]))
+
+#ifdef __cplusplus
+
+PURE_INLINE dReal dLENGTH (const dReal *a) { return dSqrt(dLENGTHSQUARED(a)); }
+
+#else
+
+#define dLENGTH(a) ( dSqrt( ((a)[0])*((a)[0]) + ((a)[1])*((a)[1]) + ((a)[2])*((a)[2]) ) )
+
+#endif /* __cplusplus */
+
+
+
+
+
+/*
+ * 3-way dot product. dDOTpq means that elements of `a' and `b' are spaced
+ * p and q indexes apart respectively. dDOT() means dDOT11.
+ * in C++ we could use function templates to get all the versions of these
+ * functions - but on some compilers this will result in sub-optimal code.
+ */
+
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+
+#ifdef __cplusplus
+
+PURE_INLINE dReal dDOT   (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE dReal dDOT13 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE dReal dDOT31 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE dReal dDOT33 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,3); }
+PURE_INLINE dReal dDOT14 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,4); }
+PURE_INLINE dReal dDOT41 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,1); }
+PURE_INLINE dReal dDOT44 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,4); }
+
+#else
+
+#define dDOT(a,b)   dDOTpq(a,b,1,1)
+#define dDOT13(a,b) dDOTpq(a,b,1,3)
+#define dDOT31(a,b) dDOTpq(a,b,3,1)
+#define dDOT33(a,b) dDOTpq(a,b,3,3)
+#define dDOT14(a,b) dDOTpq(a,b,1,4)
+#define dDOT41(a,b) dDOTpq(a,b,4,1)
+#define dDOT44(a,b) dDOTpq(a,b,4,4)
+
+#endif /* __cplusplus */
+
+
+/*
+ * cross product, set a = b x c. dCROSSpqr means that elements of `a', `b'
+ * and `c' are spaced p, q and r indexes apart respectively.
+ * dCROSS() means dCROSS111. `op' is normally `=', but you can set it to
+ * +=, -= etc to get other effects.
+ */
+
+#define dCROSS(a,op,b,c) \
+do { \
+  (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \
+  (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \
+  (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); \
+} while(0)
+#define dCROSSpqr(a,op,b,c,p,q,r) \
+do { \
+  (a)[  0] op ((b)[  q]*(c)[2*r] - (b)[2*q]*(c)[  r]); \
+  (a)[  p] op ((b)[2*q]*(c)[  0] - (b)[  0]*(c)[2*r]); \
+  (a)[2*p] op ((b)[  0]*(c)[  r] - (b)[  q]*(c)[  0]); \
+} while(0)
+#define dCROSS114(a,op,b,c) dCROSSpqr(a,op,b,c,1,1,4)
+#define dCROSS141(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,1)
+#define dCROSS144(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,4)
+#define dCROSS411(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,1)
+#define dCROSS414(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,4)
+#define dCROSS441(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,1)
+#define dCROSS444(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,4)
+
+
+/*
+ * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.
+ * A is stored by rows, and has `skip' elements per row. the matrix is
+ * assumed to be already zero, so this does not write zero elements!
+ * if (plus,minus) is (+,-) then a positive version will be written.
+ * if (plus,minus) is (-,+) then a negative version will be written.
+ */
+
+#define dCROSSMAT(A,a,skip,plus,minus) \
+do { \
+  (A)[1] = minus (a)[2]; \
+  (A)[2] = plus (a)[1]; \
+  (A)[(skip)+0] = plus (a)[2]; \
+  (A)[(skip)+2] = minus (a)[0]; \
+  (A)[2*(skip)+0] = minus (a)[1]; \
+  (A)[2*(skip)+1] = plus (a)[0]; \
+} while(0)
+
+
+/*
+ * compute the distance between two 3D-vectors
+ */
+
+#ifdef __cplusplus
+PURE_INLINE dReal dDISTANCE (const dVector3 a, const dVector3 b)
+	{ return dSqrt( (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]) ); }
+#else
+#define dDISTANCE(a,b) \
+	(dSqrt( ((a)[0]-(b)[0])*((a)[0]-(b)[0]) + ((a)[1]-(b)[1])*((a)[1]-(b)[1]) + ((a)[2]-(b)[2])*((a)[2]-(b)[2]) ))
+#endif
+
+
+/*
+ * special case matrix multipication, with operator selection
+ */
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+do { \
+  (A)[0] op dDOT((B),(C)); \
+  (A)[1] op dDOT((B+4),(C)); \
+  (A)[2] op dDOT((B+8),(C)); \
+} while(0)
+#define dMULTIPLYOP1_331(A,op,B,C) \
+do { \
+  (A)[0] op dDOT41((B),(C)); \
+  (A)[1] op dDOT41((B+1),(C)); \
+  (A)[2] op dDOT41((B+2),(C)); \
+} while(0)
+#define dMULTIPLYOP0_133(A,op,B,C) \
+do { \
+  (A)[0] op dDOT14((B),(C)); \
+  (A)[1] op dDOT14((B),(C+1)); \
+  (A)[2] op dDOT14((B),(C+2)); \
+} while(0)
+#define dMULTIPLYOP0_333(A,op,B,C) \
+do { \
+  (A)[0] op dDOT14((B),(C)); \
+  (A)[1] op dDOT14((B),(C+1)); \
+  (A)[2] op dDOT14((B),(C+2)); \
+  (A)[4] op dDOT14((B+4),(C)); \
+  (A)[5] op dDOT14((B+4),(C+1)); \
+  (A)[6] op dDOT14((B+4),(C+2)); \
+  (A)[8] op dDOT14((B+8),(C)); \
+  (A)[9] op dDOT14((B+8),(C+1)); \
+  (A)[10] op dDOT14((B+8),(C+2)); \
+} while(0)
+#define dMULTIPLYOP1_333(A,op,B,C) \
+do { \
+  (A)[0] op dDOT44((B),(C)); \
+  (A)[1] op dDOT44((B),(C+1)); \
+  (A)[2] op dDOT44((B),(C+2)); \
+  (A)[4] op dDOT44((B+1),(C)); \
+  (A)[5] op dDOT44((B+1),(C+1)); \
+  (A)[6] op dDOT44((B+1),(C+2)); \
+  (A)[8] op dDOT44((B+2),(C)); \
+  (A)[9] op dDOT44((B+2),(C+1)); \
+  (A)[10] op dDOT44((B+2),(C+2)); \
+} while(0)
+#define dMULTIPLYOP2_333(A,op,B,C) \
+do { \
+  (A)[0] op dDOT((B),(C)); \
+  (A)[1] op dDOT((B),(C+4)); \
+  (A)[2] op dDOT((B),(C+8)); \
+  (A)[4] op dDOT((B+4),(C)); \
+  (A)[5] op dDOT((B+4),(C+4)); \
+  (A)[6] op dDOT((B+4),(C+8)); \
+  (A)[8] op dDOT((B+8),(C)); \
+  (A)[9] op dDOT((B+8),(C+4)); \
+  (A)[10] op dDOT((B+8),(C+8)); \
+} while(0)
+
+#ifdef __cplusplus
+
+#define DECL template <class TA, class TB, class TC> PURE_INLINE void
+
+DECL dMULTIPLY0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,=,B,C); }
+DECL dMULTIPLY1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,=,B,C); }
+DECL dMULTIPLY0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,=,B,C); }
+DECL dMULTIPLY0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,=,B,C); }
+DECL dMULTIPLY1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,=,B,C); }
+DECL dMULTIPLY2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,=,B,C); }
+
+DECL dMULTIPLYADD0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,+=,B,C); }
+DECL dMULTIPLYADD1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,+=,B,C); }
+DECL dMULTIPLYADD0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,+=,B,C); }
+DECL dMULTIPLYADD0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,+=,B,C); }
+DECL dMULTIPLYADD1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,+=,B,C); }
+DECL dMULTIPLYADD2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,+=,B,C); }
+
+#undef DECL
+
+#else
+
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_133(A,B,C) dMULTIPLYOP0_133(A,=,B,C)
+#define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C)
+#define dMULTIPLY1_333(A,B,C) dMULTIPLYOP1_333(A,=,B,C)
+#define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C)
+
+#define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C)
+#define dMULTIPLYADD1_331(A,B,C) dMULTIPLYOP1_331(A,+=,B,C)
+#define dMULTIPLYADD0_133(A,B,C) dMULTIPLYOP0_133(A,+=,B,C)
+#define dMULTIPLYADD0_333(A,B,C) dMULTIPLYOP0_333(A,+=,B,C)
+#define dMULTIPLYADD1_333(A,B,C) dMULTIPLYOP1_333(A,+=,B,C)
+#define dMULTIPLYADD2_333(A,B,C) dMULTIPLYOP2_333(A,+=,B,C)
+
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * normalize 3x1 and 4x1 vectors (i.e. scale them to unit length)
+ */
+ODE_API int  dSafeNormalize3 (dVector3 a);
+ODE_API int  dSafeNormalize4 (dVector4 a);
+
+// For some reason demo_chain1.c does not understand "inline" keyword.
+static __inline void _dNormalize3(dVector3 a)
+{
+	int bNormalizationResult = dSafeNormalize3(a);
+	dIASSERT(bNormalizationResult);
+	dVARIABLEUSED(bNormalizationResult);
+}
+
+static __inline void _dNormalize4(dVector4 a)
+{
+	int bNormalizationResult = dSafeNormalize4(a);
+	dIASSERT(bNormalizationResult);
+	dVARIABLEUSED(bNormalizationResult);
+}
+
+// For DLL export
+ODE_API void dNormalize3 (dVector3 a); // Potentially asserts on zero vec
+ODE_API void dNormalize4 (dVector4 a); // Potentially asserts on zero vec
+
+// For internal use
+#define dNormalize3(a) _dNormalize3(a)
+#define dNormalize4(a) _dNormalize4(a)
+
+/*
+ * given a unit length "normal" vector n, generate vectors p and q vectors
+ * that are an orthonormal basis for the plane space perpendicular to n.
+ * i.e. this makes p,q such that n,p,q are all perpendicular to each other.
+ * q will equal n x p. if n is not unit length then p will be unit length but
+ * q wont be.
+ */
+
+ODE_API void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/rotation.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/rotation.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/rotation.h	(revision 216)
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_ROTATION_H_
+#define _ODE_ROTATION_H_
+
+#include <ode/common.h>
+#include <ode/compatibility.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+ODE_API void dRSetIdentity (dMatrix3 R);
+
+ODE_API void dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az,
+			 dReal angle);
+
+ODE_API void dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi);
+
+ODE_API void dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az,
+		  dReal bx, dReal by, dReal bz);
+
+ODE_API void dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az);
+
+ODE_API void dQSetIdentity (dQuaternion q);
+
+ODE_API void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az,
+			 dReal angle);
+
+/* Quaternion multiplication, analogous to the matrix multiplication routines. */
+/* qa = rotate by qc, then qb */
+ODE_API void dQMultiply0 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc);
+/* qa = rotate by qc, then by inverse of qb */
+ODE_API void dQMultiply1 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc);
+/* qa = rotate by inverse of qc, then by qb */
+ODE_API void dQMultiply2 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc);
+/* qa = rotate by inverse of qc, then by inverse of qb */
+ODE_API void dQMultiply3 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc);
+
+ODE_API void dRfromQ (dMatrix3 R, const dQuaternion q);
+ODE_API void dQfromR (dQuaternion q, const dMatrix3 R);
+ODE_API void dDQfromW (dReal dq[4], const dVector3 w, const dQuaternion q);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/include/ode/timer.h
===================================================================
--- /code/branches/ode/ode-0.9/include/ode/timer.h	(revision 216)
+++ /code/branches/ode/ode-0.9/include/ode/timer.h	(revision 216)
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_TIMER_H_
+#define _ODE_TIMER_H_
+
+#include <ode/config.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* stop watch objects */
+
+typedef struct dStopwatch {
+  double time;			/* total clock count */
+  unsigned long cc[2];		/* clock count since last `start' */
+} dStopwatch;
+
+ODE_API void dStopwatchReset (dStopwatch *);
+ODE_API void dStopwatchStart (dStopwatch *);
+ODE_API void dStopwatchStop  (dStopwatch *);
+ODE_API double dStopwatchTime (dStopwatch *);	/* returns total time in secs */
+
+
+/* code timers */
+
+ODE_API void dTimerStart (const char *description);	/* pass a static string here */
+ODE_API void dTimerNow (const char *description);	/* pass a static string here */
+ODE_API void dTimerEnd(void);
+
+/* print out a timer report. if `average' is nonzero, print out the average
+ * time for each slot (this is only meaningful if the same start-now-end
+ * calls are being made repeatedly.
+ */
+ODE_API void dTimerReport (FILE *fout, int average);
+
+
+/* resolution */
+
+/* returns the timer ticks per second implied by the timing hardware or API.
+ * the actual timer resolution may not be this great.
+ */
+ODE_API double dTimerTicksPerSecond(void);
+
+/* returns an estimate of the actual timer resolution, in seconds. this may
+ * be greater than 1/ticks_per_second.
+ */
+ODE_API double dTimerResolution(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: /code/branches/ode/ode-0.9/install-sh
===================================================================
--- /code/branches/ode/ode-0.9/install-sh	(revision 216)
+++ /code/branches/ode/ode-0.9/install-sh	(revision 216)
@@ -0,0 +1,507 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-10-14.15
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+posix_glob=
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chmodcmd=$chmodprog
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c         (ignored)
+-d         create directories instead of installing files.
+-g GROUP   $chgrpprog installed files to GROUP.
+-m MODE    $chmodprog installed files to MODE.
+-o USER    $chownprog installed files to USER.
+-s         $stripprog installed files.
+-t DIRECTORY  install into DIRECTORY.
+-T         report an error if DSTFILE is a directory.
+--help     display this help and exit.
+--version  display version info and exit.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+        shift
+        shift
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t) dstarg=$2
+	shift
+	shift
+	continue;;
+
+    -T) no_target_directory=true
+	shift
+	continue;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dstarg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dstarg"
+      shift # fnord
+    fi
+    shift # arg
+    dstarg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src ;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dstarg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dstarg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst ;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dstarg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix=/ ;;
+	-*) prefix=./ ;;
+	*)  prefix= ;;
+      esac
+
+      case $posix_glob in
+        '')
+	  if (set -f) 2>/dev/null; then
+	    posix_glob=true
+	  else
+	    posix_glob=false
+	  fi ;;
+      esac
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob && set -f
+      set fnord $dstdir
+      shift
+      $posix_glob && set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test -z "$d" && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # Now rename the file to the real destination.
+    { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
+      || {
+	   # The rename failed, perhaps because mv can't rename something else
+	   # to itself, or perhaps because mv is so ancient that it does not
+	   # support -f.
+
+	   # Now remove or move aside any old file at destination location.
+	   # We try this two ways since rm can't unlink itself on some
+	   # systems and the destination file might be busy for other
+	   # reasons.  In this case, the final cleanup might fail but the new
+	   # file should still install successfully.
+	   {
+	     if test -f "$dst"; then
+	       $doit $rmcmd -f "$dst" 2>/dev/null \
+	       || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
+		     && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
+	       || {
+		 echo "$0: cannot unlink or rename $dst" >&2
+		 (exit 1); exit 1
+	       }
+	     else
+	       :
+	     fi
+	   } &&
+
+	   # Now rename the file to the real destination.
+	   $doit $mvcmd "$dsttmp" "$dst"
+	 }
+    } || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /code/branches/ode/ode-0.9/missing
===================================================================
--- /code/branches/ode/ode-0.9/missing	(revision 216)
+++ /code/branches/ode/ode-0.9/missing	(revision 216)
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+#   Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+  lex|yacc)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  tar)
+    if test -n "$run"; then
+       echo 1>&2 "ERROR: \`tar' requires --run"
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       exit 1
+    fi
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f y.tab.h; then
+	echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+	case $LASTARG in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if test -f "$SRCFILE"; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if test ! -f lex.yy.c; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit 1
+    fi
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+	/^@setfilename/{
+	  s/.* \([^ ]*\) *$/\1/
+	  p
+	  q
+	}' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  tar)
+    shift
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case $firstarg in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case $firstarg in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /code/branches/ode/ode-0.9/ode-config.in
===================================================================
--- /code/branches/ode/ode-0.9/ode-config.in	(revision 216)
+++ /code/branches/ode/ode-0.9/ode-config.in	(revision 216)
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+usage="\
+Usage: ode-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--shared-libs]"
+
+if test $# -eq 0; then
+      echo "${usage}" 1>&2
+      exit 1
+fi
+
+while test $# -gt 0; do
+  case "$1" in
+  -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  case $1 in
+    --prefix=*)
+      prefix=$optarg
+      if test $exec_prefix_set = no ; then
+        exec_prefix=$optarg
+      fi
+      ;;
+    --prefix)
+      echo $prefix
+      ;;
+    --exec-prefix=*)
+      exec_prefix=$optarg
+      exec_prefix_set=yes
+      ;;
+    --exec-prefix)
+      echo $exec_prefix
+      ;;
+    --version)
+      echo @ODE_RELEASE@
+      ;;
+    --cflags)
+      echo  -I@includedir@
+      ;;
+    --libs)
+      echo  -L@libdir@ -lode
+      ;;
+    --shared-libs)
+      echo  -L@prefix@/lib -lode@so_ext@
+      ;;
+    *)
+      echo "${usage}" 1>&2
+      exit 1
+      ;;
+  esac
+  shift
+done
Index: /code/branches/ode/ode-0.9/ode/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/ode/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/Makefile.am	(revision 216)
@@ -0,0 +1,4 @@
+SUBDIRS = src
+if ENABLE_DEMOS
+  SUBDIRS += demo
+endif
Index: /code/branches/ode/ode-0.9/ode/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/ode/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/Makefile.in	(revision 216)
@@ -0,0 +1,489 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@ENABLE_DEMOS_TRUE@am__append_1 = demo
+subdir = ode
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in TODO
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = src demo
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src $(am__append_1)
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  ode/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  ode/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic ctags \
+	ctags-recursive distclean distclean-generic distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+	tags-recursive uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/ode/README
===================================================================
--- /code/branches/ode/ode-0.9/ode/README	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/README	(revision 216)
@@ -0,0 +1,158 @@
+Dynamics Library.
+=================
+
+CONVENTIONS
+-----------
+
+matrix storage
+--------------
+
+matrix operations like factorization are expensive, so we must store the data
+in a way that is most useful to the matrix code. we want the ability to update
+the dynamics library without recompiling applications, e.g. so users can take
+advantage of new floating point hardware. so we must settle on a single
+format. because of the prevalence of 4-way SIMD, the format is this: store
+the matrix by rows or columns, and each column is rounded up to a multiple of
+4 elements. the extra "padding" elements at the end of each row/column are set
+to 0. this is called the "standard format". to indicate if the data is stored
+by rows or columns, we will say "standard row format" or "standard column
+format". hopefully this decision will remain good in the future, as more and
+more processors have 4-way SIMD, and 3D graphics always needs fast 4x4
+matrices.
+
+exception: matrices that have only one column or row (vectors), are always
+stored as consecutive elements in standard row format, i.e. there is no
+interior padding, only padding at the end.
+
+thus: all 3x1 floating point vectors are stored as 4x1 vectors: (x,x,x,0).
+also: all 6x1 spatial velocities and accelerations are split into 3x1 position
+  and angular components, which are stored as contiguous 4x1 vectors.
+
+ALL matrices are stored by in standard row format.
+
+
+arguments
+---------
+
+3x1 vector arguments to set() functions are supplied as x,y,z.
+3x1 vector result arguments to get() function are pointers to arrays.
+larger vectors are always supplied and returned as pointers.
+all coordinates are in the global frame except where otherwise specified.
+output-only arguments are usually supplied at the end.
+
+
+memory allocation
+-----------------
+
+with many C/C++ libraries memory allocation is a difficult problem to solve.
+who allocates the memory? who frees it? must objects go on the heap or can
+they go on the stack or in static storage? to provide the maximum flexibility,
+the dynamics and collision libraries do not do their own memory allocation.
+you must pass in pointers to externally allocated chunks of the right sizes.
+the body, joint and colllision object structures are all exported, so you
+can make instances of those structure and pass pointers to them.
+
+there are helper functions which allocate objects out of areans, in case you
+need loots of dynamic creation and deletion.
+
+BUT!!! this ties us down to the body/joint/collision representation.
+
+a better approach is to supply custom memory allocation functions
+(e.g. dlAlloc() etc).
+
+
+C versus C++ ... ?
+------------------
+
+everything should be C linkable, and there should be C header files for
+everything. but we want to develop in C++. so do this:
+  * all comments are "//". automatically convert to /**/ for distribution.
+  * structures derived from other structures --> automatically convert?
+
+
+WORLDS
+------
+
+might want better terminology here.
+
+the dynamics world (DWorld) is a list of systems. each system corresponds to
+one or more bodies, or perhaps some other kinds of physical object.
+each system corresponds to one or more objects in the collision world
+(there does not have to be a one-to-one correspondence between bodies and
+collision objects).
+
+systems are simulated separately, perhaps using completely different
+techniques. we must do something special when systems collide.
+systems collide when collision objects belonging to system A touch
+collision objects belonging to system B.
+
+for each collision point, the system must provide matrix equation data
+that is used to compute collision forces. once those forces are computed,
+the system must incorporate the forces into its timestep.
+PROBLEM: what if we intertwine the LCP problems of the two systems - then
+this simple approach wont work.
+
+the dynamics world contains two kinds of objects: bodies and joints.
+joints connect two bodies together.
+
+the world contains one of more partitions. each partition is a collection of
+bodies and joints such that each body is attached (through one or more joints)
+to every other body.
+
+Joints
+------
+
+a joint can be connected to one or two bodies.
+if the joint is only connected to one body, joint.node[1].body == 0.
+joint.node[0].body is always valid.
+
+
+Linkage
+-------
+
+this library will always be statically linked with the app, for these reasons:
+  * collision space is selected at compile time, it adds data to the geom
+    objects.
+
+
+Optimization
+------------
+
+doubles must be aligned on 8 byte boundaries!
+
+
+MinGW on Windows issues
+-----------------------
+
+* the .rc file for drawstuff needs a different include, try winresrc.h.
+
+* it seems we can't have both main() and WinMain() without the entry point
+  defaulting to main() and having resource loading problems. this screws up
+  what i was trying to do in the drawstuff library. perhaps main2() ?
+
+* remember to compile resources to COFF format RES files.
+
+
+
+Collision
+---------
+
+to plug in your own collision handling, replace (some of?) these functions
+with your own. collision should be a separate library that you can link in
+or not. your own library can call components in this collision library, e.g.
+if you want polymorphic spaces instead of a single statically called space.
+
+creating an object will automatically register the appropriate
+class (if necessary). how can we ensure that the minimum amount of code is
+linked in? e.g. only one space handler, and sphere-sphere and sphere-box and
+box-box collision code (if spheres and boxes instanced).
+
+the user creates a collision space, and for each dynamics object that is
+created a collision object is inserted into the space. the collision
+object's pos and R pointers are set to the corresponding dynamics
+variables.
+
+there should be utility functions which create the dynamics and collision
+objects at the same time, e.g. dMakeSphere().
+
+collision objects and dynamics objects keep pointers to each other.
Index: /code/branches/ode/ode-0.9/ode/TODO
===================================================================
--- /code/branches/ode/ode-0.9/ode/TODO	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/TODO	(revision 216)
@@ -0,0 +1,698 @@
+
+@@@'s
+
+
+TODO for COLLISION
+------------------
+
+box-box collision: adjust generated face-face contact points by depth/2 to
+be more fair.
+
+what happens when a GeomTransform's encapsulated object is manipulated,
+e.g. position changed. should this be disallowed? should a GeomTransform
+behave like a space and propagate dirtyness upwards?
+
+make sure that when we are using a large space for static environmental geoms,
+that there is not excessive AABB computation when geoms are added/removed from
+the space. the space AABB is pretty much guaranteed to cover everything, so
+there's no need to compute/test the AABB in this case.
+
+hash space: implement collide2() efficiently instead of the current
+simple-space-like brute-force approach.
+
+hash space: incremental scheme, so we dont have to rebuild the data structures
+for geoms that don't move.
+
+disabled geoms (remove from all collision considerations) ... isn't this the
+same as just taking it out of its enclosing group/space?
+
+integrate:
+	dRay
+	triangle collider - get latest tri collider code from erwin
+	erwin's quadtree space
+
+tests:
+	all aspects of collision API
+
+	dGeomSetBody(0) maintains body-geom linked list properly.
+
+	simple space: instantiate lots of non-moving geoms (i.e. environmental
+	geoms and make sure that we're still able to collide efficiently.
+	make sure AABB computation is efficient, or can be made efficient
+	through proper use of the API.
+
+	test C interface support for making new classes.
+	make sure the dxGeom::aabbTest() function behaves as advertised.
+
+	testing for contact point consistency: test for things that
+	would cause the dynamics to fail or become unstable
+
+	test for: small adjustment in geom position causes a big jump in the
+	contact point set (bad for dynamics).
+
+	test for: if contact constraints observed then it's impossible
+	(or hard) to move the objects so that the penetration is
+	increased. relax this when only a subset of the contact points are
+	returned.
+
+	test for consistency, e.g. the boundary of geoms X and Y can
+	be defined by intersecting with a point, so test the intersection of X
+	and Y by comparing with the point tests.
+
+	check that contact points are in the collision volume
+
+	all existing space tests, and more.
+
+demos:
+	test_buggy: make a terrain out of non-moving geoms. use heirarchical
+	groups to get efficient collision, even with the simple space.
+
+go though the new collision docs and make sure the behavior that is described
+there is actually implemented.
+
+multi-resolution hash table:
+	the current implementation rebuilds a new hash table each time
+	collide() is called. we don't keep any state between calls. this is
+	wasteful if there are unmoving objects in the space.
+
+	make sure we prevent multiple collision callbacks for the same pair
+
+	better virtual address function.
+
+	the collision search can perhaps be optimized - as we search
+	chains we can come across other candidate intersections at
+	other levels, perhaps we should do the intersection check
+	straight away? --> save on list searching time only, which is
+	not too significant.
+
+collision docs:
+	optimization guide: whenever a single geom changes in a simple space,
+	the space AABB has to be recomputed by examining EVERY geom.
+	document this, or find a better behavior.
+
+
+
+TODO BEFORE NEXT RELEASE
+------------------------
+
+g++ needed for compiling tests using gcc 3.2 ? what is the problem?
+
+add joint feedback info from lambda, so that we can get motor forces etc.
+need a way to map constraint indexes to what they mean.
+
+track down and fix the occasional popping/jumping problem in test_boxstack,
+especially when boxes are piled on top of each other. find out if this is
+caused by a configuration singularity or whether there is a bug in LCP.
+i need to add some kind of diagnostic tool to help resolve these kinds of
+problems.
+
+fixup ground plane jitter and shadow jumping in drawstuff.
+
+the inertias/COMs don't appear to be totally correct for the boxstack demo.
+fix up, and add a mode that shows the effective mass box (for a given density).
+
+Improve box-box collision, especially for face-face contact (3 contact points).
+Improve cylinder-box collision (2 contact points).
+
+windows DLL building and unix shared libs. libtool?
+also MSVC project files.
+
+dBodyGetPointVel()
+
+contrib directory - all stuff in ~/3/ode
+
+functions to allow systems to be copied/cloned
+	dBodyTransplant (b, world)
+	dTransplantIsland (b, world)
+	dBodyCopy (bdest, bsrc)
+	dJointCopy (jdest, jsrc)  -- what about body connections?
+	dCloneBody()
+	dCloneJoint()
+	dCloseBodyAndJointList()
+	dCloneIsland()
+
+this collision rule:
+    // no contacts if both geoms on the same body, and the body is not 0
+    if (g1->body == g2->body && g1->body) return 0;
+needs to be replaced. sometimes we want no collision when both bodies are 0,
+but this wont work for geomgroup-to-environment. avoid stupid stuff like
+    dGeomSetBody (geom_group, (dBodyID) 1);
+this also causes "failed-to-report" errors in the space test.
+
+Expose type-specific collision functions?
+
+Automatic code optimization process.
+
+joint limit spongyness: interacts with powered joints badly, because when the
+limit is reached full power is applied. fix or doc.
+
+various hinge2 functions may not function correctly if axis1 and axis2 are not
+perpendicular. in particular the getAngle() and getAngleRate() functions
+probably will give bogus answers.
+
+slow step function will not respect the joint getinfo2 functions calling
+addTorque() because it reads the force/torque accumulators before the
+getinfo2 functions are called.
+
+spaces need multiple lists of objects that can never overlap. objects in these
+lists are never tested against each other.
+
+deleting a body a joint is attached to should adjust the joint to only have
+one body attached. currently the connected joints have *both* their body
+attachments removed. BUT, dont do this if the dJOINT_TWOBODIES flag is set
+on the joint.
+
+document error, mem and math functions.
+
+Web pages
+	credits section
+	projects using ODE
+
+update C++ interface? use SWIG?
+
+collision exclusion groups - exclude if obj1.n == obj2.n ?
+
+make sure the amotor joint can be used with just one body. at the moment it
+only allows two-body attachments.
+
+implement dJointGetAMotorAngleRate()
+
+erwin says: Should the GeomGroup have a cleanupmode as the GeomTransform has?
+
+erwin says: http://q12.org/pipermail/ode/2002-January/000766.html
+        and http://q12.org/pipermail/ode/2001-December/000753.html
+
+rename duplicate filenames (object.h?) - some environments can't handle this.
+
+naming inconsistency: dCreateSphere() should be dSphereCreate() (etc...) to
+match the rest of the API.
+
+
+TODO
+----
+
+joint allocation in joint groups. allocation size should be rounded up using
+dEFFICIENT_SIZE, to properly align all the data members.
+
+all dAlloc() allocations should be aligned using dEFFICIENT_SIZE() ???
+
+automatic body & joint disabling / enabling.
+
+sometimes getting LCP infinite loops.
+
+function to get the entire island of bodies/joints
+
+joints:
+	hinge2 joint - implement trail, i.e. non-convergent steering and wheel
+	axes.
+
+	erp individually settable for each joint?
+
+	more joints:
+		angular3 (constrian full angle not position)
+		fixed path 1 (point must follow fixed path, etc etc)
+		  - other fixed path joints.
+		linear a (point in 1 body fixed to plane of other)
+		linear b (point in 1 body fixed to line on other)
+		linear c (line in 1 body fixed to plane on other)
+		linear d (line in 1 body fixed to line on other) - like
+			prismatic but orientation along line can change
+		Relative-Path-Relative-Oriention Joint (set all dofs of 2
+			bodies relative to each other)
+		spring (with natural length)
+		universal (2 kinds)
+		various angular relationships
+
+	when attaching joints to static env, provision to move attachment
+	point (e.g. give it a linear/angular velocity). this can be used
+	instead of a FPFO joint on a body in many cases.
+	also do this with contacts to static env, to allow for contacts to
+	*moving* objects in the static env.
+
+	interpretation of erp: is it (1) the error reduction per timestep,
+	(2) or a time constant independent of timestep?? if it's (2) then
+	perhaps this should be universal - this is already the meaning for
+	the suspension.
+
+	hinge2 suspension:
+		suspension limits
+		suspension limit restitution and spongyness??
+
+use autoconf? set paths in makefile?
+
+no-arg init functions, for andy
+
+explore: do joint parameters need to be set for the joint to be setup
+correctly, or should set some proper body-dependent params when it is
+attached? this is only really an issue for joints that have no parameters to
+set, such as the fixed joint.
+
+dAlloc() should take an arena parameters which is stored in dWorld.
+
+debugging mode should use dASSERT2 that prints a descriptive error message
+on error, not just the file:line or function. use dASSERT for internal
+consistency checking.
+
+when vectors and matrices are initialized, we must ensure that the padding
+elements are set to 0. this is going to be a problem everywhere!
+
+don't use 3-vectors anywhere. use SIMD friendly 4-vectors.
+
+make sure all data in body/joint etc objects is aligned well for single
+precision SIMD (i.e. all vectors start on a 16 byte boundary).
+
+think about more complicated uses of collision, e.g. a single geom representing
+an articulated structure.
+
+bodyGroup? (like joint group but for bodies). systemGroup?
+
+check the overhead of resizing Array<>s as elements are pushed on to them.
+
+replace alloca() with dPushFrame(), dPopFrame(), and dAlloca() ? allow for
+the possibility of allocating in non-stack memory ?
+
+make sure that we can set mass parameters with non-zero center of mass.
+if this is done after the body position is set, the position is adjusted.
+if this is done before the body position is set, what do we do when the
+pos is set? does the pos always refer to the center of mass from the user's
+point of view?
+
+consider splitting solver into functions, which can be optimized separately.
+might make things go faster.
+
+faster code for islands with a single body? faster code for dynamically
+symmetric bodies?
+
+rotation.cpp functions that set matrices should also set padding elements.
+
+lcp solver must return (L,d) and some other information, so we can re-solve
+for other right hand sides later on, but using the same complimentarity
+solution so there are no integrator discontinuities.
+
+dSetZero() - make fast inline functions for fixed n e.g. (1-4).
+
+need proper `sticky' friction, i.e. compensation for numerical slip.
+
+on windows, make sure gcc-compiles libs can be linked with VC++ apps. need
+to make sure some C++ runtime bits are present?
+
+kill all references to dArray<> (in geom.cpp).
+
+need testing code to test all joints with body-to-static-env
+
+copy stack.cpp, memory.cpp stuff to reuse
+
+dFactorLDLT() is not so efficient for matrix sizes < block size, e.g.
+redundant calls, zero loads, adds etc
+
+contacts: cheaper friction: viscous friction? one step delay friction force.
+
+in geom.cpp, for objects that are never meant to collide, dCollide() will
+always try to find the collider functions, which wastes a bit of time.
+
+geom.cpp:dCollideG() - handle special case of colliding 2 groups more
+efficiently.
+
+timer reporting function:
+	void timerReport (void (*printFunction)(char *, ...));
+
+disabled bodies stored in a separate list, so they are never traversed at all,
+for speed when there are many disabled bodies.
+
+
+MAYBE
+-----
+
+new implementation for joint groups that is not so system dependent.
+maybe individual contacts are reusable? in this case contact information
+should be settable in the contact joints. max_size arg is really annoying.
+
+consider making anchor,axis, (everything) into a joint parameter and setting
+them with a consistent interface. also consider overload the joint functions
+so they are not distinguished by joint type??
+
+collision memory optimizations?
+
+collision: support for persistent contact information?
+
+multiply reference tri list data so that it can be cloned
+	if the tri-list geoms could support rot/pos
+	transformations then we could have several tri-lists pointing to the
+	same vertex information.
+
+height fields
+
+pre-converted collision data -- Creating a hash space and associated
+opcode tree structures may take significant amounts of time for a
+large world with many 10s of thousands of triangles.  Any chance of
+pre-building that off-line and passing a memory block pointer to the
+collision system?
+
+putting objects in multiple spaces -- If it was possible to add
+objects to more than one space, you could do collision queries other
+than 1vsN and NvsN.  That flexibility might be useful when you want to
+only collide against a subset of the space.  For example, a camera
+system may want to collide some rays with occlusion walls but the
+occlusion walls may also need to be in the game-level space to bounce
+against.
+
+
+ALWAYS
+------
+
+make sure functions check their arguments in debug mode (e.g. using dASSERT).
+make sure joint/geom functions check for the specific object type.
+
+vectors alloca()ed on the stack must have the correct alignment, use ALLOCA16.
+
+library should have no global constructors, as it might be used with C linkage.
+
+use `const' in function arguments. blah.
+
+
+
+DON'T BOTHER
+------------
+
+warning if user tries to set mass params with nonzero center of mass.
+
+
+
+DONE
+----
+
+check: when contact attached with (body1,0) and (0,body1), check that polarity
+on depth and error info is okay for the two cases.
+
+set a better convention for which is the 1st and 2nd body in a joint, because
+sometimes we get things swapped (because of the way the joint nodes are used).
+
+hinge and prismatic, attachment to static environment.
+
+turn macros into C++ inline functions? what about C users?
+
+remove `space' argument to geom creation functions? make user add it?
+or just remove it from dCreateGeom() ?  <-- did this one.
+
+test_chain should be in C, not C++. but first must remove global constructors.
+
+add more functionality to C++ interface - dMass, dSpace, dGeom
+
+there should be functions to delete groups of bodies/joints in one go - this
+will be more efficient than deleting them one at a time, because less
+partitioning tests will be needed.
+
+should we expose body and joint object structures so that the user can
+explicitly allocate them locally, or e.g. on the stack? makes allocating
+temporary contact constraints easier. NO --> helps data hiding and therefore
+library binary compatability.
+
+joints:
+	hinge & slider - DONE
+		measure angle, rate - DONE
+		power - DONE
+		joint limits - DONE
+		mixed powered+limited joints, powering away from limit - DONE
+
+	hinge2 - DONE
+		steering angle and rate measurement - DONE
+		steering limits - DONE
+		steering motor - DONE
+		wheel motor - DONE
+		wheel angle rate measurement - DONE
+
+	optional hinge2 suspension: - DONE
+		alignment of B&S part to given axis - DONE
+		global framework for giving epsilon and gamma - DONE
+
+	toss away r-motor, make power & stuff specific to joint - DONE
+		it's just easier that way
+
+	joint code reuse: - DONE
+		use standard functions to set velocity (c), limits (lo,hi),
+		spongyness (epsilon) etc, this prevents these functions from
+		proliferating
+
+	implicit spring framework - actually allow joints to return a value `k'
+		such that J*vnew = c + k*f, where f = force needed to achieve
+		vnew - DONE
+
+	contact slip - DONE
+	contact erp & cfm parameters (not just "softness") - DONE
+
+	hinge2: when we lock back wheels along the steering axis, there is no
+	error correction if they get out of alignment - DONE, just use high
+	and low limits.
+
+	joint limit spongyness: erp and cfm for joint set from world (global)
+	values when joint created. - DONE
+
+	joint limit restitution - DONE
+
+check inertia transformations, e.g. by applying steering torque to a thin
+wheel --> actually, i made test_I
+
+more comprehensive random number comparisons between slow and fast methods.
+	- random PD inertia (not just diagonal).
+	- random velocity
+	- random joint error (make joints then move bodies a bit)
+
+check that J*vnew=c (slow step already does this, but it doesn't equal zero
+for some reason! - actually, when LCP constraint limits are reached, it wont!)
+
+tons of things in lcp.cpp (@@@), especially speed optimizations. also, we
+wanted to do index block switching and index block updates to take advantage
+of the outer product trick ... but this is not worth the effort i think.
+
+lcp.cpp: if lo=hi=0, check operation. can we switch from NL <-> NH without
+going through C? --> done.
+
+andy says: still having trouble with those resource files..
+drawstuff.res doesn't seem to build or be found under cygwin gcc.
+
+DOC how bodies and geoms associated then resolved in contact callback ... not
+really necessary.
+
+fix the "memory leak" in geom.cpp
+
+library should have no global constructors, as it might be used with C linkage.
+	--> as long as test_chain1 works, there are none.
+
+DOC cfm, the derivation and what it means.
+	--> partially done, could be better
+
+joint "get type" function
+
+andy says: in ode/src/error.cpp _snprintf() and _vsnprintf() are missing
+in testode: finite and isnan are missing. copysign is missing
+	russ: okay here's the problem: i have Makefile.platform files for
+	VC++, MinGW, but not Cygwin. Cygwin uses the unix-like functions
+	for everything, but the VC++/MinGW configs assumes the MS C-runtime
+	functions. this is easy to fix, except i need to install Cygwin
+	which is a pain to do over MinGW. argh.
+
+build on linux - assumptions made about location of X11 lib, opengl etc.
+
+implement: dBodyAddForceAtPos,dBodyAddRelForceAtPos,dBodyAddRelForceAtRelPos,
+	dBodyGetPointPos,dBodyGetPointVel,dBodyGetPointRelVel
+
+dJointAttach(), allow both bodies to be 0 to put the joint into limbo.
+
+space near-callback should be given potentially intersecting objects 100 at a
+time instead of 1 at a time, to save on calling costs ... which are trivial,
+so we don't bother to do this.
+
+doccer: @func{} also refs second etc function in function *list*.
+
+make sure joints can return 0 from GetInfo1, i.e. no constraints or "inactive"
+joint, and the step functions will handle it.
+
+when attaching contact with (0,body), instead of setting the reverse flag
+on the joint and checking it in getInfo2(), we should just reverse the normal
+straight away ... ?
+	--> trouble is, dJointAttach() knows nothing about what kind of joint
+	    it is attaching.
+
+hinge2 needs to be attached to two bodies for it to work, make sure this is
+always the case. --> assertion added in dJointAttach().
+
+if two joints connect to the same two bodies, check that the fast solver
+works! -> it should.
+
+functions to get all the joints/bodies a body/joint is connected to.
+
+If I don't have the GCC libraries installed, HUGE_VALF is undefined.
+
+fix capped cylinder - capped cylinder collision so that two contacts can
+be generated.
+
+transformation geometry object.
+
+joint groups should also be destroyed by destroying the world --> naaahhh.
+
+DONT DO THIS: body/joint creators with world = 0 --> not inserted into any
+world. allow bodies/joints to be detached from a world (this is what happens
+to grouped joints when a world is destroyed).
+	can bodies and joints be linked together when not attached to world??
+	what happens when we have an island of b/j, some of which are not in
+	world? soln: dont keep lists of b/j in the world, just infer it from
+	the islands?
+
+body & joint disabling / enabling
+
+start a change log.
+
+collision flags - 0xffff mask.
+
+dBodyGetFiniteRotationMode() / ...Axis()
+
+dBodyAddForceAtRelPos()
+
+ball & socket joint limits and motors.
+
+auto-build env on windows: 3 compilers, debug/release, short/double =
+12 combinations --> auto logs.
+
+handle infinities better: HUGE_VALF is not commanly defined, it seems.
+get rid of the __USE_ISOC9X macro in common.h
+perhaps just use a "big" number instead of the actual IEEE infinity, it's
+more portable anyway.
+	--> new config system
+
+dCloseODE() - tidy up *all* allocated memory, esp in geom.cpp. used to keep
+leak detectors happy.
+
+extra API to get lambda and J'*lambda from last timestep.
+
+better stack implementation that is not so system dependent. but how will
+we do dynamic page allocation? do we even need to?
+
+
+all collision files will now be collision_*, not geom_*
+
+check exported global symbols - no C++ mangling.
+
+rename dSphere etc to dxSphere etc.
+
+C interface support for making new classes.
+
+make sure DLL-ized stuff preserved ... but class numbers should no longer be
+exported.
+
+point geom ( = sphere of radius 0 )
+
+geoms stored in doubly linked lists in space (fast removal).
+
+bodies need to keep geoms pointers and call dGeomMoved() in dBodySetPosition()
+etc and world step. PROBLEM: links dynamics and collision together too much,
+makes it hard to extract ODE collision ... unless we say: dGeomMoved() and
+dGeomID must be supplied by the new collision library!
+
+dCollide() should take spaces as arguments - it should call dSpaceCollide2()
+with its own callback that puts all found contacts in the array, stopping
+when there is no more space left in the array.
+
+dxSpace::getGeom() - the geom numbers will change as geoms are dirtied - find
+some other numbering scheme, or document this behavior.
+
+the 'placeable' property - objects that should not ever be attached to bodies
+should flag an error when setBody etc are called.
+
+dGeomSetBody(0) - DOC: the position and orientation of the body will be
+preserved. in this case the geom should NOT be dirtied (dGeomMoved() should
+not be called).
+
+DOC: dGeomGetBodyNext() as part of dynamics/collision interface
+
+groups/spaces are subclasses of geom.
+
+groups/spaces can contain other groups/spaces. geom can be owned by a
+group/space. collision handling:
+	geom-geom : standard collision function
+	geom-group : special space code
+	group-group : n^2 tests (or n space tests) - hard to optimize because
+		of disjoint space representations.
+	group internal : normal space internal-collision code
+
+groups/spaces can be told that some objects never move, i.e. that the objects
+are locked. should we lock the whole space?
+	locking: the AABB for the object is not recalculated
+
+groups/spaces can be told that the internal contents self-intersect or not.
+actually an old ODE group is the equivalent of an old ODE simple space.
+	- just call dCollide() or not.
+
+the group doesn't get passed to the space callback any more ... only the
+intersecting geoms get passed? maybe the callback can initiate the extra
+intersection tests itself? (because we want programmable flexibility to
+determine what gets intersected and what doesn't)
+	- NO
+
+infrastructure to indicate when an object has moved (and thus its AABB needs
+to be recalculated)
+
+space enumeration functions. make sure that there are no additions or deletions
+while enumeration is taking place.
+	- documented the behavior, didn't disallow it
+
+cache the AABB in the dxGeom? (for non-moving objects) - perhaps keep a
+pointer to separately allocated space? ... no
+
+DOC: dGeomGetClass() is a first-class geom function, not in the "User
+defined classes" section. it returns a constant that can be checked
+against dSphereClass etc.
+
+remove dxGeom dependence on dBodyID? ... not yet
+
+dBase -> dxBase
+
+allow a geom to be inserted into multiple spaces? need this to optimize some
+kinds of tests ... no
+
+update docs.
+
+make CHECK_NOT_LOCKED an assert.
+
+DOC: "Calling these functions on a non-placeable geom results in a
+runtime error." ...in the debug build only?
+
+non-placeable geoms should not allocate dxPosR. perhaps pass a dGeom
+constructor arg that says 'placeable' or not - this also sets the
+GEOM_PLACEABLE flag.
+
+GeomTransform:
+	final_pos and final_R valid if no GEOM_AABB_BAD flag!!!
+	fix up this code, esp use of ComputeTX().
+
+Space incompatibilities: no dSpaceDestroy(), dGeomDestroy() does not
+take a dSpaceID ... dSpaceDestroy() added.
+
+GeomGroup incompatibilities:
+	dCollide() used to take a GeomGroup and would return all the contact
+	points for all the intersecting objects. now you have to call
+	dSpaceCollide2() and get a callback for each one.
+	need to provide old behavior.
+
+simple space optimization: we should keep the precomputed AABB for the
+non-moving geoms around, so that when the other geoms move we can just
+compute the AABBs for those geoms and then combine it with the non-moving AABB.
+  --> too hard!
+
+collision build options: old and new
+
+tidyups for collision:
+	* rationalize what stuff goes in what source files, and file names
+	* minimize set of header files that all collision* sources use - after
+	  all changes.
+	* update ode-cpp stuff (C++ interface header files).
+
+porting guide:
+	ODE list email
+
+	dGeomGetSpaceAABB() deleted
+
+	dGeomGetClass (geom_group); used to return a unique type for
+	GeomGroups, but now it returns dSimpleSpaceID.
+
+tidyups: update DLL declarations.
+
Index: /code/branches/ode/ode-0.9/ode/demo/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/Makefile.am	(revision 216)
@@ -0,0 +1,254 @@
+AM_CXXFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+
+noinst_PROGRAMS=demo_collision \
+		demo_slider \
+		demo_feedback \
+		demo_crash \
+		demo_space \
+		demo_I \
+		demo_friction \
+		demo_space_stress \
+		demo_boxstack demo_hinge \
+		demo_step \
+		demo_buggy \
+		demo_joints \
+		demo_motor \
+		demo_chain1 \
+		demo_chain2 \
+                demo_cylvssphere \
+		demo_ode \
+		demo_plane2d \
+		demo_heightfield \
+		demo_convex_cd \
+		demo_jointPR
+if TRIMESH
+noinst_PROGRAMS+= demo_trimesh demo_moving_trimesh demo_basket demo_cyl
+endif
+demo_collision_SOURCES= demo_collision.cpp
+demo_slider_SOURCES= demo_slider.cpp 
+demo_feedback_SOURCES= demo_feedback.cpp 
+demo_crash_SOURCES= demo_crash.cpp
+demo_space_SOURCES= demo_space.cpp
+demo_I_SOURCES= demo_I.cpp
+demo_friction_SOURCES= demo_friction.cpp
+demo_space_stress_SOURCES= demo_space_stress.cpp
+demo_boxstack_SOURCES= demo_boxstack.cpp
+demo_hinge_SOURCES= demo_hinge.cpp
+demo_step_SOURCES= demo_step.cpp
+demo_buggy_SOURCES= demo_buggy.cpp
+demo_cyl_SOURCES= demo_cyl.cpp world_geom3.h
+demo_cylvssphere_SOURCES= demo_cylvssphere.cpp
+demo_joints_SOURCES= demo_joints.cpp
+demo_jointPR_SOURCES= demo_jointPR.cpp
+demo_motor_SOURCES= demo_motor.cpp
+demo_chain1_SOURCES= demo_chain1.c
+demo_chain2_SOURCES= demo_chain2.cpp
+demo_ode_SOURCES= demo_ode.cpp
+demo_plane2d_SOURCES= demo_plane2d.cpp
+demo_heightfield_SOURCES= demo_heightfield.cpp
+demo_convex_cd_SOURCES= demo_convex_cd.cpp
+demo_collision_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_slider_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@  
+demo_feedback_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@  
+demo_crash_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_space_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_I_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_friction_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_space_stress_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_boxstack_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_hinge_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_step_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_buggy_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_cyl_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_cylvssphere_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_joints_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_jointPR_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_motor_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_chain1_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_chain2_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_ode_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_plane2d_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_heightfield_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+demo_convex_cd_LDFLAGS= -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_collision_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_slider_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_feedback_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_crash_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_space_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_I_DEPENDENCIES=		$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_friction_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_space_stress_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_boxstack_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_hinge_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_step_DEPENDENCIES=		$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_buggy_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_cyl_DEPENDENCIES=		$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_cylvssphere_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_joints_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_jointPR_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_motor_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_chain1_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_chain2_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_ode_DEPENDENCIES=		$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_plane2d_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_heightfield_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_convex_cd_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+
+if TRIMESH
+demo_trimesh_SOURCES= 			demo_trimesh.cpp
+demo_moving_trimesh_SOURCES= 		demo_moving_trimesh.cpp
+demo_basket_SOURCES= 			demo_basket.cpp
+demo_trimesh_LDFLAGS= 			-L$(top_builddir)/drawstuff/src \
+					-L$(top_builddir)/ode/src @LDFLAGS@ \
+					@GL_LIBS@ @LIBS@
+demo_moving_trimesh_LDFLAGS= 		-L$(top_builddir)/drawstuff/src \
+					-L$(top_builddir)/ode/src @LDFLAGS@ \
+					@GL_LIBS@ @LIBS@
+demo_basket_LDFLAGS=          		-L$(top_builddir)/drawstuff/src \
+                                        -L$(top_builddir)/ode/src @LDFLAGS@ \
+                                        @GL_LIBS@ @LIBS@
+demo_trimesh_DEPENDENCIES=		$(top_builddir)/ode/src/libode.a \
+					$(top_builddir)/drawstuff/src/libdrawstuff.a
+demo_moving_trimesh_DEPENDENCIES=	$(top_builddir)/ode/src/libode.a \
+					$(top_builddir)/drawstuff/src/libdrawstuff.a
+
+demo_basket_DEPENDENCIES=		$(top_builddir)/ode/src/libode.a \
+					$(top_builddir)/drawstuff/src/libdrawstuff.a
+
+endif
+
+demo_ode_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_plane2d_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_heightfield_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_chain2_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_chain1_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_joints_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_jointPR_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_motor_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_buggy_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_cyl_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_cylvssphere_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_step_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_hinge_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_boxstack_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_space_stress_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_friction_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_I_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_space_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_crash_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_slider_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_feedback_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_collision_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_convex_cd_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+
+
+if TRIMESH
+demo_trimesh_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_moving_trimesh_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_basket_LDADD= -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+endif
+
+
+if WIN32
+resources.o: ../../drawstuff/src/resources.rc ../../drawstuff/src/resource.h
+	@WINDRES@ ../../drawstuff/src/resources.rc -o resources.o
+demo_ode_LDADD+= resources.o
+demo_heightfield_LDADD+= resources.o
+demo_chain2_LDADD+= resources.o
+demo_chain1_LDADD+= resources.o
+demo_joints_LDADD+= resources.o
+demo_jointPR_LDADD+= resources.o
+demo_motor_LDADD+= resources.o
+demo_buggy_LDADD+= resources.o
+demo_cyl_LDADD+= resources.o
+demo_cylvssphere_LDADD+= resources.o
+demo_step_LDADD+= resources.o
+demo_hinge_LDADD+= resources.o
+demo_boxstack_LDADD+= resources.o
+demo_space_stress_LDADD+= resources.o
+demo_friction_LDADD+= resources.o
+demo_I_LDADD+= resources.o
+demo_space_LDADD+= resources.o
+demo_crash_LDADD+= resources.o
+demo_slider_LDADD+= resources.o
+demo_feedback_LDADD+= resources.o
+demo_collision_LDADD+= resources.o
+demo_convex_cd_LDADD+= resources.o
+demo_ode_DEPENDENCIES+= resources.o
+demo_chain2_DEPENDENCIES+= resources.o
+demo_chain1_DEPENDENCIES+= resources.o
+demo_joints_DEPENDENCIES+= resources.o
+demo_jointPR_DEPENDENCIES+= resources.o
+demo_motor_DEPENDENCIES+= resources.o
+demo_buggy_DEPENDENCIES+= resources.o
+demo_cyl_DEPENDENCIES+= resources.o
+demo_cylvssphere_DEPENDENCIES+= resources.o
+demo_step_DEPENDENCIES+= resources.o
+demo_hinge_DEPENDENCIES+= resources.o
+demo_boxstack_DEPENDENCIES+= resources.o
+demo_space_stress_DEPENDENCIES+= resources.o
+demo_friction_DEPENDENCIES+= resources.o
+demo_I_DEPENDENCIES+= resources.o
+demo_space_DEPENDENCIES+= resources.o
+demo_crash_DEPENDENCIES+= resources.o
+demo_slider_DEPENDENCIES+= resources.o
+demo_feedback_DEPENDENCIES+= resources.o
+demo_collision_DEPENDENCIES+= resources.o
+demo_convex_cd_DEPENDENCIES+= resources.o
+
+if TRIMESH
+demo_trimesh_LDADD+= resources.o
+demo_moving_trimesh_LDADD+= resources.o
+demo_trimesh_DEPENDENCIES+= resources.o
+demo_moving_trimesh_DEPENDENCIES+= resources.o
+demo_basket_DEPENDENCIES+= resources.o
+endif
+endif
Index: /code/branches/ode/ode-0.9/ode/demo/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/Makefile.in	(revision 216)
@@ -0,0 +1,953 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = demo_collision$(EXEEXT) demo_slider$(EXEEXT) \
+	demo_feedback$(EXEEXT) demo_crash$(EXEEXT) demo_space$(EXEEXT) \
+	demo_I$(EXEEXT) demo_friction$(EXEEXT) \
+	demo_space_stress$(EXEEXT) demo_boxstack$(EXEEXT) \
+	demo_hinge$(EXEEXT) demo_step$(EXEEXT) demo_buggy$(EXEEXT) \
+	demo_joints$(EXEEXT) demo_motor$(EXEEXT) demo_chain1$(EXEEXT) \
+	demo_chain2$(EXEEXT) demo_cylvssphere$(EXEEXT) \
+	demo_ode$(EXEEXT) demo_plane2d$(EXEEXT) \
+	demo_heightfield$(EXEEXT) demo_convex_cd$(EXEEXT) \
+	demo_jointPR$(EXEEXT) $(am__EXEEXT_1)
+@TRIMESH_TRUE@am__append_1 = demo_trimesh demo_moving_trimesh demo_basket demo_cyl
+@WIN32_TRUE@am__append_2 = resources.o
+@WIN32_TRUE@am__append_3 = resources.o
+@WIN32_TRUE@am__append_4 = resources.o
+@WIN32_TRUE@am__append_5 = resources.o
+@WIN32_TRUE@am__append_6 = resources.o
+@WIN32_TRUE@am__append_7 = resources.o
+@WIN32_TRUE@am__append_8 = resources.o
+@WIN32_TRUE@am__append_9 = resources.o
+@WIN32_TRUE@am__append_10 = resources.o
+@WIN32_TRUE@am__append_11 = resources.o
+@WIN32_TRUE@am__append_12 = resources.o
+@WIN32_TRUE@am__append_13 = resources.o
+@WIN32_TRUE@am__append_14 = resources.o
+@WIN32_TRUE@am__append_15 = resources.o
+@WIN32_TRUE@am__append_16 = resources.o
+@WIN32_TRUE@am__append_17 = resources.o
+@WIN32_TRUE@am__append_18 = resources.o
+@WIN32_TRUE@am__append_19 = resources.o
+@WIN32_TRUE@am__append_20 = resources.o
+@WIN32_TRUE@am__append_21 = resources.o
+@WIN32_TRUE@am__append_22 = resources.o
+@WIN32_TRUE@am__append_23 = resources.o
+@WIN32_TRUE@am__append_24 = resources.o
+@WIN32_TRUE@am__append_25 = resources.o
+@WIN32_TRUE@am__append_26 = resources.o
+@WIN32_TRUE@am__append_27 = resources.o
+@WIN32_TRUE@am__append_28 = resources.o
+@WIN32_TRUE@am__append_29 = resources.o
+@WIN32_TRUE@am__append_30 = resources.o
+@WIN32_TRUE@am__append_31 = resources.o
+@WIN32_TRUE@am__append_32 = resources.o
+@WIN32_TRUE@am__append_33 = resources.o
+@WIN32_TRUE@am__append_34 = resources.o
+@WIN32_TRUE@am__append_35 = resources.o
+@WIN32_TRUE@am__append_36 = resources.o
+@WIN32_TRUE@am__append_37 = resources.o
+@WIN32_TRUE@am__append_38 = resources.o
+@WIN32_TRUE@am__append_39 = resources.o
+@WIN32_TRUE@am__append_40 = resources.o
+@WIN32_TRUE@am__append_41 = resources.o
+@WIN32_TRUE@am__append_42 = resources.o
+@WIN32_TRUE@am__append_43 = resources.o
+@WIN32_TRUE@am__append_44 = resources.o
+@TRIMESH_TRUE@@WIN32_TRUE@am__append_45 = resources.o
+@TRIMESH_TRUE@@WIN32_TRUE@am__append_46 = resources.o
+@TRIMESH_TRUE@@WIN32_TRUE@am__append_47 = resources.o
+@TRIMESH_TRUE@@WIN32_TRUE@am__append_48 = resources.o
+@TRIMESH_TRUE@@WIN32_TRUE@am__append_49 = resources.o
+subdir = ode/demo
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+@TRIMESH_TRUE@am__EXEEXT_1 = demo_trimesh$(EXEEXT) \
+@TRIMESH_TRUE@	demo_moving_trimesh$(EXEEXT) \
+@TRIMESH_TRUE@	demo_basket$(EXEEXT) demo_cyl$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+am_demo_I_OBJECTS = demo_I.$(OBJEXT)
+demo_I_OBJECTS = $(am_demo_I_OBJECTS)
+demo_I_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(demo_I_LDFLAGS) \
+	$(LDFLAGS) -o $@
+am__demo_basket_SOURCES_DIST = demo_basket.cpp
+@TRIMESH_TRUE@am_demo_basket_OBJECTS = demo_basket.$(OBJEXT)
+demo_basket_OBJECTS = $(am_demo_basket_OBJECTS)
+demo_basket_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_basket_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_boxstack_OBJECTS = demo_boxstack.$(OBJEXT)
+demo_boxstack_OBJECTS = $(am_demo_boxstack_OBJECTS)
+demo_boxstack_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_boxstack_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_buggy_OBJECTS = demo_buggy.$(OBJEXT)
+demo_buggy_OBJECTS = $(am_demo_buggy_OBJECTS)
+demo_buggy_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_buggy_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_chain1_OBJECTS = demo_chain1.$(OBJEXT)
+demo_chain1_OBJECTS = $(am_demo_chain1_OBJECTS)
+demo_chain1_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(demo_chain1_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_chain2_OBJECTS = demo_chain2.$(OBJEXT)
+demo_chain2_OBJECTS = $(am_demo_chain2_OBJECTS)
+demo_chain2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_chain2_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_collision_OBJECTS = demo_collision.$(OBJEXT)
+demo_collision_OBJECTS = $(am_demo_collision_OBJECTS)
+demo_collision_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_collision_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_convex_cd_OBJECTS = demo_convex_cd.$(OBJEXT)
+demo_convex_cd_OBJECTS = $(am_demo_convex_cd_OBJECTS)
+demo_convex_cd_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_convex_cd_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_crash_OBJECTS = demo_crash.$(OBJEXT)
+demo_crash_OBJECTS = $(am_demo_crash_OBJECTS)
+demo_crash_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_crash_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_cyl_OBJECTS = demo_cyl.$(OBJEXT)
+demo_cyl_OBJECTS = $(am_demo_cyl_OBJECTS)
+demo_cyl_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_cyl_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_cylvssphere_OBJECTS = demo_cylvssphere.$(OBJEXT)
+demo_cylvssphere_OBJECTS = $(am_demo_cylvssphere_OBJECTS)
+demo_cylvssphere_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_cylvssphere_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_feedback_OBJECTS = demo_feedback.$(OBJEXT)
+demo_feedback_OBJECTS = $(am_demo_feedback_OBJECTS)
+demo_feedback_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_feedback_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_friction_OBJECTS = demo_friction.$(OBJEXT)
+demo_friction_OBJECTS = $(am_demo_friction_OBJECTS)
+demo_friction_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_friction_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_heightfield_OBJECTS = demo_heightfield.$(OBJEXT)
+demo_heightfield_OBJECTS = $(am_demo_heightfield_OBJECTS)
+demo_heightfield_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_heightfield_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_hinge_OBJECTS = demo_hinge.$(OBJEXT)
+demo_hinge_OBJECTS = $(am_demo_hinge_OBJECTS)
+demo_hinge_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_hinge_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_jointPR_OBJECTS = demo_jointPR.$(OBJEXT)
+demo_jointPR_OBJECTS = $(am_demo_jointPR_OBJECTS)
+demo_jointPR_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_jointPR_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_joints_OBJECTS = demo_joints.$(OBJEXT)
+demo_joints_OBJECTS = $(am_demo_joints_OBJECTS)
+demo_joints_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_joints_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_motor_OBJECTS = demo_motor.$(OBJEXT)
+demo_motor_OBJECTS = $(am_demo_motor_OBJECTS)
+demo_motor_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_motor_LDFLAGS) $(LDFLAGS) -o $@
+am__demo_moving_trimesh_SOURCES_DIST = demo_moving_trimesh.cpp
+@TRIMESH_TRUE@am_demo_moving_trimesh_OBJECTS =  \
+@TRIMESH_TRUE@	demo_moving_trimesh.$(OBJEXT)
+demo_moving_trimesh_OBJECTS = $(am_demo_moving_trimesh_OBJECTS)
+demo_moving_trimesh_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_moving_trimesh_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_ode_OBJECTS = demo_ode.$(OBJEXT)
+demo_ode_OBJECTS = $(am_demo_ode_OBJECTS)
+demo_ode_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_ode_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_plane2d_OBJECTS = demo_plane2d.$(OBJEXT)
+demo_plane2d_OBJECTS = $(am_demo_plane2d_OBJECTS)
+demo_plane2d_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_plane2d_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_slider_OBJECTS = demo_slider.$(OBJEXT)
+demo_slider_OBJECTS = $(am_demo_slider_OBJECTS)
+demo_slider_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_slider_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_space_OBJECTS = demo_space.$(OBJEXT)
+demo_space_OBJECTS = $(am_demo_space_OBJECTS)
+demo_space_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_space_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_space_stress_OBJECTS = demo_space_stress.$(OBJEXT)
+demo_space_stress_OBJECTS = $(am_demo_space_stress_OBJECTS)
+demo_space_stress_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_space_stress_LDFLAGS) $(LDFLAGS) -o $@
+am_demo_step_OBJECTS = demo_step.$(OBJEXT)
+demo_step_OBJECTS = $(am_demo_step_OBJECTS)
+demo_step_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_step_LDFLAGS) $(LDFLAGS) -o $@
+am__demo_trimesh_SOURCES_DIST = demo_trimesh.cpp
+@TRIMESH_TRUE@am_demo_trimesh_OBJECTS = demo_trimesh.$(OBJEXT)
+demo_trimesh_OBJECTS = $(am_demo_trimesh_OBJECTS)
+demo_trimesh_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(demo_trimesh_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+SOURCES = $(demo_I_SOURCES) $(demo_basket_SOURCES) \
+	$(demo_boxstack_SOURCES) $(demo_buggy_SOURCES) \
+	$(demo_chain1_SOURCES) $(demo_chain2_SOURCES) \
+	$(demo_collision_SOURCES) $(demo_convex_cd_SOURCES) \
+	$(demo_crash_SOURCES) $(demo_cyl_SOURCES) \
+	$(demo_cylvssphere_SOURCES) $(demo_feedback_SOURCES) \
+	$(demo_friction_SOURCES) $(demo_heightfield_SOURCES) \
+	$(demo_hinge_SOURCES) $(demo_jointPR_SOURCES) \
+	$(demo_joints_SOURCES) $(demo_motor_SOURCES) \
+	$(demo_moving_trimesh_SOURCES) $(demo_ode_SOURCES) \
+	$(demo_plane2d_SOURCES) $(demo_slider_SOURCES) \
+	$(demo_space_SOURCES) $(demo_space_stress_SOURCES) \
+	$(demo_step_SOURCES) $(demo_trimesh_SOURCES)
+DIST_SOURCES = $(demo_I_SOURCES) $(am__demo_basket_SOURCES_DIST) \
+	$(demo_boxstack_SOURCES) $(demo_buggy_SOURCES) \
+	$(demo_chain1_SOURCES) $(demo_chain2_SOURCES) \
+	$(demo_collision_SOURCES) $(demo_convex_cd_SOURCES) \
+	$(demo_crash_SOURCES) $(demo_cyl_SOURCES) \
+	$(demo_cylvssphere_SOURCES) $(demo_feedback_SOURCES) \
+	$(demo_friction_SOURCES) $(demo_heightfield_SOURCES) \
+	$(demo_hinge_SOURCES) $(demo_jointPR_SOURCES) \
+	$(demo_joints_SOURCES) $(demo_motor_SOURCES) \
+	$(am__demo_moving_trimesh_SOURCES_DIST) $(demo_ode_SOURCES) \
+	$(demo_plane2d_SOURCES) $(demo_slider_SOURCES) \
+	$(demo_space_SOURCES) $(demo_space_stress_SOURCES) \
+	$(demo_step_SOURCES) $(am__demo_trimesh_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CXXFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+demo_collision_SOURCES = demo_collision.cpp
+demo_slider_SOURCES = demo_slider.cpp 
+demo_feedback_SOURCES = demo_feedback.cpp 
+demo_crash_SOURCES = demo_crash.cpp
+demo_space_SOURCES = demo_space.cpp
+demo_I_SOURCES = demo_I.cpp
+demo_friction_SOURCES = demo_friction.cpp
+demo_space_stress_SOURCES = demo_space_stress.cpp
+demo_boxstack_SOURCES = demo_boxstack.cpp
+demo_hinge_SOURCES = demo_hinge.cpp
+demo_step_SOURCES = demo_step.cpp
+demo_buggy_SOURCES = demo_buggy.cpp
+demo_cyl_SOURCES = demo_cyl.cpp world_geom3.h
+demo_cylvssphere_SOURCES = demo_cylvssphere.cpp
+demo_joints_SOURCES = demo_joints.cpp
+demo_jointPR_SOURCES = demo_jointPR.cpp
+demo_motor_SOURCES = demo_motor.cpp
+demo_chain1_SOURCES = demo_chain1.c
+demo_chain2_SOURCES = demo_chain2.cpp
+demo_ode_SOURCES = demo_ode.cpp
+demo_plane2d_SOURCES = demo_plane2d.cpp
+demo_heightfield_SOURCES = demo_heightfield.cpp
+demo_convex_cd_SOURCES = demo_convex_cd.cpp
+demo_collision_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_slider_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@  
+
+demo_feedback_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@  
+
+demo_crash_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_space_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_I_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_friction_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_space_stress_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_boxstack_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_hinge_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_step_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_buggy_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_cyl_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_cylvssphere_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_joints_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_jointPR_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_motor_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_chain1_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_chain2_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_ode_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_plane2d_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_heightfield_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_convex_cd_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+		-L$(top_builddir)/ode/src @LDFLAGS@ 
+
+demo_collision_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_43)
+demo_slider_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_41)
+demo_feedback_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_42)
+demo_crash_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_40)
+demo_space_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_39)
+demo_I_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_38)
+demo_friction_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_37)
+demo_space_stress_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_36)
+demo_boxstack_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_35)
+demo_hinge_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_34)
+demo_step_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_33)
+demo_buggy_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_30)
+demo_cyl_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_31)
+demo_cylvssphere_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_32)
+demo_joints_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_27)
+demo_jointPR_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_28)
+demo_motor_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_29)
+demo_chain1_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_26)
+demo_chain2_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_25)
+demo_ode_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_24)
+demo_plane2d_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+
+demo_heightfield_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+				$(top_builddir)/drawstuff/src/libdrawstuff.a
+
+demo_convex_cd_DEPENDENCIES = $(top_builddir)/ode/src/libode.a \
+	$(top_builddir)/drawstuff/src/libdrawstuff.a $(am__append_44)
+@TRIMESH_TRUE@demo_trimesh_SOURCES = demo_trimesh.cpp
+@TRIMESH_TRUE@demo_moving_trimesh_SOURCES = demo_moving_trimesh.cpp
+@TRIMESH_TRUE@demo_basket_SOURCES = demo_basket.cpp
+@TRIMESH_TRUE@demo_trimesh_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+@TRIMESH_TRUE@					-L$(top_builddir)/ode/src @LDFLAGS@ \
+@TRIMESH_TRUE@					@GL_LIBS@ @LIBS@
+
+@TRIMESH_TRUE@demo_moving_trimesh_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+@TRIMESH_TRUE@					-L$(top_builddir)/ode/src @LDFLAGS@ \
+@TRIMESH_TRUE@					@GL_LIBS@ @LIBS@
+
+@TRIMESH_TRUE@demo_basket_LDFLAGS = -L$(top_builddir)/drawstuff/src \
+@TRIMESH_TRUE@                                        -L$(top_builddir)/ode/src @LDFLAGS@ \
+@TRIMESH_TRUE@                                        @GL_LIBS@ @LIBS@
+
+@TRIMESH_TRUE@demo_trimesh_DEPENDENCIES =  \
+@TRIMESH_TRUE@	$(top_builddir)/ode/src/libode.a \
+@TRIMESH_TRUE@	$(top_builddir)/drawstuff/src/libdrawstuff.a \
+@TRIMESH_TRUE@	$(am__append_47)
+@TRIMESH_TRUE@demo_moving_trimesh_DEPENDENCIES =  \
+@TRIMESH_TRUE@	$(top_builddir)/ode/src/libode.a \
+@TRIMESH_TRUE@	$(top_builddir)/drawstuff/src/libdrawstuff.a \
+@TRIMESH_TRUE@	$(am__append_48)
+@TRIMESH_TRUE@demo_basket_DEPENDENCIES =  \
+@TRIMESH_TRUE@	$(top_builddir)/ode/src/libode.a \
+@TRIMESH_TRUE@	$(top_builddir)/drawstuff/src/libdrawstuff.a \
+@TRIMESH_TRUE@	$(am__append_49)
+demo_ode_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_2)
+demo_plane2d_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+demo_heightfield_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_3)
+demo_chain2_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_4)
+demo_chain1_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_5)
+demo_joints_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_6)
+demo_jointPR_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_7)
+demo_motor_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_8)
+demo_buggy_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_9)
+demo_cyl_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_10)
+demo_cylvssphere_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_11)
+demo_step_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_12)
+demo_hinge_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_13)
+demo_boxstack_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_14)
+demo_space_stress_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_15)
+demo_friction_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_16)
+demo_I_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ \
+	@LIBS@ $(am__append_17)
+demo_space_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_18)
+demo_crash_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_19)
+demo_slider_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_20)
+demo_feedback_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_21)
+demo_collision_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_22)
+demo_convex_cd_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a \
+	@GL_LIBS@ @LIBS@ $(am__append_23)
+@TRIMESH_TRUE@demo_trimesh_LDADD = -ldrawstuff \
+@TRIMESH_TRUE@	$(top_builddir)/ode/src/libode.a @GL_LIBS@ \
+@TRIMESH_TRUE@	@LIBS@ $(am__append_45)
+@TRIMESH_TRUE@demo_moving_trimesh_LDADD = -ldrawstuff \
+@TRIMESH_TRUE@	$(top_builddir)/ode/src/libode.a @GL_LIBS@ \
+@TRIMESH_TRUE@	@LIBS@ $(am__append_46)
+@TRIMESH_TRUE@demo_basket_LDADD = -ldrawstuff $(top_builddir)/ode/src/libode.a @GL_LIBS@ @LIBS@
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  ode/demo/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  ode/demo/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+	-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+demo_I$(EXEEXT): $(demo_I_OBJECTS) $(demo_I_DEPENDENCIES) 
+	@rm -f demo_I$(EXEEXT)
+	$(demo_I_LINK) $(demo_I_OBJECTS) $(demo_I_LDADD) $(LIBS)
+demo_basket$(EXEEXT): $(demo_basket_OBJECTS) $(demo_basket_DEPENDENCIES) 
+	@rm -f demo_basket$(EXEEXT)
+	$(demo_basket_LINK) $(demo_basket_OBJECTS) $(demo_basket_LDADD) $(LIBS)
+demo_boxstack$(EXEEXT): $(demo_boxstack_OBJECTS) $(demo_boxstack_DEPENDENCIES) 
+	@rm -f demo_boxstack$(EXEEXT)
+	$(demo_boxstack_LINK) $(demo_boxstack_OBJECTS) $(demo_boxstack_LDADD) $(LIBS)
+demo_buggy$(EXEEXT): $(demo_buggy_OBJECTS) $(demo_buggy_DEPENDENCIES) 
+	@rm -f demo_buggy$(EXEEXT)
+	$(demo_buggy_LINK) $(demo_buggy_OBJECTS) $(demo_buggy_LDADD) $(LIBS)
+demo_chain1$(EXEEXT): $(demo_chain1_OBJECTS) $(demo_chain1_DEPENDENCIES) 
+	@rm -f demo_chain1$(EXEEXT)
+	$(demo_chain1_LINK) $(demo_chain1_OBJECTS) $(demo_chain1_LDADD) $(LIBS)
+demo_chain2$(EXEEXT): $(demo_chain2_OBJECTS) $(demo_chain2_DEPENDENCIES) 
+	@rm -f demo_chain2$(EXEEXT)
+	$(demo_chain2_LINK) $(demo_chain2_OBJECTS) $(demo_chain2_LDADD) $(LIBS)
+demo_collision$(EXEEXT): $(demo_collision_OBJECTS) $(demo_collision_DEPENDENCIES) 
+	@rm -f demo_collision$(EXEEXT)
+	$(demo_collision_LINK) $(demo_collision_OBJECTS) $(demo_collision_LDADD) $(LIBS)
+demo_convex_cd$(EXEEXT): $(demo_convex_cd_OBJECTS) $(demo_convex_cd_DEPENDENCIES) 
+	@rm -f demo_convex_cd$(EXEEXT)
+	$(demo_convex_cd_LINK) $(demo_convex_cd_OBJECTS) $(demo_convex_cd_LDADD) $(LIBS)
+demo_crash$(EXEEXT): $(demo_crash_OBJECTS) $(demo_crash_DEPENDENCIES) 
+	@rm -f demo_crash$(EXEEXT)
+	$(demo_crash_LINK) $(demo_crash_OBJECTS) $(demo_crash_LDADD) $(LIBS)
+demo_cyl$(EXEEXT): $(demo_cyl_OBJECTS) $(demo_cyl_DEPENDENCIES) 
+	@rm -f demo_cyl$(EXEEXT)
+	$(demo_cyl_LINK) $(demo_cyl_OBJECTS) $(demo_cyl_LDADD) $(LIBS)
+demo_cylvssphere$(EXEEXT): $(demo_cylvssphere_OBJECTS) $(demo_cylvssphere_DEPENDENCIES) 
+	@rm -f demo_cylvssphere$(EXEEXT)
+	$(demo_cylvssphere_LINK) $(demo_cylvssphere_OBJECTS) $(demo_cylvssphere_LDADD) $(LIBS)
+demo_feedback$(EXEEXT): $(demo_feedback_OBJECTS) $(demo_feedback_DEPENDENCIES) 
+	@rm -f demo_feedback$(EXEEXT)
+	$(demo_feedback_LINK) $(demo_feedback_OBJECTS) $(demo_feedback_LDADD) $(LIBS)
+demo_friction$(EXEEXT): $(demo_friction_OBJECTS) $(demo_friction_DEPENDENCIES) 
+	@rm -f demo_friction$(EXEEXT)
+	$(demo_friction_LINK) $(demo_friction_OBJECTS) $(demo_friction_LDADD) $(LIBS)
+demo_heightfield$(EXEEXT): $(demo_heightfield_OBJECTS) $(demo_heightfield_DEPENDENCIES) 
+	@rm -f demo_heightfield$(EXEEXT)
+	$(demo_heightfield_LINK) $(demo_heightfield_OBJECTS) $(demo_heightfield_LDADD) $(LIBS)
+demo_hinge$(EXEEXT): $(demo_hinge_OBJECTS) $(demo_hinge_DEPENDENCIES) 
+	@rm -f demo_hinge$(EXEEXT)
+	$(demo_hinge_LINK) $(demo_hinge_OBJECTS) $(demo_hinge_LDADD) $(LIBS)
+demo_jointPR$(EXEEXT): $(demo_jointPR_OBJECTS) $(demo_jointPR_DEPENDENCIES) 
+	@rm -f demo_jointPR$(EXEEXT)
+	$(demo_jointPR_LINK) $(demo_jointPR_OBJECTS) $(demo_jointPR_LDADD) $(LIBS)
+demo_joints$(EXEEXT): $(demo_joints_OBJECTS) $(demo_joints_DEPENDENCIES) 
+	@rm -f demo_joints$(EXEEXT)
+	$(demo_joints_LINK) $(demo_joints_OBJECTS) $(demo_joints_LDADD) $(LIBS)
+demo_motor$(EXEEXT): $(demo_motor_OBJECTS) $(demo_motor_DEPENDENCIES) 
+	@rm -f demo_motor$(EXEEXT)
+	$(demo_motor_LINK) $(demo_motor_OBJECTS) $(demo_motor_LDADD) $(LIBS)
+demo_moving_trimesh$(EXEEXT): $(demo_moving_trimesh_OBJECTS) $(demo_moving_trimesh_DEPENDENCIES) 
+	@rm -f demo_moving_trimesh$(EXEEXT)
+	$(demo_moving_trimesh_LINK) $(demo_moving_trimesh_OBJECTS) $(demo_moving_trimesh_LDADD) $(LIBS)
+demo_ode$(EXEEXT): $(demo_ode_OBJECTS) $(demo_ode_DEPENDENCIES) 
+	@rm -f demo_ode$(EXEEXT)
+	$(demo_ode_LINK) $(demo_ode_OBJECTS) $(demo_ode_LDADD) $(LIBS)
+demo_plane2d$(EXEEXT): $(demo_plane2d_OBJECTS) $(demo_plane2d_DEPENDENCIES) 
+	@rm -f demo_plane2d$(EXEEXT)
+	$(demo_plane2d_LINK) $(demo_plane2d_OBJECTS) $(demo_plane2d_LDADD) $(LIBS)
+demo_slider$(EXEEXT): $(demo_slider_OBJECTS) $(demo_slider_DEPENDENCIES) 
+	@rm -f demo_slider$(EXEEXT)
+	$(demo_slider_LINK) $(demo_slider_OBJECTS) $(demo_slider_LDADD) $(LIBS)
+demo_space$(EXEEXT): $(demo_space_OBJECTS) $(demo_space_DEPENDENCIES) 
+	@rm -f demo_space$(EXEEXT)
+	$(demo_space_LINK) $(demo_space_OBJECTS) $(demo_space_LDADD) $(LIBS)
+demo_space_stress$(EXEEXT): $(demo_space_stress_OBJECTS) $(demo_space_stress_DEPENDENCIES) 
+	@rm -f demo_space_stress$(EXEEXT)
+	$(demo_space_stress_LINK) $(demo_space_stress_OBJECTS) $(demo_space_stress_LDADD) $(LIBS)
+demo_step$(EXEEXT): $(demo_step_OBJECTS) $(demo_step_DEPENDENCIES) 
+	@rm -f demo_step$(EXEEXT)
+	$(demo_step_LINK) $(demo_step_OBJECTS) $(demo_step_LDADD) $(LIBS)
+demo_trimesh$(EXEEXT): $(demo_trimesh_OBJECTS) $(demo_trimesh_DEPENDENCIES) 
+	@rm -f demo_trimesh$(EXEEXT)
+	$(demo_trimesh_LINK) $(demo_trimesh_OBJECTS) $(demo_trimesh_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_I.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_basket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_boxstack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_buggy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_chain1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_chain2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_collision.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_convex_cd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_crash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cyl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_cylvssphere.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_feedback.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_friction.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_heightfield.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_hinge.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_jointPR.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_joints.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_motor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_moving_trimesh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_ode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_plane2d.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_slider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_space.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_space_stress.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_step.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demo_trimesh.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstPROGRAMS ctags distclean distclean-compile \
+	distclean-generic distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am
+
+
+@WIN32_TRUE@resources.o: ../../drawstuff/src/resources.rc ../../drawstuff/src/resource.h
+@WIN32_TRUE@	@WINDRES@ ../../drawstuff/src/resources.rc -o resources.o
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/ode/demo/basket_geom.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/basket_geom.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/basket_geom.h	(revision 216)
@@ -0,0 +1,13 @@
+
+static float world_normals[] = {
+0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,0,0,1,0,0,1,0,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,-0.948064f,0.318080f,0,-0.989482f,0.144655f,0,-0.983494f,0.180939f,0,-0.983494f,0.180939f,0,-0.908999f,0.416798f,0,-0.948064f,0.318080f,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,-0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-0.132460f,0.991188f,0,0.264920f,0.964270f,0,0.132460f,0.991188f,0,0.132460f,0.991188f,0,-0.264920f,0.964270f,0,-0.132460f,0.991188f,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-0.687592f,-0.726097f,-0,-0.881727f,-0.471761f,0,-0.687592f,-0.726097f,-0,-0.881727f,-0.471761f,0,-0.881727f,-0.471761f,0,-0.687592f,-0.726097f,-0,0.687592f,-0.726097f,0,0.928375f,-0.371644f,0,0.824321f,-0.566123f,0,0.687592f,-0.726097f,0,0.824321f,-0.566123f,0,0.687592f,-0.726097f,0,-0.881727f,-0.471761f,0,-0.985594f,-0.169128f,0,-0.985594f,-0.169128f,0,-0.985594f,-0.169128f,0,-0.881727f,-0.471761f,0,-0.881727f,-0.471761f,0,0.928375f,-0.371644f,0,0.985594f,-0.169128f,0,0.985594f,-0.169128f,0,0.928375f,-0.371644f,0,0.985594f,-0.169128f,0,0.824321f,-0.566123f,0,-0.870167f,0.492758f,0,-0.870167f,0.492758f,0,-0.870167f,0.492758f,0,-0.870167f,0.492758f,0,-0.870167f,0.492758f,0,-0.870167f,0.492758f,0,0.870167f,0.492758f,0,0.870167f,0.492758f,0,0.870167f,0.492758f,0,0.870167f,0.492758f,0,0.870167f,0.492758f,0,0.870167f,0.492758f,-0,-0.390313f,0.920682f,0,-0.132460f,0.991188f,0,-0.264920f,0.964270f,0,-0.264920f,0.964270f,0,-0.390313f,0.920682f,0,-0.390313f,0.920682f,0,0.390313f,0.920682f,0,0.132460f,0.991188f,0,0.264920f,0.964270f,0,0.390313f,0.920682f,0,0.264920f,0.964270f,0,0.390313f,0.920682f,-0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0.985594f,0.169128f,0,0.824321f,0.566123f,0,0.928375f,0.371644f,0,0.928375f,0.371644f,0,0.985594f,0.169128f,0,0.985594f,0.169128f,0,0.824321f,0.566123f,0,0.687592f,0.726097f,0,0.687592f,0.726097f,0,0.687592f,0.726097f,0,0.928375f,0.371644f,0,0.824321f,0.566123f,0,0,1,0,-0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0.687592f,0.726097f,0,-0.687592f,0.726097f,0,-0.881727f,0.471761f,0,-0.881727f,0.471761f,0,-0.881727f,0.471761f,0,-0.687592f,0.726097f,0,-0.881727f,0.471761f,0,-0.985594f,0.169128f,0,-0.985594f,0.169128f,0,-0.985594f,0.169128f,0,-0.881727f,0.471761f,0,-0.881727f,0.471761f,0,-0.870166f,-0.492758f,0,-0.870166f,-0.492758f,0,-0.870166f,-0.492758f,0,-0.870166f,-0.492758f,0,-0.870166f,-0.492758f,0,-0.870166f,-0.492758f,0,-0.390314f,-0.920682f,0,-0.132460f,-0.991188f,0,-0.264921f,-0.964270f,0,-0.264921f,-0.964270f,0,-0.390314f,-0.920682f,0,-0.390314f,-0.920682f,0,-0.132460f,-0.991188f,0,0.264921f,-0.964270f,0,0.132460f,-0.991188f,0,0.132460f,-0.991188f,0,-0.264921f,-0.964270f,0,-0.132460f,-0.991188f,0,0.264921f,-0.964270f,0,0.390314f,-0.920682f,0,0.390314f,-0.920682f,0,0.390314f,-0.920682f,0,0.132460f,-0.991188f,0,0.264921f,-0.964270f,0,0.870166f,-0.492758f,0,0.870166f,-0.492758f,0,0.870166f,-0.492758f,0,0.870166f,-0.492758f,0,0.870166f,-0.492758f,0,0.870166f,-0.492758f,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0.527606f,0.849489f,0,-0.793893f,0.608057f,0,-0.715135f,0.698986f,0,-0.715135f,0.698986f,0,-0.418249f,0.908332f,0,-0.527606f,0.849489f,0,-0.075284f,0.997162f,0,-0.253577f,0.967315f,0,-0.202069f,0.979371f,0,-0.202069f,0.979371f,0,-0.075284f,0.997162f,0,-0.075284f,0.997162f,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0.160137f,0.987095f,0,0.049305f,0.998784f,0,0.049305f,0.998784f,0,0.049305f,0.998784f,0,0.221401f,0.975183f,0,0.160137f,0.987095f,0,0.696124f,0.717921f,0,0.696124f,0.717921f,0,0.433340f,0.901230f,0,0.433340f,0.901230f,0,0.433340f,0.901230f,0,0.696124f,0.717921f,0,0.696124f,0.717921f,0,0.696124f,0.717921f,0,0.838308f,0.545197f,0,0.696124f,0.717921f,0,0.872167f,0.489208f,0,0.838308f,0.545197f,0,-0.994126f,0.108225f,0,-0.983494f,0.180939f,0,-0.989482f,0.144655f,0,-0.994126f,0.108225f,0,-0.989482f,0.144655f,0,-0.994126f,0.108225f,0,-0.948064f,0.318080f,0,-0.908999f,0.416798f,0,-0.793893f,0.608057f,0,-0.908999f,0.416798f,0,-0.715135f,0.698986f,0,-0.793893f,0.608057f,0,-0.527606f,0.849489f,0,-0.418249f,0.908332f,0,-0.253577f,0.967315f,0,-0.418249f,0.908332f,0,-0.202069f,0.979371f,0,-0.253577f,0.967315f,0,-0.075284f,0.997162f,0,-0.075284f,0.997162f,0,0,1,0,-0.075284f,0.997162f,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0.049305f,0.998784f,0,0,1,0,0.049305f,0.998784f,0,0.049305f,0.998784f,0,0.160137f,0.987095f,0,0.221401f,0.975183f,0,0.433340f,0.901230f,0,0.221401f,0.975183f,0,0.433340f,0.901230f,0,0.433340f,0.901230f,0,0.902172f,0.431376f,0,0.838308f,0.545197f,0,0.872167f,0.489208f,0,0.872167f,0.489208f,0,0.902172f,0.431376f,0,0.902172f,0.431376f,
+};
+
+static float world_vertices[] = {
+-4,-4,-0.100000f,4,-4,-0.100000f,4,-4,0.100000f,-4,-4,-0.100000f,4,-4,0.100000f,-4,-4,0.100000f,4,0,0.100000f,4,-4,-0.100000f,4,4,-0.100000f,4,0,0.100000f,4,4,-0.100000f,4,4,0.100000f,4,0,0.100000f,4,-4,0.100000f,4,-4,-0.100000f,-4,-4,-0.100000f,-4,4,-0.100000f,4,4,-0.100000f,-4,-4,-0.100000f,4,4,-0.100000f,4,-4,-0.100000f,0.066000f,-2.060000f,2,0.066000f,-1.940000f,2,-0.066000f,-2.060000f,2,0.066000f,-1.940000f,2,-0.066000f,-1.940000f,2,-0.066000f,-2.060000f,2,-4,4,0.100000f,4,4,0.100000f,4,4,-0.100000f,4,4,-0.100000f,-4,4,-0.100000f,-4,4,0.100000f,-4,-4,0.100000f,-4,0,0.100000f,-4,-4,-0.100000f,-4,0,0.100000f,-4,4,0.100000f,-4,4,-0.100000f,-4,0,0.100000f,-4,4,-0.100000f,-4,-4,-0.100000f,0.360000f,3.244444f,1.466974f,0.360000f,3.422222f,2.266974f,-0.360000f,3.422222f,2.266974f,-0.360000f,3.422222f,2.266974f,-0.360000f,3.244444f,1.466974f,0.360000f,3.244444f,1.466974f,4,-4,0.100000f,0.066000f,-2.060000f,0.100000f,-0.066000f,-2.060000f,0.100000f,-0.066000f,-2.060000f,0.100000f,-4,-4,0.100000f,4,-4,0.100000f,4,0,0.100000f,0.066000f,-1.940000f,0.100000f,4,-4,0.100000f,0.066000f,-1.940000f,0.100000f,0.066000f,-2.060000f,0.100000f,4,-4,0.100000f,-0.066000f,-1.940000f,0.100000f,0.066000f,-1.940000f,0.100000f,4,0,0.100000f,4,0,0.100000f,-4,0,0.100000f,-0.066000f,-1.940000f,0.100000f,-0.066000f,-2.060000f,0.100000f,-0.066000f,-1.940000f,0.100000f,-4,0,0.100000f,-4,0,0.100000f,-4,-4,0.100000f,-0.066000f,-2.060000f,0.100000f,0.066000f,-2.060000f,2,-0.066000f,-2.060000f,2,-0.066000f,-2.060000f,0.100000f,-0.066000f,-2.060000f,0.100000f,0.066000f,-2.060000f,0.100000f,0.066000f,-2.060000f,2,0.066000f,-1.940000f,1.950000f,0.066000f,-1.940000f,2,0.066000f,-2.060000f,2,0.066000f,-2.060000f,2,0.066000f,-2.060000f,0.100000f,0.066000f,-1.940000f,1.950000f,0.066000f,-2.060000f,0.100000f,0.066000f,-1.940000f,0.100000f,0.066000f,-1.940000f,1.950000f,-0.052853f,-1.506390f,2,0.052853f,-1.506390f,2,0.052853f,-1.506390f,1.950000f,0.052853f,-1.506390f,1.950000f,-0.052853f,-1.506390f,1.950000f,-0.052853f,-1.506390f,2,-0.066000f,-2.060000f,0.100000f,-0.066000f,-2.060000f,2,-0.066000f,-1.940000f,1.950000f,-0.066000f,-2.060000f,0.100000f,-0.066000f,-1.940000f,1.950000f,-0.066000f,-1.940000f,0.100000f,-0.066000f,-2.060000f,2,-0.066000f,-1.940000f,2,-0.066000f,-1.940000f,1.950000f,-0.066000f,-1.940000f,0.100000f,-0.066000f,-1.940000f,1.950000f,0.066000f,-1.940000f,1.950000f,-0.066000f,-1.940000f,0.100000f,0.066000f,-1.940000f,1.950000f,0.066000f,-1.940000f,0.100000f,-0.066000f,-1.940000f,1.950000f,-0.066000f,-1.840000f,1.950000f,0.066000f,-1.940000f,1.950000f,-0.066000f,-1.840000f,1.950000f,0.066000f,-1.840000f,1.950000f,0.066000f,-1.940000f,1.950000f,-0.066000f,-1.940000f,2,-0.066000f,-1.840000f,2,-0.066000f,-1.840000f,1.950000f,-0.066000f,-1.840000f,1.950000f,-0.066000f,-1.940000f,1.950000f,-0.066000f,-1.940000f,2,0.066000f,-1.940000f,2,0.066000f,-1.840000f,2,-0.066000f,-1.940000f,2,0.066000f,-1.840000f,2,-0.066000f,-1.840000f,2,-0.066000f,-1.940000f,2,0.066000f,-1.940000f,1.950000f,0.066000f,-1.840000f,1.950000f,0.066000f,-1.840000f,2,0.066000f,-1.940000f,1.950000f,0.066000f,-1.840000f,2,0.066000f,-1.940000f,2,-0.066000f,-1.840000f,2,-0.171600f,-1.740000f,2,-0.066000f,-1.840000f,1.950000f,-0.171600f,-1.740000f,2,-0.171600f,-1.740000f,1.950000f,-0.066000f,-1.840000f,1.950000f,0.066000f,-1.840000f,1.950000f,0.171600f,-1.740000f,1.950000f,0.171600f,-1.740000f,2,0.066000f,-1.840000f,1.950000f,0.171600f,-1.740000f,2,0.066000f,-1.840000f,2,-0.171600f,-1.740000f,2,-0.188760f,-1.640000f,2,-0.188760f,-1.640000f,1.950000f,-0.188760f,-1.640000f,1.950000f,-0.171600f,-1.740000f,1.950000f,-0.171600f,-1.740000f,2,0.171600f,-1.740000f,1.950000f,0.188760f,-1.640000f,1.950000f,0.188760f,-1.640000f,2,0.171600f,-1.740000f,1.950000f,0.188760f,-1.640000f,2,0.171600f,-1.740000f,2,-0.188760f,-1.640000f,2,-0.132132f,-1.540000f,2,-0.132132f,-1.540000f,1.950000f,-0.132132f,-1.540000f,1.950000f,-0.188760f,-1.640000f,1.950000f,-0.188760f,-1.640000f,2,0.188760f,-1.640000f,1.950000f,0.132132f,-1.540000f,1.950000f,0.132132f,-1.540000f,2,0.188760f,-1.640000f,1.950000f,0.132132f,-1.540000f,2,0.188760f,-1.640000f,2,-0.132132f,-1.540000f,2,-0.052853f,-1.506390f,2,-0.052853f,-1.506390f,1.950000f,-0.052853f,-1.506390f,1.950000f,-0.132132f,-1.540000f,1.950000f,-0.132132f,-1.540000f,2,0.132132f,-1.540000f,1.950000f,0.052853f,-1.506390f,1.950000f,0.052853f,-1.506390f,2,0.132132f,-1.540000f,1.950000f,0.052853f,-1.506390f,2,0.132132f,-1.540000f,2,0.188760f,-1.640000f,1.950000f,0.173397f,-1.642679f,1.950000f,0.121808f,-1.551577f,1.950000f,0.121808f,-1.551577f,1.950000f,0.132132f,-1.540000f,1.950000f,0.188760f,-1.640000f,1.950000f,0.171600f,-1.740000f,1.950000f,0.157950f,-1.732697f,1.950000f,0.173397f,-1.642679f,1.950000f,0.171600f,-1.740000f,1.950000f,0.173397f,-1.642679f,1.950000f,0.188760f,-1.640000f,1.950000f,0.171600f,-1.740000f,1.950000f,0.066000f,-1.840000f,1.950000f,0.060149f,-1.825311f,1.950000f,0.171600f,-1.740000f,1.950000f,0.060149f,-1.825311f,1.950000f,0.157950f,-1.732697f,1.950000f,-0.066000f,-1.840000f,1.950000f,-0.060149f,-1.825311f,1.950000f,0.066000f,-1.840000f,1.950000f,-0.060149f,-1.825311f,1.950000f,0.060149f,-1.825311f,1.950000f,0.066000f,-1.840000f,1.950000f,-0.171600f,-1.740000f,1.950000f,-0.157950f,-1.732697f,1.950000f,-0.060149f,-1.825311f,1.950000f,-0.171600f,-1.740000f,1.950000f,-0.060149f,-1.825311f,1.950000f,-0.066000f,-1.840000f,1.950000f,-0.173397f,-1.642679f,1.950000f,-0.157950f,-1.732697f,1.950000f,-0.171600f,-1.740000f,1.950000f,-0.171600f,-1.740000f,1.950000f,-0.188760f,-1.640000f,1.950000f,-0.173397f,-1.642679f,1.950000f,-0.121808f,-1.551577f,1.950000f,-0.173397f,-1.642679f,1.950000f,-0.188760f,-1.640000f,1.950000f,-0.188760f,-1.640000f,1.950000f,-0.132132f,-1.540000f,1.950000f,-0.121808f,-1.551577f,1.950000f,-0.052853f,-1.506390f,1.950000f,-0.049868f,-1.521079f,1.950000f,-0.121808f,-1.551577f,1.950000f,-0.052853f,-1.506390f,1.950000f,-0.121808f,-1.551577f,1.950000f,-0.132132f,-1.540000f,1.950000f,0.049868f,-1.521079f,1.950000f,-0.049868f,-1.521079f,1.950000f,-0.052853f,-1.506390f,1.950000f,-0.052853f,-1.506390f,1.950000f,0.052853f,-1.506390f,1.950000f,0.049868f,-1.521079f,1.950000f,0.052853f,-1.506390f,1.950000f,0.132132f,-1.540000f,1.950000f,0.121808f,-1.551577f,1.950000f,0.052853f,-1.506390f,1.950000f,0.121808f,-1.551577f,1.950000f,0.049868f,-1.521079f,1.950000f,-0.188760f,-1.640000f,2,-0.173397f,-1.642679f,2,-0.121808f,-1.551577f,2,-0.121808f,-1.551577f,2,-0.132132f,-1.540000f,2,-0.188760f,-1.640000f,2,-0.171600f,-1.740000f,2,-0.157950f,-1.732697f,2,-0.173397f,-1.642679f,2,-0.173397f,-1.642679f,2,-0.188760f,-1.640000f,2,-0.171600f,-1.740000f,2,-0.066000f,-1.840000f,2,-0.060149f,-1.825311f,2,-0.171600f,-1.740000f,2,-0.060149f,-1.825311f,2,-0.157950f,-1.732697f,2,-0.171600f,-1.740000f,2,0.066000f,-1.840000f,2,0.060149f,-1.825311f,2,-0.066000f,-1.840000f,2,0.060149f,-1.825311f,2,-0.060149f,-1.825311f,2,-0.066000f,-1.840000f,2,0.171600f,-1.740000f,2,0.157950f,-1.732697f,2,0.060149f,-1.825311f,2,0.171600f,-1.740000f,2,0.060149f,-1.825311f,2,0.066000f,-1.840000f,2,0.173397f,-1.642679f,2,0.157950f,-1.732697f,2,0.171600f,-1.740000f,2,0.171600f,-1.740000f,2,0.188760f,-1.640000f,2,0.173397f,-1.642679f,2,0.121808f,-1.551577f,2,0.173397f,-1.642679f,2,0.188760f,-1.640000f,2,0.188760f,-1.640000f,2,0.132132f,-1.540000f,2,0.121808f,-1.551577f,2,0.052853f,-1.506390f,2,0.049868f,-1.521079f,2,0.121808f,-1.551577f,2,0.052853f,-1.506390f,2,0.121808f,-1.551577f,2,0.132132f,-1.540000f,2,-0.049868f,-1.521079f,2,0.049868f,-1.521079f,2,0.052853f,-1.506390f,2,0.052853f,-1.506390f,2,-0.052853f,-1.506390f,2,-0.049868f,-1.521079f,2,-0.121808f,-1.551577f,2,-0.049868f,-1.521079f,2,-0.052853f,-1.506390f,2,-0.052853f,-1.506390f,2,-0.132132f,-1.540000f,2,-0.121808f,-1.551577f,2,-0.173397f,-1.642679f,2,-0.157950f,-1.732697f,2,-0.157950f,-1.732697f,1.950000f,-0.157950f,-1.732697f,1.950000f,-0.173397f,-1.642679f,1.950000f,-0.173397f,-1.642679f,2,-0.157950f,-1.732697f,2,-0.060149f,-1.825311f,2,-0.060149f,-1.825311f,1.950000f,-0.060149f,-1.825311f,1.950000f,-0.157950f,-1.732697f,1.950000f,-0.157950f,-1.732697f,2,-0.060149f,-1.825311f,2,0.060149f,-1.825311f,2,0.060149f,-1.825311f,1.950000f,0.060149f,-1.825311f,1.950000f,-0.060149f,-1.825311f,1.950000f,-0.060149f,-1.825311f,2,0.060149f,-1.825311f,1.950000f,0.060149f,-1.825311f,2,0.157950f,-1.732697f,2,0.157950f,-1.732697f,2,0.157950f,-1.732697f,1.950000f,0.060149f,-1.825311f,1.950000f,0.157950f,-1.732697f,2,0.173397f,-1.642679f,2,0.173397f,-1.642679f,1.950000f,0.173397f,-1.642679f,1.950000f,0.157950f,-1.732697f,1.950000f,0.157950f,-1.732697f,2,0.173397f,-1.642679f,2,0.121808f,-1.551577f,2,0.121808f,-1.551577f,1.950000f,0.121808f,-1.551577f,1.950000f,0.173397f,-1.642679f,1.950000f,0.173397f,-1.642679f,2,0.121808f,-1.551577f,2,0.049868f,-1.521079f,2,0.049868f,-1.521079f,1.950000f,0.049868f,-1.521079f,1.950000f,0.121808f,-1.551577f,1.950000f,0.121808f,-1.551577f,2,0.049868f,-1.521079f,2,-0.049868f,-1.521079f,2,-0.049868f,-1.521079f,1.950000f,-0.049868f,-1.521079f,1.950000f,0.049868f,-1.521079f,1.950000f,0.049868f,-1.521079f,2,-0.049868f,-1.521079f,2,-0.121808f,-1.551577f,2,-0.121808f,-1.551577f,1.950000f,-0.121808f,-1.551577f,1.950000f,-0.049868f,-1.521079f,1.950000f,-0.049868f,-1.521079f,2,-0.121808f,-1.551577f,2,-0.173397f,-1.642679f,2,-0.173397f,-1.642679f,1.950000f,-0.173397f,-1.642679f,1.950000f,-0.121808f,-1.551577f,1.950000f,-0.121808f,-1.551577f,2,-0.360000f,3.600000f,0.100000f,0.360000f,3.600000f,0.100000f,4,4,0.100000f,4,4,0.100000f,-4,4,0.100000f,-0.360000f,3.600000f,0.100000f,-0.360000f,0.400000f,0.100000f,-0.360000f,3.600000f,0.100000f,-4,4,0.100000f,-4,4,0.100000f,-4,0,0.100000f,-0.360000f,0.400000f,0.100000f,4,0,0.100000f,0.360000f,0.400000f,0.100000f,-0.360000f,0.400000f,0.100000f,-0.360000f,0.400000f,0.100000f,-4,0,0.100000f,4,0,0.100000f,4,4,0.100000f,0.360000f,3.600000f,0.100000f,4,0,0.100000f,0.360000f,3.600000f,0.100000f,0.360000f,0.400000f,0.100000f,4,0,0.100000f,0.360000f,2.888889f,1.023752f,0.360000f,3.066667f,1.166974f,-0.360000f,3.066667f,1.166974f,-0.360000f,3.066667f,1.166974f,-0.360000f,2.888889f,1.023752f,0.360000f,2.888889f,1.023752f,0.360000f,2.533333f,0.939976f,0.360000f,2.711111f,0.966974f,-0.360000f,2.711111f,0.966974f,-0.360000f,2.711111f,0.966974f,-0.360000f,2.533333f,0.939976f,0.360000f,2.533333f,0.939976f,-0.360000f,2.177778f,0.939976f,0.360000f,2.177778f,0.939976f,0.360000f,2.355556f,0.939976f,0.360000f,2.355556f,0.939976f,-0.360000f,2.355556f,0.939976f,-0.360000f,2.177778f,0.939976f,-0.360000f,1.822222f,0.939976f,0.360000f,1.822222f,0.939976f,0.360000f,2,0.939976f,0.360000f,2,0.939976f,-0.360000f,2,0.939976f,-0.360000f,1.822222f,0.939976f,-0.360000f,1.466667f,0.939976f,0.360000f,1.466667f,0.939976f,0.360000f,1.644444f,0.939976f,0.360000f,1.644444f,0.939976f,-0.360000f,1.644444f,0.939976f,-0.360000f,1.466667f,0.939976f,0.360000f,1.111111f,0.957571f,0.360000f,1.288889f,0.939976f,-0.360000f,1.288889f,0.939976f,-0.360000f,1.288889f,0.939976f,-0.360000f,1.111111f,0.957571f,0.360000f,1.111111f,0.957571f,-0.360000f,0.755556f,1.134246f,0.360000f,0.755556f,1.134246f,0.360000f,0.933333f,1.009739f,0.360000f,0.933333f,1.009739f,-0.360000f,0.933333f,1.009739f,-0.360000f,0.755556f,1.134246f,0.360000f,0.755556f,1.134246f,-0.360000f,0.755556f,1.134246f,0.360000f,0.577778f,1.372130f,-0.360000f,0.755556f,1.134246f,-0.360000f,0.577778f,1.372130f,0.360000f,0.577778f,1.372130f,-0.360000f,3.600000f,3.900000f,-0.360000f,3.422222f,2.266974f,0.360000f,3.422222f,2.266974f,-0.360000f,3.600000f,3.900000f,0.360000f,3.422222f,2.266974f,0.360000f,3.600000f,3.900000f,0.360000f,3.244444f,1.466974f,-0.360000f,3.244444f,1.466974f,0.360000f,3.066667f,1.166974f,-0.360000f,3.244444f,1.466974f,-0.360000f,3.066667f,1.166974f,0.360000f,3.066667f,1.166974f,0.360000f,2.888889f,1.023752f,-0.360000f,2.888889f,1.023752f,0.360000f,2.711111f,0.966974f,-0.360000f,2.888889f,1.023752f,-0.360000f,2.711111f,0.966974f,0.360000f,2.711111f,0.966974f,0.360000f,2.533333f,0.939976f,-0.360000f,2.533333f,0.939976f,-0.360000f,2.355556f,0.939976f,0.360000f,2.533333f,0.939976f,-0.360000f,2.355556f,0.939976f,0.360000f,2.355556f,0.939976f,0.360000f,2.177778f,0.939976f,-0.360000f,2.177778f,0.939976f,-0.360000f,2,0.939976f,0.360000f,2.177778f,0.939976f,-0.360000f,2,0.939976f,0.360000f,2,0.939976f,0.360000f,1.822222f,0.939976f,-0.360000f,1.822222f,0.939976f,-0.360000f,1.644444f,0.939976f,0.360000f,1.822222f,0.939976f,-0.360000f,1.644444f,0.939976f,0.360000f,1.644444f,0.939976f,0.360000f,1.466667f,0.939976f,-0.360000f,1.466667f,0.939976f,-0.360000f,1.288889f,0.939976f,0.360000f,1.466667f,0.939976f,-0.360000f,1.288889f,0.939976f,0.360000f,1.288889f,0.939976f,0.360000f,1.111111f,0.957571f,-0.360000f,1.111111f,0.957571f,0.360000f,0.933333f,1.009739f,-0.360000f,1.111111f,0.957571f,-0.360000f,0.933333f,1.009739f,0.360000f,0.933333f,1.009739f,0.360000f,0.400000f,1.743932f,0.360000f,0.577778f,1.372130f,-0.360000f,0.577778f,1.372130f,-0.360000f,0.577778f,1.372130f,-0.360000f,0.400000f,1.743932f,0.360000f,0.400000f,1.743932f,
+};
+
+static int world_indices[] = {
+0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,
+};
+
Index: /code/branches/ode/ode-0.9/ode/demo/demo_I.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_I.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_I.cpp	(revision 216)
@@ -0,0 +1,254 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+test that the rotational physics is correct.
+
+an "anchor body" has a number of other randomly positioned bodies
+("particles") attached to it by ball-and-socket joints, giving it some
+random effective inertia tensor. the effective inertia matrix is calculated,
+and then this inertia is assigned to another "test" body. a random torque is
+applied to both bodies and the difference in angular velocity and orientation
+is observed after a number of iterations.
+
+typical errors for each test cycle are about 1e-5 ... 1e-4.
+
+*/
+
+
+#include <time.h>
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define NUM 10			// number of particles
+#define SIDE 0.1		// visual size of the particles
+
+
+// dynamics objects an globals
+
+static dWorldID world=0;
+static dBodyID anchor_body,particle[NUM],test_body;
+static dJointID particle_joint[NUM];
+static dReal torque[3];
+static int iteration;
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {1.5572f,-1.8886f,1.5700f};
+  static float hpr[3] = {118.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// compute the mass parameters of a particle set. q = particle positions,
+// pm = particle masses
+
+#define _I(i,j) I[(i)*4+(j)]
+
+void computeMassParams (dMass *m, dReal q[NUM][3], dReal pm[NUM])
+{
+  int i,j;
+  dMassSetZero (m);
+  for (i=0; i<NUM; i++) {
+    m->mass += pm[i];
+    for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j];
+    m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]);
+    m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]);
+    m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]);
+    m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]);
+    m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]);
+    m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]);
+  }
+  for (j=0; j<3; j++) m->c[j] /= m->mass;
+  m->_I(1,0) = m->_I(0,1);
+  m->_I(2,0) = m->_I(0,2);
+  m->_I(2,1) = m->_I(1,2);
+}
+
+
+void reset_test()
+{
+  int i;
+  dMass m,anchor_m;
+  dReal q[NUM][3], pm[NUM];	// particle positions and masses
+  dReal pos1[3] = {1,0,1};	// point of reference (POR)
+  dReal pos2[3] = {-1,0,1};	// point of reference (POR)
+
+  // make random particle positions (relative to POR) and masses
+  for (i=0; i<NUM; i++) {
+    pm[i] = dRandReal()+0.1;
+    q[i][0] = dRandReal()-0.5;
+    q[i][1] = dRandReal()-0.5;
+    q[i][2] = dRandReal()-0.5;
+  }
+
+  // adjust particle positions so centor of mass = POR
+  computeMassParams (&m,q,pm);
+  for (i=0; i<NUM; i++) {
+    q[i][0] -= m.c[0];
+    q[i][1] -= m.c[1];
+    q[i][2] -= m.c[2];
+  }
+
+  if (world) dWorldDestroy (world);
+  world = dWorldCreate();
+
+  anchor_body = dBodyCreate (world);
+  dBodySetPosition (anchor_body,pos1[0],pos1[1],pos1[2]);
+  dMassSetBox (&anchor_m,1,SIDE,SIDE,SIDE);
+  dMassAdjust (&anchor_m,0.1);
+  dBodySetMass (anchor_body,&anchor_m);
+
+  for (i=0; i<NUM; i++) {
+    particle[i] = dBodyCreate (world);
+    dBodySetPosition (particle[i],
+		      pos1[0]+q[i][0],pos1[1]+q[i][1],pos1[2]+q[i][2]);
+    dMassSetBox (&m,1,SIDE,SIDE,SIDE);
+    dMassAdjust (&m,pm[i]);
+    dBodySetMass (particle[i],&m);
+  }
+
+  for (i=0; i < NUM; i++) {
+    particle_joint[i] = dJointCreateBall (world,0);
+    dJointAttach (particle_joint[i],anchor_body,particle[i]);
+    const dReal *p = dBodyGetPosition (particle[i]);
+    dJointSetBallAnchor (particle_joint[i],p[0],p[1],p[2]);
+  }
+
+  // make test_body with the same mass and inertia of the anchor_body plus
+  // all the particles
+
+  test_body = dBodyCreate (world);
+  dBodySetPosition (test_body,pos2[0],pos2[1],pos2[2]);
+  computeMassParams (&m,q,pm);
+  m.mass += anchor_m.mass;
+  for (i=0; i<12; i++) m.I[i] = m.I[i] + anchor_m.I[i];
+  dBodySetMass (test_body,&m);
+
+  // rotate the test and anchor bodies by a random amount
+  dQuaternion qrot;
+  for (i=0; i<4; i++) qrot[i] = dRandReal()-0.5;
+  dNormalize4 (qrot);
+  dBodySetQuaternion (anchor_body,qrot);
+  dBodySetQuaternion (test_body,qrot);
+  dMatrix3 R;
+  dQtoR (qrot,R);
+  for (i=0; i<NUM; i++) {
+    dVector3 v;
+    dMultiply0 (v,R,&q[i][0],3,3,1);
+    dBodySetPosition (particle[i],pos1[0]+v[0],pos1[1]+v[1],pos1[2]+v[2]);
+  }
+
+  // set random torque
+  for (i=0; i<3; i++) torque[i] = (dRandReal()-0.5) * 0.1;
+
+
+  iteration=0;
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  if (!pause) {
+    dBodyAddTorque (anchor_body,torque[0],torque[1],torque[2]);
+    dBodyAddTorque (test_body,torque[0],torque[1],torque[2]);
+    dWorldStep (world,0.03);
+
+    iteration++;
+    if (iteration >= 100) {
+      // measure the difference between the anchor and test bodies
+      const dReal *w1 = dBodyGetAngularVel (anchor_body);
+      const dReal *w2 = dBodyGetAngularVel (test_body);
+      const dReal *q1 = dBodyGetQuaternion (anchor_body);
+      const dReal *q2 = dBodyGetQuaternion (test_body);
+      dReal maxdiff = dMaxDifference (w1,w2,1,3);
+      printf ("w-error = %.4e  (%.2f,%.2f,%.2f) and (%.2f,%.2f,%.2f)\n",
+	      maxdiff,w1[0],w1[1],w1[2],w2[0],w2[1],w2[2]);
+      maxdiff = dMaxDifference (q1,q2,1,4);
+      printf ("q-error = %.4e\n",maxdiff);
+      reset_test();
+    }
+  }
+
+  dReal sides[3] = {SIDE,SIDE,SIDE};
+  dReal sides2[3] = {6*SIDE,6*SIDE,6*SIDE};
+  dReal sides3[3] = {3*SIDE,3*SIDE,3*SIDE};
+  dsSetColor (1,1,1);
+  dsDrawBox (dBodyGetPosition(anchor_body), dBodyGetRotation(anchor_body),
+	     sides3);
+  dsSetColor (1,0,0);
+  dsDrawBox (dBodyGetPosition(test_body), dBodyGetRotation(test_body), sides2);
+  dsSetColor (1,1,0);
+  for (int i=0; i<NUM; i++)
+    dsDrawBox (dBodyGetPosition (particle[i]),
+	       dBodyGetRotation (particle[i]), sides);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = 0;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  dInitODE();
+  dRandSetSeed (time(0));
+  reset_test();
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_basket.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_basket.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_basket.cpp	(revision 216)
@@ -0,0 +1,278 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// Basket ball demo.
+// Serves as a test for the sphere vs trimesh collider
+// By Bram Stolk.
+// Press the spacebar to reset the position of the ball.
+
+#include <ode/config.h>
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#include "basket_geom.h" // this is our world mesh
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// some constants
+
+#define RADIUS 0.14
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+
+static dBodyID sphbody;
+static dGeomID sphgeom;
+
+static dJointGroupID contactgroup;
+static dGeomID world_mesh;
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  assert(o1);
+  assert(o2);
+
+  if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
+  {
+    fprintf(stderr,"testing space %p %p\n", o1,o2);
+    // colliding a space with something
+    dSpaceCollide2(o1,o2,data,&nearCallback);
+    // Note we do not want to test intersections within a space,
+    // only between spaces.
+    return;
+  }
+
+//  fprintf(stderr,"testing geoms %p %p\n", o1, o2);
+
+  const int N = 32;
+  dContact contact[N];
+  int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
+  if (n > 0) 
+  {
+    for (int i=0; i<n; i++) 
+    {
+	  // Paranoia  <-- not working for some people, temporarily removed for 0.6
+      //dIASSERT(dVALIDVEC3(contact[i].geom.pos));
+      //dIASSERT(dVALIDVEC3(contact[i].geom.normal));
+      //dIASSERT(!dIsNan(contact[i].geom.depth));
+      contact[i].surface.slip1 = 0.7;
+      contact[i].surface.slip2 = 0.7;
+      contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
+      contact[i].surface.mu = 50.0; // was: dInfinity
+      contact[i].surface.soft_erp = 0.96;
+      contact[i].surface.soft_cfm = 0.04;
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c,
+		    dGeomGetBody(contact[i].geom.g1),
+		    dGeomGetBody(contact[i].geom.g2));
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {-8,0,5};
+  static float hpr[3] = {0.0f,-29.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+
+static void reset_ball(void)
+{
+  float sx=0.0f, sy=3.40f, sz=7.05;
+
+#if defined(_MSC_VER) && defined(dDOUBLE)
+  sy -= 0.01; // Cheat, to make it score under win32/double
+#endif
+
+  dQuaternion q;
+  dQSetIdentity(q);
+  dBodySetPosition (sphbody, sx, sy, sz);
+  dBodySetQuaternion(sphbody, q);
+  dBodySetLinearVel (sphbody, 0,0,0);
+  dBodySetAngularVel (sphbody, 0,0,0);
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  switch (cmd) 
+  {
+    case ' ':
+	  reset_ball();
+      break;
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  double simstep = 0.001; // 1ms simulation steps
+  double dt = dsElapsedTime();
+
+  int nrofsteps = (int) ceilf(dt/simstep);
+//  fprintf(stderr, "dt=%f, nr of steps = %d\n", dt, nrofsteps);
+
+  for (int i=0; i<nrofsteps && !pause; i++)
+  {
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldQuickStep (world, simstep);
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (1,1,1);
+  const dReal *SPos = dBodyGetPosition(sphbody);
+  const dReal *SRot = dBodyGetRotation(sphbody);
+  float spos[3] = {SPos[0], SPos[1], SPos[2]};
+  float srot[12] = { SRot[0], SRot[1], SRot[2], SRot[3], SRot[4], SRot[5], SRot[6], SRot[7], SRot[8], SRot[9], SRot[10], SRot[11] };
+  dsDrawSphere
+  (
+    spos, 
+    srot, 
+    RADIUS
+  );
+
+  // draw world trimesh
+  dsSetColor(0.4,0.7,0.9);
+  dsSetTexture (DS_NONE);
+
+  const dReal* Pos = dGeomGetPosition(world_mesh);
+  //dIASSERT(dVALIDVEC3(Pos));
+  float pos[3] = { Pos[0], Pos[1], Pos[2] };
+
+  const dReal* Rot = dGeomGetRotation(world_mesh);
+  //dIASSERT(dVALIDMAT3(Rot));
+  float rot[12] = { Rot[0], Rot[1], Rot[2], Rot[3], Rot[4], Rot[5], Rot[6], Rot[7], Rot[8], Rot[9], Rot[10], Rot[11] };
+
+  int numi = sizeof(world_indices)  / sizeof(int);
+
+  for (int i=0; i<numi/3; i++)
+  {
+    int i0 = world_indices[i*3+0];
+    int i1 = world_indices[i*3+1];
+    int i2 = world_indices[i*3+2];
+    float *v0 = world_vertices+i0*3;
+    float *v1 = world_vertices+i1*3;
+    float *v2 = world_vertices+i2*3;
+    dsDrawTriangle(pos, rot, v0,v1,v2, true); // single precision draw
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  dMass m;
+  dMatrix3 R;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    fn.path_to_textures = argv[1];
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-9.8);
+  dWorldSetQuickStepNumIterations (world, 64);
+
+  // Create a static world using a triangle mesh that we can collide with.
+  int numv = sizeof(world_vertices)/(3*sizeof(float));
+  int numi = sizeof(world_indices)/ sizeof(int);
+  printf("numv=%d, numi=%d\n", numv, numi);
+  dTriMeshDataID Data = dGeomTriMeshDataCreate();
+
+//  fprintf(stderr,"Building Single Precision Mesh\n");
+
+  dGeomTriMeshDataBuildSingle
+  (
+    Data, 
+    world_vertices, 
+    3 * sizeof(float), 
+    numv, 
+    world_indices, 
+    numi, 
+    3 * sizeof(int)
+  );
+
+  world_mesh = dCreateTriMesh(space, Data, 0, 0, 0);
+  dGeomTriMeshEnableTC(world_mesh, dSphereClass, false);
+  dGeomTriMeshEnableTC(world_mesh, dBoxClass, false);
+  dGeomSetPosition(world_mesh, 0, 0, 0.5);
+  dRSetIdentity(R);
+  //dIASSERT(dVALIDMAT3(R));
+
+  dGeomSetRotation (world_mesh, R);
+
+  float sx=0.0, sy=3.40, sz=6.80;
+  sphbody = dBodyCreate (world);
+  dMassSetSphere (&m,1,RADIUS);
+  dBodySetMass (sphbody,&m);
+  sphgeom = dCreateSphere(0, RADIUS);
+  dGeomSetBody (sphgeom,sphbody);
+  reset_ball();
+  dSpaceAdd (space, sphgeom);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  // Causes segm violation? Why?
+  // (because dWorldDestroy() destroys body connected to geom; must call first!)
+  dGeomDestroy(sphgeom);
+  dGeomDestroy (world_mesh);
+
+  dJointGroupEmpty (contactgroup);
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
+
Index: /code/branches/ode/ode-0.9/ode/demo/demo_boxstack.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_boxstack.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_boxstack.cpp	(revision 216)
@@ -0,0 +1,577 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+
+//<---- Convex Object
+dReal planes[]= // planes for a cube, these should coincide with the face array
+  {
+    1.0f ,0.0f ,0.0f ,0.25f,
+    0.0f ,1.0f ,0.0f ,0.25f,
+    0.0f ,0.0f ,1.0f ,0.25f,
+    -1.0f,0.0f ,0.0f ,0.25f,
+    0.0f ,-1.0f,0.0f ,0.25f,
+    0.0f ,0.0f ,-1.0f,0.25f
+    /*
+    1.0f ,0.0f ,0.0f ,2.0f,
+    0.0f ,1.0f ,0.0f ,1.0f,
+    0.0f ,0.0f ,1.0f ,1.0f,
+    0.0f ,0.0f ,-1.0f,1.0f,
+    0.0f ,-1.0f,0.0f ,1.0f,
+    -1.0f,0.0f ,0.0f ,0.0f
+    */
+  };
+const unsigned int planecount=6;
+
+dReal points[]= // points for a cube
+  {
+    0.25f,0.25f,0.25f,  //  point 0
+    -0.25f,0.25f,0.25f, //  point 1
+
+    0.25f,-0.25f,0.25f, //  point 2
+    -0.25f,-0.25f,0.25f,//  point 3
+
+    0.25f,0.25f,-0.25f, //  point 4
+    -0.25f,0.25f,-0.25f,//  point 5
+
+    0.25f,-0.25f,-0.25f,//  point 6
+    -0.25f,-0.25f,-0.25f,// point 7 
+  };
+const unsigned int pointcount=8;
+unsigned int polygons[] = //Polygons for a cube (6 squares)
+  {
+    4,0,2,6,4, // positive X
+    4,1,0,4,5, // positive Y
+    4,0,1,3,2, // positive Z
+    4,3,1,5,7, // negative X 
+    4,2,3,7,6, // negative Y
+    4,5,4,6,7, // negative Z
+  };
+//----> Convex Object
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#define dsDrawConvex dsDrawConvexD
+#endif
+
+
+// some constants
+
+#define NUM 100			// max number of objects
+#define DENSITY (5.0)		// density of all objects
+#define GPB 3			// maximum number of geometries per body
+#define MAX_CONTACTS 8		// maximum number of contact points per body
+#define USE_GEOM_OFFSET 1
+
+// dynamics and collision objects
+
+struct MyObject {
+  dBodyID body;			// the body
+  dGeomID geom[GPB];		// geometries representing this body
+};
+
+static int num=0;		// number of objects in simulation
+static int nextobj=0;		// next object to recycle if num==NUM
+static dWorldID world;
+static dSpaceID space;
+static MyObject obj[NUM];
+static dJointGroupID contactgroup;
+static int selected = -1;	// selected object
+static int show_aabb = 0;	// show geom AABBs?
+static int show_contacts = 0;	// show contact points?
+static int random_pos = 1;	// drop objects from random position?
+static int write_world = 0;
+static int show_body = 1;
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+  // if (o1->body && o2->body) return;
+
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+
+  dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
+  for (i=0; i<MAX_CONTACTS; i++) {
+    contact[i].surface.mode = dContactBounce | dContactSoftCFM;
+    contact[i].surface.mu = dInfinity;
+    contact[i].surface.mu2 = 0;
+    contact[i].surface.bounce = 0.1;
+    contact[i].surface.bounce_vel = 0.1;
+    contact[i].surface.soft_cfm = 0.01;
+  }
+  if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
+			   sizeof(dContact))) {
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    const dReal ss[3] = {0.02,0.02,0.02};
+    for (i=0; i<numc; i++) {
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+      if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("To drop another object, press:\n");
+  printf ("   b for box.\n");
+  printf ("   s for sphere.\n");
+  printf ("   c for capsule.\n");
+  printf ("   y for cylinder.\n");
+  printf ("   v for a convex object.\n");
+  printf ("   x for a composite object.\n");
+  printf ("To select an object, press space.\n");
+  printf ("To disable the selected object, press d.\n");
+  printf ("To enable the selected object, press e.\n");
+  printf ("To toggle showing the geom AABBs, press a.\n");
+  printf ("To toggle showing the contact points, press t.\n");
+  printf ("To toggle dropping from random position/orientation, press r.\n");
+  printf ("To save the current state to 'state.dif', press 1.\n");
+}
+
+
+char locase (char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+  else return c;
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  size_t i;
+  int j,k;
+  dReal sides[3];
+  dMass m;
+  int setBody;
+  
+  cmd = locase (cmd);
+  if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'y' || cmd == 'v')
+  {
+    setBody = 0;
+    if (num < NUM) {
+      i = num;
+      num++;
+    }
+    else {
+      i = nextobj;
+      nextobj++;
+      if (nextobj >= num) nextobj = 0;
+
+      // destroy the body and geoms for slot i
+      dBodyDestroy (obj[i].body);
+      for (k=0; k < GPB; k++) {
+	if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+      }
+      memset (&obj[i],0,sizeof(obj[i]));
+    }
+
+    obj[i].body = dBodyCreate (world);
+    for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+    dMatrix3 R;
+    if (random_pos) 
+      {
+	dBodySetPosition (obj[i].body,
+			  dRandReal()*2-1,dRandReal()*2-1,dRandReal()+2);
+	dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+      }
+    else 
+      {
+	dReal maxheight = 0;
+	for (k=0; k<num; k++) 
+	  {
+	    const dReal *pos = dBodyGetPosition (obj[k].body);
+	    if (pos[2] > maxheight) maxheight = pos[2];
+	  }
+	dBodySetPosition (obj[i].body, 0,0,maxheight+1);
+	dRSetIdentity (R);
+	//dRFromAxisAndAngle (R,0,0,1,/*dRandReal()*10.0-5.0*/0);
+      }
+    dBodySetRotation (obj[i].body,R);
+    dBodySetData (obj[i].body,(void*) i);
+
+    if (cmd == 'b') {
+      dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+      obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+    }
+    else if (cmd == 'c') {
+      sides[0] *= 0.5;
+      dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
+    }
+    //<---- Convex Object    
+    else if (cmd == 'v') 
+      {
+	dMassSetBox (&m,DENSITY,0.25,0.25,0.25);
+	obj[i].geom[0] = dCreateConvex (space,
+					planes,
+					planecount,
+					points,
+					pointcount,
+					polygons);
+      }
+    //----> Convex Object
+    else if (cmd == 'y') {
+      dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
+    }
+    else if (cmd == 's') {
+      sides[0] *= 0.5;
+      dMassSetSphere (&m,DENSITY,sides[0]);
+      obj[i].geom[0] = dCreateSphere (space,sides[0]);
+    }
+    else if (cmd == 'x' && USE_GEOM_OFFSET) {
+      setBody = 1;
+      // start accumulating masses for the encapsulated geometries
+      dMass m2;
+      dMassSetZero (&m);
+
+      dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+      dMatrix3 drot[GPB];
+      
+      // set random delta positions
+      for (j=0; j<GPB; j++) {
+		for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+      }
+    
+      for (k=0; k<GPB; k++) {
+		if (k==0) {
+		  dReal radius = dRandReal()*0.25+0.05;
+		  obj[i].geom[k] = dCreateSphere (space,radius);
+		  dMassSetSphere (&m2,DENSITY,radius);
+		}
+		else if (k==1) {
+		  obj[i].geom[k] = dCreateBox (space,sides[0],sides[1],sides[2]);
+		  dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+		}
+		else {
+		  dReal radius = dRandReal()*0.1+0.05;
+		  dReal length = dRandReal()*1.0+0.1;
+		  obj[i].geom[k] = dCreateCapsule (space,radius,length);
+		  dMassSetCapsule (&m2,DENSITY,3,radius,length);
+		}
+
+		dRFromAxisAndAngle (drot[k],dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+					dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+		dMassRotate (&m2,drot[k]);
+		
+		dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+
+		// add to the total mass
+		dMassAdd (&m,&m2);
+		
+	}
+      for (k=0; k<GPB; k++) {
+		dGeomSetBody (obj[i].geom[k],obj[i].body);
+		dGeomSetOffsetPosition (obj[i].geom[k],
+			  dpos[k][0]-m.c[0],
+			  dpos[k][1]-m.c[1],
+			  dpos[k][2]-m.c[2]);
+		dGeomSetOffsetRotation(obj[i].geom[k], drot[k]);
+      }
+      dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+	  dBodySetMass (obj[i].body,&m);
+		
+    }
+    else if (cmd == 'x') {
+      dGeomID g2[GPB];		// encapsulated geometries
+      dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+      // start accumulating masses for the encapsulated geometries
+      dMass m2;
+      dMassSetZero (&m);
+
+      // set random delta positions
+      for (j=0; j<GPB; j++) {
+	for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+      }
+
+      for (k=0; k<GPB; k++) {
+	obj[i].geom[k] = dCreateGeomTransform (space);
+	dGeomTransformSetCleanup (obj[i].geom[k],1);
+	if (k==0) {
+	  dReal radius = dRandReal()*0.25+0.05;
+	  g2[k] = dCreateSphere (0,radius);
+	  dMassSetSphere (&m2,DENSITY,radius);
+	}
+	else if (k==1) {
+	  g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+	  dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+	}
+	else {
+	  dReal radius = dRandReal()*0.1+0.05;
+	  dReal length = dRandReal()*1.0+0.1;
+	  g2[k] = dCreateCapsule (0,radius,length);
+	  dMassSetCapsule (&m2,DENSITY,3,radius,length);
+	}
+	dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+	// set the transformation (adjust the mass too)
+	dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMatrix3 Rtx;
+	dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+	dGeomSetRotation (g2[k],Rtx);
+	dMassRotate (&m2,Rtx);
+
+	// Translation *after* rotation
+	dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+
+	// add to the total mass
+	dMassAdd (&m,&m2);
+      }
+
+      // move all encapsulated objects so that the center of mass is (0,0,0)
+      for (k=0; k<GPB; k++) {
+	dGeomSetPosition (g2[k],
+			  dpos[k][0]-m.c[0],
+			  dpos[k][1]-m.c[1],
+			  dpos[k][2]-m.c[2]);
+      }
+      dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+    }
+
+    if (!setBody)
+     for (k=0; k < GPB; k++) {
+      if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+     }
+
+    dBodySetMass (obj[i].body,&m);
+  }
+
+  if (cmd == ' ') {
+    selected++;
+    if (selected >= num) selected = 0;
+    if (selected < 0) selected = 0;
+  }
+  else if (cmd == 'd' && selected >= 0 && selected < num) {
+    dBodyDisable (obj[selected].body);
+  }
+  else if (cmd == 'e' && selected >= 0 && selected < num) {
+    dBodyEnable (obj[selected].body);
+  }
+  else if (cmd == 'a') {
+    show_aabb ^= 1;
+  }
+  else if (cmd == 't') {
+    show_contacts ^= 1;
+  }
+  else if (cmd == 'r') {
+    random_pos ^= 1;
+  }
+  else if (cmd == '1') {
+    write_world = 1;
+  }
+}
+
+
+// draw a geom
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
+{
+  int i;
+	
+  if (!g) return;
+  if (!pos) pos = dGeomGetPosition (g);
+  if (!R) R = dGeomGetRotation (g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass) {
+    dVector3 sides;
+    dGeomBoxGetLengths (g,sides);
+    dsDrawBox (pos,R,sides);
+  }
+  else if (type == dSphereClass) {
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+  }
+  else if (type == dCapsuleClass) {
+    dReal radius,length;
+    dGeomCapsuleGetParams (g,&radius,&length);
+    dsDrawCapsule (pos,R,length,radius);
+  }
+  //<---- Convex Object
+  else if (type == dConvexClass) 
+    {
+      //dVector3 sides={0.50,0.50,0.50};
+      dsDrawConvex(pos,R,planes,
+		   planecount,
+		   points,
+		   pointcount,
+		   polygons);
+    }
+  //----> Convex Object
+  else if (type == dCylinderClass) {
+    dReal radius,length;
+    dGeomCylinderGetParams (g,&radius,&length);
+    dsDrawCylinder (pos,R,length,radius);
+  }
+  else if (type == dGeomTransformClass) {
+    dGeomID g2 = dGeomTransformGetGeom (g);
+    const dReal *pos2 = dGeomGetPosition (g2);
+    const dReal *R2 = dGeomGetRotation (g2);
+    dVector3 actual_pos;
+    dMatrix3 actual_R;
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+    actual_pos[0] += pos[0];
+    actual_pos[1] += pos[1];
+    actual_pos[2] += pos[2];
+    dMULTIPLY0_333 (actual_R,R,R2);
+    drawGeom (g2,actual_pos,actual_R,0);
+  }
+  if (show_body) {
+    dBodyID body = dGeomGetBody(g);
+    if (body) {
+      const dReal *bodypos = dBodyGetPosition (body); 
+      const dReal *bodyr = dBodyGetRotation (body); 
+      dReal bodySides[3] = { 0.1, 0.1, 0.1 };
+      dsSetColorAlpha(0,1,0,1);
+      dsDrawBox(bodypos,bodyr,bodySides); 
+    }
+  }
+  if (show_aabb) {
+    // draw the bounding box for this geom
+    dReal aabb[6];
+    dGeomGetAABB (g,aabb);
+    dVector3 bbpos;
+    for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+    dVector3 bbsides;
+    for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    dsSetColorAlpha (1,0,0,0.5);
+    dsDrawBox (bbpos,RI,bbsides);
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  dsSetColor (0,0,2);
+  dSpaceCollide (space,0,&nearCallback);
+  if (!pause) dWorldQuickStep (world,0.02);
+
+  if (write_world) {
+    FILE *f = fopen ("state.dif","wt");
+    if (f) {
+      dWorldExportDIF (world,f,"X");
+      fclose (f);
+    }
+    write_world = 0;
+  }
+  
+  // remove all contact joints
+  dJointGroupEmpty (contactgroup);
+
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+  for (int i=0; i<num; i++) {
+    for (int j=0; j < GPB; j++) {
+      if (i==selected) {
+	dsSetColor (0,0.7,1);
+      }
+      else if (! dBodyIsEnabled (obj[i].body)) {
+	dsSetColor (1,0.8,0);
+      }
+      else {
+	dsSetColor (1,1,0);
+      }
+      drawGeom (obj[i].geom[j],0,0,show_aabb);
+    }
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  dWorldSetCFM (world,1e-5);
+  dWorldSetAutoDisableFlag (world,1);
+
+#if 1
+
+  dWorldSetAutoDisableAverageSamplesCount( world, 10 );
+
+#endif
+
+
+  dWorldSetContactMaxCorrectingVel (world,0.1);
+  dWorldSetContactSurfaceLayer (world,0.001);
+  dCreatePlane (space,0,0,1,0);
+  memset (obj,0,sizeof(obj));
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_buggy.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_buggy.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_buggy.cpp	(revision 216)
@@ -0,0 +1,325 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+buggy with suspension.
+this also shows you how to use geom groups.
+
+*/
+
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define LENGTH 0.7	// chassis length
+#define WIDTH 0.5	// chassis width
+#define HEIGHT 0.2	// chassis height
+#define RADIUS 0.18	// wheel radius
+#define STARTZ 0.5	// starting height of chassis
+#define CMASS 1		// chassis mass
+#define WMASS 0.2	// wheel mass
+
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+static dBodyID body[4];
+static dJointID joint[3];	// joint[0] is the front wheel
+static dJointGroupID contactgroup;
+static dGeomID ground;
+static dSpaceID car_space;
+static dGeomID box[1];
+static dGeomID sphere[3];
+static dGeomID ground_box;
+
+
+// things that the user controls
+
+static dReal speed=0,steer=0;	// user commands
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i,n;
+
+  // only collide things with the ground
+  int g1 = (o1 == ground || o1 == ground_box);
+  int g2 = (o2 == ground || o2 == ground_box);
+  if (!(g1 ^ g2)) return;
+
+  const int N = 10;
+  dContact contact[N];
+  n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
+  if (n > 0) {
+    for (i=0; i<n; i++) {
+      contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
+	dContactSoftERP | dContactSoftCFM | dContactApprox1;
+      contact[i].surface.mu = dInfinity;
+      contact[i].surface.slip1 = 0.1;
+      contact[i].surface.slip2 = 0.1;
+      contact[i].surface.soft_erp = 0.5;
+      contact[i].surface.soft_cfm = 0.3;
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c,
+		    dGeomGetBody(contact[i].geom.g1),
+		    dGeomGetBody(contact[i].geom.g2));
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {0.8317f,-0.9817f,0.8000f};
+  static float hpr[3] = {121.0000f,-27.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("Press:\t'a' to increase speed.\n"
+	  "\t'z' to decrease speed.\n"
+	  "\t',' to steer left.\n"
+	  "\t'.' to steer right.\n"
+	  "\t' ' to reset speed and steering.\n"
+	  "\t'1' to save the current state to 'state.dif'.\n");
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  switch (cmd) {
+  case 'a': case 'A':
+    speed += 0.3;
+    break;
+  case 'z': case 'Z':
+    speed -= 0.3;
+    break;
+  case ',':
+    steer -= 0.5;
+    break;
+  case '.':
+    steer += 0.5;
+    break;
+  case ' ':
+    speed = 0;
+    steer = 0;
+    break;
+  case '1': {
+      FILE *f = fopen ("state.dif","wt");
+      if (f) {
+        dWorldExportDIF (world,f,"");
+        fclose (f);
+      }
+    }
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i;
+  if (!pause) {
+    // motor
+    dJointSetHinge2Param (joint[0],dParamVel2,-speed);
+    dJointSetHinge2Param (joint[0],dParamFMax2,0.1);
+
+    // steering
+    dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
+    if (v > 0.1) v = 0.1;
+    if (v < -0.1) v = -0.1;
+    v *= 10.0;
+    dJointSetHinge2Param (joint[0],dParamVel,v);
+    dJointSetHinge2Param (joint[0],dParamFMax,0.2);
+    dJointSetHinge2Param (joint[0],dParamLoStop,-0.75);
+    dJointSetHinge2Param (joint[0],dParamHiStop,0.75);
+    dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1);
+
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldStep (world,0.05);
+
+    // remove all contact joints
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (0,1,1);
+  dsSetTexture (DS_WOOD);
+  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
+  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
+  dsSetColor (1,1,1);
+  for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
+				       dBodyGetRotation(body[i]),0.02f,RADIUS);
+
+  dVector3 ss;
+  dGeomBoxGetLengths (ground_box,ss);
+  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
+
+  /*
+  printf ("%.10f %.10f %.10f %.10f\n",
+	  dJointGetHingeAngle (joint[1]),
+	  dJointGetHingeAngle (joint[2]),
+	  dJointGetHingeAngleRate (joint[1]),
+	  dJointGetHingeAngleRate (joint[2]));
+  */
+}
+
+
+int main (int argc, char **argv)
+{
+  int i;
+  dMass m;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  ground = dCreatePlane (space,0,0,1,0);
+
+  // chassis body
+  body[0] = dBodyCreate (world);
+  dBodySetPosition (body[0],0,0,STARTZ);
+  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
+  dMassAdjust (&m,CMASS);
+  dBodySetMass (body[0],&m);
+  box[0] = dCreateBox (0,LENGTH,WIDTH,HEIGHT);
+  dGeomSetBody (box[0],body[0]);
+
+  // wheel bodies
+  for (i=1; i<=3; i++) {
+    body[i] = dBodyCreate (world);
+    dQuaternion q;
+    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
+    dBodySetQuaternion (body[i],q);
+    dMassSetSphere (&m,1,RADIUS);
+    dMassAdjust (&m,WMASS);
+    dBodySetMass (body[i],&m);
+    sphere[i-1] = dCreateSphere (0,RADIUS);
+    dGeomSetBody (sphere[i-1],body[i]);
+  }
+  dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
+  dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);
+
+  // front wheel hinge
+  /*
+  joint[0] = dJointCreateHinge2 (world,0);
+  dJointAttach (joint[0],body[0],body[1]);
+  const dReal *a = dBodyGetPosition (body[1]);
+  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
+  dJointSetHinge2Axis1 (joint[0],0,0,1);
+  dJointSetHinge2Axis2 (joint[0],0,1,0);
+  */
+
+  // front and back wheel hinges
+  for (i=0; i<3; i++) {
+    joint[i] = dJointCreateHinge2 (world,0);
+    dJointAttach (joint[i],body[0],body[i+1]);
+    const dReal *a = dBodyGetPosition (body[i+1]);
+    dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
+    dJointSetHinge2Axis1 (joint[i],0,0,1);
+    dJointSetHinge2Axis2 (joint[i],0,1,0);
+  }
+
+  // set joint suspension
+  for (i=0; i<3; i++) {
+    dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4);
+    dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8);
+  }
+
+  // lock back wheels along the steering axis
+  for (i=1; i<3; i++) {
+    // set stops to make sure wheels always stay in alignment
+    dJointSetHinge2Param (joint[i],dParamLoStop,0);
+    dJointSetHinge2Param (joint[i],dParamHiStop,0);
+    // the following alternative method is no good as the wheels may get out
+    // of alignment:
+    //   dJointSetHinge2Param (joint[i],dParamVel,0);
+    //   dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
+  }
+
+  // create car space and add it to the top level space
+  car_space = dSimpleSpaceCreate (space);
+  dSpaceSetCleanup (car_space,0);
+  dSpaceAdd (car_space,box[0]);
+  dSpaceAdd (car_space,sphere[0]);
+  dSpaceAdd (car_space,sphere[1]);
+  dSpaceAdd (car_space,sphere[2]);
+
+  // environment
+  ground_box = dCreateBox (space,2,1.5,1);
+  dMatrix3 R;
+  dRFromAxisAndAngle (R,0,1,0,-0.15);
+  dGeomSetPosition (ground_box,2,0,-0.34);
+  dGeomSetRotation (ground_box,R);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dGeomDestroy (box[0]);
+  dGeomDestroy (sphere[0]);
+  dGeomDestroy (sphere[1]);
+  dGeomDestroy (sphere[2]);
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_chain1.c
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_chain1.c	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_chain1.c	(revision 216)
@@ -0,0 +1,171 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* exercise the C interface */
+
+#include <stdio.h>
+#include "ode/ode.h"
+#include "drawstuff/drawstuff.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+/* select correct drawing functions */
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+/* some constants */
+
+#define NUM 10			/* number of boxes */
+#define SIDE (0.2)		/* side length of a box */
+#define MASS (1.0)		/* mass of a box */
+#define RADIUS (0.1732f)	/* sphere radius */
+
+
+/* dynamics and collision objects */
+
+static dWorldID world;
+static dSpaceID space;
+static dBodyID body[NUM];
+static dJointID joint[NUM-1];
+static dJointGroupID contactgroup;
+static dGeomID sphere[NUM];
+
+
+/* this is called by dSpaceCollide when two objects in space are
+ * potentially colliding.
+ */
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  /* exit without doing anything if the two bodies are connected by a joint */
+  dBodyID b1,b2;
+  dContact contact;
+
+  b1 = dGeomGetBody(o1);
+  b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnected (b1,b2)) return;
+
+  contact.surface.mode = 0;
+  contact.surface.mu = 0.1;
+  contact.surface.mu2 = 0;
+  if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) {
+    dJointID c = dJointCreateContact (world,contactgroup,&contact);
+    dJointAttach (c,b1,b2);
+  }
+}
+
+
+/* start simulation - set viewpoint */
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+/* simulation loop */
+
+static void simLoop (int pause)
+{
+  int i;
+  if (!pause) {
+    static double angle = 0;
+    angle += 0.05;
+    dBodyAddForce (body[NUM-1],0,0,1.5*(sin(angle)+1.0));
+
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldStep (world,0.05);
+
+    /* remove all contact joints */
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+  for (i=0; i<NUM; i++) dsDrawSphere (dBodyGetPosition(body[i]),
+				      dBodyGetRotation(body[i]),RADIUS);
+}
+
+
+int main (int argc, char **argv)
+{
+  int i;
+  dReal k;
+  dMass m;
+
+  /* setup pointers to drawstuff callback functions */
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = 0;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  /* create world */
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (1000000);
+  dWorldSetGravity (world,0,0,-0.5);
+  dCreatePlane (space,0,0,1,0);
+
+  for (i=0; i<NUM; i++) {
+    body[i] = dBodyCreate (world);
+    k = i*SIDE;
+    dBodySetPosition (body[i],k,k,k+0.4);
+    dMassSetBox (&m,1,SIDE,SIDE,SIDE);
+    dMassAdjust (&m,MASS);
+    dBodySetMass (body[i],&m);
+    sphere[i] = dCreateSphere (space,RADIUS);
+    dGeomSetBody (sphere[i],body[i]);
+  }
+  for (i=0; i<(NUM-1); i++) {
+    joint[i] = dJointCreateBall (world,0);
+    dJointAttach (joint[i],body[i],body[i+1]);
+    k = (i+0.5)*SIDE;
+    dJointSetBallAnchor (joint[i],k,k,k+0.4);
+  }
+
+  /* run simulation */
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_chain2.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_chain2.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_chain2.cpp	(revision 216)
@@ -0,0 +1,165 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* exercise the C++ interface */
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define NUM 10			// number of boxes
+#define SIDE (0.2)		// side length of a box
+#define MASS (1.0)		// mass of a box
+#define RADIUS (0.1732f)	// sphere radius
+
+
+// dynamics and collision objects
+
+static dWorld world;
+static dSimpleSpace space (0);
+static dBody body[NUM];
+static dBallJoint joint[NUM-1];
+static dJointGroup contactgroup;
+static dBox box[NUM];
+
+
+// this is called by space.collide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnected (b1,b2)) return;
+
+  // @@@ it's still more convenient to use the C interface here.
+
+  dContact contact;
+  contact.surface.mode = 0;
+  contact.surface.mu = dInfinity;
+  if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) {
+    dJointID c = dJointCreateContact (world.id(),contactgroup.id(),&contact);
+    dJointAttach (c,b1,b2);
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  if (!pause) {
+    static double angle = 0;
+    angle += 0.05;
+    body[NUM-1].addForce (0,0,1.5*(sin(angle)+1.0));
+
+    space.collide (0,&nearCallback);
+    world.step (0.05);
+
+    // remove all contact joints
+    contactgroup.empty();
+  }
+
+  dReal sides[3] = {SIDE,SIDE,SIDE};
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+  for (int i=0; i<NUM; i++)
+    dsDrawBox (body[i].getPosition(),body[i].getRotation(),sides);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = 0;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+
+  int i;
+  contactgroup.create (0);
+  world.setGravity (0,0,-0.5);
+  dWorldSetCFM (world.id(),1e-5);
+  dPlane plane (space,0,0,1,0);
+
+  for (i=0; i<NUM; i++) {
+    body[i].create (world);
+    dReal k = i*SIDE;
+    body[i].setPosition (k,k,k+0.4);
+    dMass m;
+    m.setBox (1,SIDE,SIDE,SIDE);
+    m.adjust (MASS);
+    body[i].setMass (&m);
+    body[i].setData ((void*)(size_t)i);
+
+    box[i].create (space,SIDE,SIDE,SIDE);
+    box[i].setBody (body[i]);
+  }
+  for (i=0; i<(NUM-1); i++) {
+    joint[i].create (world);
+    joint[i].attach (body[i],body[i+1]);
+    dReal k = (i+0.5)*SIDE;
+    joint[i].setAnchor (k,k,k+0.4);
+  }
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_collision.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_collision.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_collision.cpp	(revision 216)
@@ -0,0 +1,1371 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+collision tests. if this program is run without any arguments it will
+perform all the tests multiple times, with different random data for each
+test. if this program is given a test number it will run that test
+graphically/interactively, in which case the space bar can be used to
+change the random test conditions.
+
+*/
+
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+#ifdef dDOUBLE
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawBox dsDrawBoxD
+#define dsDrawLine dsDrawLineD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+//****************************************************************************
+// test infrastructure, including constants and macros
+
+#define TEST_REPS1 1000		// run each test this many times (first batch)
+#define TEST_REPS2 10000	// run each test this many times (second batch)
+const dReal tol = 1e-8;		// tolerance used for numerical checks
+#define MAX_TESTS 1000		// maximum number of test slots
+#define Z_OFFSET 2		// z offset for drawing (to get above ground)
+
+
+// test function. returns 1 if the test passed or 0 if it failed
+typedef int test_function_t();
+
+struct TestSlot {
+  int number;			// number of test
+  char *name;			// name of test
+  int failcount;
+  test_function_t *test_fn;
+  int last_failed_line;
+};
+TestSlot testslot[MAX_TESTS];
+
+
+// globals used by the test functions
+int graphical_test=0;		// show graphical results of this test, 0=none
+int current_test;		// currently execiting test
+int draw_all_objects_called;
+
+
+#define MAKE_TEST(number,function) \
+  if (testslot[number].name) dDebug (0,"test number already used"); \
+  if (number <= 0 || number >= MAX_TESTS) dDebug (0,"bad test number"); \
+  testslot[number].name = # function; \
+  testslot[number].test_fn = function;
+
+#define FAILED() { if (graphical_test==0) { \
+  testslot[current_test].last_failed_line=__LINE__; return 0; } }
+#define PASSED() { return 1; }
+
+//****************************************************************************
+// globals
+
+/* int dBoxBox (const dVector3 p1, const dMatrix3 R1,
+	     const dVector3 side1, const dVector3 p2,
+	     const dMatrix3 R2, const dVector3 side2,
+	     dVector3 normal, dReal *depth, int *code,
+	     int maxc, dContactGeom *contact, int skip); */
+
+void dLineClosestApproach (const dVector3 pa, const dVector3 ua,
+			   const dVector3 pb, const dVector3 ub,
+			   dReal *alpha, dReal *beta);
+
+//****************************************************************************
+// draw all objects in a space, and draw all the collision contact points
+
+void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i,j,n;
+  const int N = 100;
+  dContactGeom contact[N];
+
+  if (dGeomGetClass (o2) == dRayClass) {
+    n = dCollide (o2,o1,N,&contact[0],sizeof(dContactGeom));
+  }
+  else {
+    n = dCollide (o1,o2,N,&contact[0],sizeof(dContactGeom));
+  }
+  if (n > 0) {
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    const dReal ss[3] = {0.01,0.01,0.01};
+    for (i=0; i<n; i++) {
+      contact[i].pos[2] += Z_OFFSET;
+      dsDrawBox (contact[i].pos,RI,ss);
+      dVector3 n;
+      for (j=0; j<3; j++) n[j] = contact[i].pos[j] + 0.1*contact[i].normal[j];
+      dsDrawLine (contact[i].pos,n);
+    }
+  }
+}
+
+
+void draw_all_objects (dSpaceID space)
+{
+  int i, j;
+
+  draw_all_objects_called = 1;
+  if (!graphical_test) return;
+  int n = dSpaceGetNumGeoms (space);
+
+  // draw all contact points
+  dsSetColor (0,1,1);
+  dSpaceCollide (space,0,&nearCallback);
+
+  // draw all rays
+  for (i=0; i<n; i++) {
+    dGeomID g = dSpaceGetGeom (space,i);
+    if (dGeomGetClass (g) == dRayClass) {
+      dsSetColor (1,1,1);
+      dVector3 origin,dir;
+      dGeomRayGet (g,origin,dir);
+      origin[2] += Z_OFFSET;
+      dReal length = dGeomRayGetLength (g);
+      for (j=0; j<3; j++) dir[j] = dir[j]*length + origin[j];
+      dsDrawLine (origin,dir);
+      dsSetColor (0,0,1);
+      dsDrawSphere (origin,dGeomGetRotation(g),0.01);
+    }
+  }
+
+  // draw all other objects
+  for (i=0; i<n; i++) {
+    dGeomID g = dSpaceGetGeom (space,i);
+    dVector3 pos;
+    if (dGeomGetClass (g) != dPlaneClass) {
+      memcpy (pos,dGeomGetPosition(g),sizeof(pos));
+      pos[2] += Z_OFFSET;
+    }
+
+    switch (dGeomGetClass (g)) {
+
+    case dSphereClass: {
+      dsSetColorAlpha (1,0,0,0.8);
+      dReal radius = dGeomSphereGetRadius (g);
+      dsDrawSphere (pos,dGeomGetRotation(g),radius);
+      break;
+    }
+
+    case dBoxClass: {
+      dsSetColorAlpha (1,1,0,0.8);
+      dVector3 sides;
+      dGeomBoxGetLengths (g,sides);
+      dsDrawBox (pos,dGeomGetRotation(g),sides);
+      break;
+    }
+
+    case dCapsuleClass: {
+      dsSetColorAlpha (0,1,0,0.8);
+      dReal radius,length;
+      dGeomCapsuleGetParams (g,&radius,&length);
+      dsDrawCapsule (pos,dGeomGetRotation(g),length,radius);
+      break;
+    }
+
+    case dPlaneClass: {
+      dVector4 n;
+      dMatrix3 R,sides;
+      dVector3 pos2;
+      dGeomPlaneGetParams (g,n);
+      dRFromZAxis (R,n[0],n[1],n[2]);
+      for (j=0; j<3; j++) pos[j] = n[j]*n[3];
+      pos[2] += Z_OFFSET;
+      sides[0] = 2;
+      sides[1] = 2;
+      sides[2] = 0.001;
+      dsSetColor (1,0,1);
+      for (j=0; j<3; j++) pos2[j] = pos[j] + 0.1*n[j];
+      dsDrawLine (pos,pos2);
+      dsSetColorAlpha (1,0,1,0.8);
+      dsDrawBox (pos,R,sides);
+      break;
+    }
+
+    }
+  }
+}
+
+//****************************************************************************
+// point depth tests
+
+int test_sphere_point_depth()
+{
+  int j;
+  dVector3 p,q;
+  dMatrix3 R;
+  dReal r,d;
+
+  dSimpleSpace space(0);
+  dGeomID sphere = dCreateSphere (0,1);
+  dSpaceAdd (space,sphere);
+
+  // ********** make a random sphere of radius r at position p
+
+  r = dRandReal()+0.1;
+  dGeomSphereSetRadius (sphere,r);
+  dMakeRandomVector (p,3,1.0);
+  dGeomSetPosition (sphere,p[0],p[1],p[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (sphere,R);
+
+  // ********** test center point has depth r
+
+  if (dFabs(dGeomSpherePointDepth (sphere,p[0],p[1],p[2]) - r) > tol) FAILED();
+
+  // ********** test point on surface has depth 0
+
+  for (j=0; j<3; j++) q[j] = dRandReal()-0.5;
+  dNormalize3 (q);
+  for (j=0; j<3; j++) q[j] = q[j]*r + p[j];
+  if (dFabs(dGeomSpherePointDepth (sphere,q[0],q[1],q[2])) > tol) FAILED();
+
+  // ********** test point at random depth
+
+  d = (dRandReal()*2-1) * r;
+  for (j=0; j<3; j++) q[j] = dRandReal()-0.5;
+  dNormalize3 (q);
+  for (j=0; j<3; j++) q[j] = q[j]*(r-d) + p[j];
+  if (dFabs(dGeomSpherePointDepth (sphere,q[0],q[1],q[2])-d) > tol) FAILED();
+
+  PASSED();
+}
+
+
+int test_box_point_depth()
+{
+  int i,j;
+  dVector3 s,p,q,q2;	// s = box sides
+  dMatrix3 R;
+  dReal ss,d;		// ss = smallest side
+
+  dSimpleSpace space(0);
+  dGeomID box = dCreateBox (0,1,1,1);
+  dSpaceAdd (space,box);
+
+  // ********** make a random box
+
+  for (j=0; j<3; j++) s[j] = dRandReal() + 0.1;
+  dGeomBoxSetLengths (box,s[0],s[1],s[2]);
+  dMakeRandomVector (p,3,1.0);
+  dGeomSetPosition (box,p[0],p[1],p[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (box,R);
+
+  // ********** test center point has depth of smallest side
+
+  ss = 1e9;
+  for (j=0; j<3; j++) if (s[j] < ss) ss = s[j];
+  if (dFabs(dGeomBoxPointDepth (box,p[0],p[1],p[2]) - 0.5*ss) > tol)
+    FAILED();
+
+  // ********** test point on surface has depth 0
+
+  for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
+  i = dRandInt (3);
+  if (dRandReal() > 0.5) q[i] = 0.5*s[i]; else q[i] = -0.5*s[i];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  if (dFabs(dGeomBoxPointDepth (box,q2[0],q2[1],q2[2])) > tol) FAILED();
+
+  // ********** test points outside box have -ve depth
+
+  for (j=0; j<3; j++) {
+    q[j] = 0.5*s[j] + dRandReal() + 0.01;
+    if (dRandReal() > 0.5) q[j] = -q[j];
+  }
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  if (dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) >= 0) FAILED();
+
+  // ********** test points inside box have +ve depth
+
+  for (j=0; j<3; j++) q[j] = s[j] * 0.99 * (dRandReal()-0.5);
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  if (dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) <= 0) FAILED();
+
+  // ********** test random depth of point aligned along axis (up to ss deep)
+
+  i = dRandInt (3);
+  for (j=0; j<3; j++) q[j] = 0;
+  d = (dRandReal()*(ss*0.5+1)-1);
+  q[i] = s[i]*0.5 - d;
+  if (dRandReal() > 0.5) q[i] = -q[i];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  if (dFabs(dGeomBoxPointDepth (box,q2[0],q2[1],q2[2]) - d) >= tol) FAILED();
+
+  PASSED();
+}
+
+
+int test_ccylinder_point_depth()
+{
+  int j;
+  dVector3 p,a;
+  dMatrix3 R;
+  dReal r,l,beta,x,y,d;
+
+  dSimpleSpace space(0);
+  dGeomID ccyl = dCreateCapsule (0,1,1);
+  dSpaceAdd (space,ccyl);
+
+  // ********** make a random ccyl
+
+  r = dRandReal()*0.5 + 0.01;
+  l = dRandReal()*1 + 0.01;
+  dGeomCapsuleSetParams (ccyl,r,l);
+  dMakeRandomVector (p,3,1.0);
+  dGeomSetPosition (ccyl,p[0],p[1],p[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ccyl,R);
+
+  // ********** test point on axis has depth of 'radius'
+
+  beta = dRandReal()-0.5;
+  for (j=0; j<3; j++) a[j] = p[j] + l*beta*R[j*4+2];
+  if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - r) >= tol)
+    FAILED();
+
+  // ********** test point on surface (excluding caps) has depth 0
+
+  beta = dRandReal()*2*M_PI;
+  x = r*sin(beta);
+  y = r*cos(beta);
+  beta = dRandReal()-0.5;
+  for (j=0; j<3; j++) a[j] = p[j] + x*R[j*4+0] + y*R[j*4+1] + l*beta*R[j*4+2];
+  if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2])) >= tol) FAILED();
+
+  // ********** test point on surface of caps has depth 0
+
+  for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
+  dNormalize3 (a);
+  if (dDOT14(a,R+2) > 0) {
+    for (j=0; j<3; j++) a[j] = p[j] + a[j]*r + l*0.5*R[j*4+2];
+  }
+  else {
+    for (j=0; j<3; j++) a[j] = p[j] + a[j]*r - l*0.5*R[j*4+2];
+  }
+  if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2])) >= tol) FAILED();
+
+  // ********** test point inside ccyl has positive depth
+
+  for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
+  dNormalize3 (a);
+  beta = dRandReal()-0.5;
+  for (j=0; j<3; j++) a[j] = p[j] + a[j]*r*0.99 + l*beta*R[j*4+2];
+  if (dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) < 0) FAILED();
+
+  // ********** test point depth (1)
+
+  d = (dRandReal()*2-1) * r;
+  beta = dRandReal()*2*M_PI;
+  x = (r-d)*sin(beta);
+  y = (r-d)*cos(beta);
+  beta = dRandReal()-0.5;
+  for (j=0; j<3; j++) a[j] = p[j] + x*R[j*4+0] + y*R[j*4+1] + l*beta*R[j*4+2];
+  if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - d) >= tol)
+    FAILED();
+
+  // ********** test point depth (2)
+
+  d = (dRandReal()*2-1) * r;
+  for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
+  dNormalize3 (a);
+  if (dDOT14(a,R+2) > 0) {
+    for (j=0; j<3; j++) a[j] = p[j] + a[j]*(r-d) + l*0.5*R[j*4+2];
+  }
+  else {
+    for (j=0; j<3; j++) a[j] = p[j] + a[j]*(r-d) - l*0.5*R[j*4+2];
+  }
+  if (dFabs(dGeomCapsulePointDepth (ccyl,a[0],a[1],a[2]) - d) >= tol)
+    FAILED();
+
+  PASSED();
+}
+
+
+int test_plane_point_depth()
+{
+  int j;
+  dVector3 n,p,q,a,b;	// n = plane normal
+  dReal d;
+
+  dSimpleSpace space(0);
+  dGeomID plane = dCreatePlane (0,0,0,1,0);
+  dSpaceAdd (space,plane);
+
+  // ********** make a random plane
+
+  for (j=0; j<3; j++) n[j] = dRandReal() - 0.5;
+  dNormalize3 (n);
+  d = dRandReal() - 0.5;
+  dGeomPlaneSetParams (plane,n[0],n[1],n[2],d);
+  dPlaneSpace (n,p,q);
+
+  // ********** test point on plane has depth 0
+
+  a[0] = dRandReal() - 0.5;
+  a[1] = dRandReal() - 0.5;
+  a[2] = 0;
+  for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
+  if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2])) >= tol) FAILED();
+
+  // ********** test arbitrary depth point
+
+  a[0] = dRandReal() - 0.5;
+  a[1] = dRandReal() - 0.5;
+  a[2] = dRandReal() - 0.5;
+  for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
+  if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2]) + a[2]) >= tol)
+    FAILED();
+
+  // ********** test depth-1 point
+
+  a[0] = dRandReal() - 0.5;
+  a[1] = dRandReal() - 0.5;
+  a[2] = -1;
+  for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
+  if (dFabs(dGeomPlanePointDepth (plane,b[0],b[1],b[2]) - 1) >= tol) FAILED();
+
+  PASSED();
+}
+
+//****************************************************************************
+// ray tests
+
+int test_ray_and_sphere()
+{
+  int j;
+  dContactGeom contact;
+  dVector3 p,q,q2,n,v1;
+  dMatrix3 R;
+  dReal r,k;
+
+  dSimpleSpace space(0);
+  dGeomID ray = dCreateRay (0,0);
+  dGeomID sphere = dCreateSphere (0,1);
+  dSpaceAdd (space,ray);
+  dSpaceAdd (space,sphere);
+
+  // ********** make a random sphere of radius r at position p
+
+  r = dRandReal()+0.1;
+  dGeomSphereSetRadius (sphere,r);
+  dMakeRandomVector (p,3,1.0);
+  dGeomSetPosition (sphere,p[0],p[1],p[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (sphere,R);
+
+  // ********** test zero length ray just inside sphere
+
+  dGeomRaySetLength (ray,0);
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  for (j=0; j<3; j++) q[j] = 0.99*r * q[j] + p[j];
+  dGeomSetPosition (ray,q[0],q[1],q[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ray,R);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test zero length ray just outside that sphere
+
+  dGeomRaySetLength (ray,0);
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j];
+  dGeomSetPosition (ray,q[0],q[1],q[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ray,R);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test finite length ray totally contained inside the sphere
+
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  k = dRandReal();
+  for (j=0; j<3; j++) q[j] = k*r*0.99 * q[j] + p[j];
+  dMakeRandomVector (q2,3,1.0);
+  dNormalize3 (q2);
+  k = dRandReal();
+  for (j=0; j<3; j++) q2[j] = k*r*0.99 * q2[j] + p[j];
+  for (j=0; j<3; j++) n[j] = q2[j] - q[j];
+  dNormalize3 (n);
+  dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,dDISTANCE (q,q2));
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test finite length ray totally outside the sphere
+
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  do {
+    dMakeRandomVector (n,3,1.0);
+    dNormalize3 (n);
+  }
+  while (dDOT(n,q) < 0);	// make sure normal goes away from sphere
+  for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j];
+  dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,100);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray from outside to just above surface
+
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  for (j=0; j<3; j++) n[j] = -q[j];
+  for (j=0; j<3; j++) q2[j] = 2*r * q[j] + p[j];
+  dGeomRaySet (ray,q2[0],q2[1],q2[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,0.99*r);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray from outside to just below surface
+
+  dGeomRaySetLength (ray,1.01*r);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+  for (j=0; j<3; j++) q2[j] = r * q[j] + p[j];
+  if (dDISTANCE (contact.pos,q2) > tol) FAILED();
+
+  // ********** test contact point distance for random rays
+
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  k = dRandReal()+0.5;
+  for (j=0; j<3; j++) q[j] = k*r * q[j] + p[j];
+  dMakeRandomVector (n,3,1.0);
+  dNormalize3 (n);
+  dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,100);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom))) {
+    k = dDISTANCE (contact.pos,dGeomGetPosition(sphere));
+    if (dFabs(k - r) > tol) FAILED();
+    // also check normal signs
+    if (dDOT (n,contact.normal) > 0) FAILED();
+    // also check depth of contact point
+    if (dFabs (dGeomSpherePointDepth
+	       (sphere,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
+      FAILED();
+
+    draw_all_objects (space);
+  }
+
+  // ********** test tangential grazing - miss
+
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  dPlaneSpace (q,n,v1);
+  for (j=0; j<3; j++) q[j] = 1.01*r * q[j] + p[j];
+  for (j=0; j<3; j++) q[j] -= n[j];
+  dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,2);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test tangential grazing - hit
+
+  dMakeRandomVector (q,3,1.0);
+  dNormalize3 (q);
+  dPlaneSpace (q,n,v1);
+  for (j=0; j<3; j++) q[j] = 0.99*r * q[j] + p[j];
+  for (j=0; j<3; j++) q[j] -= n[j];
+  dGeomRaySet (ray,q[0],q[1],q[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,2);
+  if (dCollide (ray,sphere,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+
+  PASSED();
+}
+
+
+int test_ray_and_box()
+{
+  int i,j;
+  dContactGeom contact;
+  dVector3 s,p,q,n,q2,q3,q4;		// s = box sides
+  dMatrix3 R;
+  dReal k;
+
+  dSimpleSpace space(0);
+  dGeomID ray = dCreateRay (0,0);
+  dGeomID box = dCreateBox (0,1,1,1);
+  dSpaceAdd (space,ray);
+  dSpaceAdd (space,box);
+
+  // ********** make a random box
+
+  for (j=0; j<3; j++) s[j] = dRandReal() + 0.1;
+  dGeomBoxSetLengths (box,s[0],s[1],s[2]);
+  dMakeRandomVector (p,3,1.0);
+  dGeomSetPosition (box,p[0],p[1],p[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (box,R);
+
+  // ********** test zero length ray just inside box
+
+  dGeomRaySetLength (ray,0);
+  for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
+  i = dRandInt (3);
+  if (dRandReal() > 0.5) q[i] = 0.99*0.5*s[i]; else q[i] = -0.99*0.5*s[i];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  dGeomSetPosition (ray,q2[0],q2[1],q2[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ray,R);
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test zero length ray just outside box
+
+  dGeomRaySetLength (ray,0);
+  for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
+  i = dRandInt (3);
+  if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  dGeomSetPosition (ray,q2[0],q2[1],q2[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ray,R);
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test finite length ray totally contained inside the box
+
+  for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*0.99*s[j];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  for (j=0; j<3; j++) q3[j] = (dRandReal()-0.5)*0.99*s[j];
+  dMultiply0 (q4,dGeomGetRotation(box),q3,3,3,1);
+  for (j=0; j<3; j++) q4[j] += p[j];
+  for (j=0; j<3; j++) n[j] = q4[j] - q2[j];
+  dNormalize3 (n);
+  dGeomRaySet (ray,q2[0],q2[1],q2[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,dDISTANCE(q2,q4));
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test finite length ray totally outside the box
+
+  for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
+  i = dRandInt (3);
+  if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q3[j] = q2[j] + p[j];
+  dNormalize3 (q2);
+  dGeomRaySet (ray,q3[0],q3[1],q3[2],q2[0],q2[1],q2[2]);
+  dGeomRaySetLength (ray,10);
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray from outside to just above surface
+
+  for (j=0; j<3; j++) q[j] = (dRandReal()-0.5)*s[j];
+  i = dRandInt (3);
+  if (dRandReal() > 0.5) q[i] = 1.01*0.5*s[i]; else q[i] = -1.01*0.5*s[i];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q3[j] = 2*q2[j] + p[j];
+  k = dSqrt(q2[0]*q2[0] + q2[1]*q2[1] + q2[2]*q2[2]);
+  for (j=0; j<3; j++) q2[j] = -q2[j];
+  dGeomRaySet (ray,q3[0],q3[1],q3[2],q2[0],q2[1],q2[2]);
+  dGeomRaySetLength (ray,k*0.99);
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray from outside to just below surface
+
+  dGeomRaySetLength (ray,k*1.01);
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+
+  // ********** test contact point position for random rays
+
+  for (j=0; j<3; j++) q[j] = dRandReal()*s[j];
+  dMultiply0 (q2,dGeomGetRotation(box),q,3,3,1);
+  for (j=0; j<3; j++) q2[j] += p[j];
+  for (j=0; j<3; j++) q3[j] = dRandReal()-0.5;
+  dNormalize3 (q3);
+  dGeomRaySet (ray,q2[0],q2[1],q2[2],q3[0],q3[1],q3[2]);
+  dGeomRaySetLength (ray,10);
+  if (dCollide (ray,box,1,&contact,sizeof(dContactGeom))) {
+    // check depth of contact point
+    if (dFabs (dGeomBoxPointDepth
+	       (box,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
+      FAILED();
+    // check position of contact point
+    for (j=0; j<3; j++) contact.pos[j] -= p[j];
+    dMultiply1 (q,dGeomGetRotation(box),contact.pos,3,3,1);
+    if ( dFabs(dFabs (q[0]) - 0.5*s[0]) > tol &&
+	 dFabs(dFabs (q[1]) - 0.5*s[1]) > tol &&
+	 dFabs(dFabs (q[2]) - 0.5*s[2]) > tol) {
+      FAILED();
+    }
+    // also check normal signs
+    if (dDOT (q3,contact.normal) > 0) FAILED();
+
+    draw_all_objects (space);
+  }
+
+  PASSED();
+}
+
+
+int test_ray_and_ccylinder()
+{
+  int j;
+  dContactGeom contact;
+  dVector3 p,a,b,n;
+  dMatrix3 R;
+  dReal r,l,k,x,y;
+
+  dSimpleSpace space(0);
+  dGeomID ray = dCreateRay (0,0);
+  dGeomID ccyl = dCreateCapsule (0,1,1);
+  dSpaceAdd (space,ray);
+  dSpaceAdd (space,ccyl);
+
+  // ********** make a random capped cylinder
+
+  r = dRandReal()*0.5 + 0.01;
+  l = dRandReal()*1 + 0.01;
+  dGeomCapsuleSetParams (ccyl,r,l);
+  dMakeRandomVector (p,3,1.0);
+  dGeomSetPosition (ccyl,p[0],p[1],p[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ccyl,R);
+
+  // ********** test ray completely within ccyl
+
+  for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
+  dNormalize3 (a);
+  k = (dRandReal()-0.5)*l;
+  for (j=0; j<3; j++) a[j] = p[j] + r*0.99*a[j] + k*0.99*R[j*4+2];
+  for (j=0; j<3; j++) b[j] = dRandReal()-0.5;
+  dNormalize3 (b);
+  k = (dRandReal()-0.5)*l;
+  for (j=0; j<3; j++) b[j] = p[j] + r*0.99*b[j] + k*0.99*R[j*4+2];
+  dGeomRaySetLength (ray,dDISTANCE(a,b));
+  for (j=0; j<3; j++) b[j] -= a[j];
+  dNormalize3 (b);
+  dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]);
+  if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray outside ccyl that just misses (between caps)
+
+  k = dRandReal()*2*M_PI;
+  x = sin(k);
+  y = cos(k);
+  for (j=0; j<3; j++) a[j] = x*R[j*4+0] + y*R[j*4+1];
+  k = (dRandReal()-0.5)*l;
+  for (j=0; j<3; j++) b[j] = -a[j]*r*2 + k*R[j*4+2] + p[j];
+  dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]);
+  dGeomRaySetLength (ray,r*0.99);
+  if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray outside ccyl that just hits (between caps)
+
+  dGeomRaySetLength (ray,r*1.01);
+  if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+  // check depth of contact point
+  if (dFabs (dGeomCapsulePointDepth
+	     (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
+    FAILED();
+
+  // ********** test ray outside ccyl that just misses (caps)
+
+  for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
+  dNormalize3 (a);
+  if (dDOT14(a,R+2) < 0) {
+    for (j=0; j<3; j++) b[j] = p[j] - a[j]*2*r + l*0.5*R[j*4+2];
+  }
+  else {
+    for (j=0; j<3; j++) b[j] = p[j] - a[j]*2*r - l*0.5*R[j*4+2];
+  }
+  dGeomRaySet (ray,b[0],b[1],b[2],a[0],a[1],a[2]);
+  dGeomRaySetLength (ray,r*0.99);
+  if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray outside ccyl that just hits (caps)
+
+  dGeomRaySetLength (ray,r*1.01);
+  if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+  // check depth of contact point
+  if (dFabs (dGeomCapsulePointDepth
+	     (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
+    FAILED();
+
+  // ********** test random rays
+
+  for (j=0; j<3; j++) a[j] = dRandReal()-0.5;
+  for (j=0; j<3; j++) n[j] = dRandReal()-0.5;
+  dNormalize3 (n);
+  dGeomRaySet (ray,a[0],a[1],a[2],n[0],n[1],n[2]);
+  dGeomRaySetLength (ray,10);
+
+  if (dCollide (ray,ccyl,1,&contact,sizeof(dContactGeom))) {
+    // check depth of contact point
+    if (dFabs (dGeomCapsulePointDepth
+	       (ccyl,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
+      FAILED();
+
+    // check normal signs
+    if (dDOT (n,contact.normal) > 0) FAILED();
+
+    draw_all_objects (space);
+  }
+
+  PASSED();
+}
+
+
+int test_ray_and_plane()
+{
+  int j;
+  dContactGeom contact;
+  dVector3 n,p,q,a,b,g,h;		// n,d = plane parameters
+  dMatrix3 R;
+  dReal d;
+
+  dSimpleSpace space(0);
+  dGeomID ray = dCreateRay (0,0);
+  dGeomID plane = dCreatePlane (0,0,0,1,0);
+  dSpaceAdd (space,ray);
+  dSpaceAdd (space,plane);
+
+  // ********** make a random plane
+
+  for (j=0; j<3; j++) n[j] = dRandReal() - 0.5;
+  dNormalize3 (n);
+  d = dRandReal() - 0.5;
+  dGeomPlaneSetParams (plane,n[0],n[1],n[2],d);
+  dPlaneSpace (n,p,q);
+
+  // ********** test finite length ray below plane
+
+  dGeomRaySetLength (ray,0.09);
+  a[0] = dRandReal()-0.5;
+  a[1] = dRandReal()-0.5;
+  a[2] = -dRandReal()*0.5 - 0.1;
+  for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
+  dGeomSetPosition (ray,b[0],b[1],b[2]);
+  dRFromAxisAndAngle (R,dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2-1,dRandReal()*10-5);
+  dGeomSetRotation (ray,R);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test finite length ray above plane
+
+  a[0] = dRandReal()-0.5;
+  a[1] = dRandReal()-0.5;
+  a[2] = dRandReal()*0.5 + 0.01;
+  for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
+  g[0] = dRandReal()-0.5;
+  g[1] = dRandReal()-0.5;
+  g[2] = dRandReal() + 0.01;
+  for (j=0; j<3; j++) h[j] = g[0]*p[j] + g[1]*q[j] + g[2]*n[j];
+  dNormalize3 (h);
+  dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]);
+  dGeomRaySetLength (ray,10);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test finite length ray that intersects plane
+
+  a[0] = dRandReal()-0.5;
+  a[1] = dRandReal()-0.5;
+  a[2] = dRandReal()-0.5;
+  for (j=0; j<3; j++) b[j] = a[0]*p[j] + a[1]*q[j] + (a[2]+d)*n[j];
+  g[0] = dRandReal()-0.5;
+  g[1] = dRandReal()-0.5;
+  g[2] = dRandReal()-0.5;
+  for (j=0; j<3; j++) h[j] = g[0]*p[j] + g[1]*q[j] + g[2]*n[j];
+  dNormalize3 (h);
+  dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]);
+  dGeomRaySetLength (ray,10);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom))) {
+    // test that contact is on plane surface
+    if (dFabs (dDOT(contact.pos,n) - d) > tol) FAILED();
+    // also check normal signs
+    if (dDOT (h,contact.normal) > 0) FAILED();
+    // also check contact point depth
+    if (dFabs (dGeomPlanePointDepth
+	       (plane,contact.pos[0],contact.pos[1],contact.pos[2])) > tol)
+      FAILED();
+
+    draw_all_objects (space);
+  }
+
+  // ********** test ray that just misses
+
+  for (j=0; j<3; j++) b[j] = (1+d)*n[j];
+  for (j=0; j<3; j++) h[j] = -n[j];
+  dGeomRaySet (ray,b[0],b[1],b[2],h[0],h[1],h[2]);
+  dGeomRaySetLength (ray,0.99);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 0) FAILED();
+
+  // ********** test ray that just hits
+
+  dGeomRaySetLength (ray,1.01);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+
+  // ********** test polarity with typical ground plane
+
+  dGeomPlaneSetParams (plane,0,0,1,0);
+  for (j=0; j<3; j++) a[j] = 0.1;
+  for (j=0; j<3; j++) b[j] = 0;
+  a[2] = 1;
+  b[2] = -1;
+  dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]);
+  dGeomRaySetLength (ray,2);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+  if (dFabs (contact.depth - 1) > tol) FAILED();
+  a[2] = -1;
+  b[2] = 1;
+  dGeomRaySet (ray,a[0],a[1],a[2],b[0],b[1],b[2]);
+  if (dCollide (ray,plane,1,&contact,sizeof(dContactGeom)) != 1) FAILED();
+  if (dFabs (contact.depth - 1) > tol) FAILED();
+
+  PASSED();
+}
+
+//****************************************************************************
+// a really inefficient, but hopefully correct implementation of
+// dBoxTouchesBox(), that does 144 edge-face tests.
+
+// return 1 if edge v1 -> v2 hits the rectangle described by p1,p2,p3
+
+static int edgeIntersectsRect (dVector3 v1, dVector3 v2,
+			       dVector3 p1, dVector3 p2, dVector3 p3)
+{
+  int k;
+  dVector3 u1,u2,n,tmp;
+  for (k=0; k<3; k++) u1[k] = p3[k]-p1[k];
+  for (k=0; k<3; k++) u2[k] = p2[k]-p1[k];
+  dReal d1 = dSqrt(dDOT(u1,u1));
+  dReal d2 = dSqrt(dDOT(u2,u2));
+  dNormalize3 (u1);
+  dNormalize3 (u2);
+  if (dFabs(dDOT(u1,u2)) > 1e-6) dDebug (0,"bad u1/u2");
+  dCROSS (n,=,u1,u2);
+  for (k=0; k<3; k++) tmp[k] = v2[k]-v1[k];
+  dReal d = -dDOT(n,p1);
+  if (dFabs(dDOT(n,p1)+d) > 1e-8) dDebug (0,"bad n wrt p1");
+  if (dFabs(dDOT(n,p2)+d) > 1e-8) dDebug (0,"bad n wrt p2");
+  if (dFabs(dDOT(n,p3)+d) > 1e-8) dDebug (0,"bad n wrt p3");
+  dReal alpha = -(d+dDOT(n,v1))/dDOT(n,tmp);
+  for (k=0; k<3; k++) tmp[k] = v1[k]+alpha*(v2[k]-v1[k]);
+  if (dFabs(dDOT(n,tmp)+d) > 1e-6) dDebug (0,"bad tmp");
+  if (alpha < 0) return 0;
+  if (alpha > 1) return 0;
+  for (k=0; k<3; k++) tmp[k] -= p1[k];
+  dReal a1 = dDOT(u1,tmp);
+  dReal a2 = dDOT(u2,tmp);
+  if (a1<0 || a2<0 || a1>d1 || a2>d2) return 0;
+  return 1;
+}
+
+
+// return 1 if box 1 is completely inside box 2
+
+static int box1inside2 (const dVector3 p1, const dMatrix3 R1,
+			const dVector3 side1, const dVector3 p2,
+			const dMatrix3 R2, const dVector3 side2)
+{
+  for (int i=-1; i<=1; i+=2) {
+    for (int j=-1; j<=1; j+=2) {
+      for (int k=-1; k<=1; k+=2) {
+	dVector3 v,vv;
+	v[0] = i*0.5*side1[0];
+	v[1] = j*0.5*side1[1];
+	v[2] = k*0.5*side1[2];
+	dMULTIPLY0_331 (vv,R1,v);
+	vv[0] += p1[0] - p2[0];
+	vv[1] += p1[1] - p2[1];
+	vv[2] += p1[2] - p2[2];
+	for (int axis=0; axis < 3; axis++) {
+	  dReal z = dDOT14(vv,R2+axis);
+	  if (z < (-side2[axis]*0.5) || z > (side2[axis]*0.5)) return 0;
+	}
+      }
+    }
+  }
+  return 1;
+}
+
+
+// test if any edge from box 1 hits a face from box 2
+
+static int testBoxesTouch2 (const dVector3 p1, const dMatrix3 R1,
+			    const dVector3 side1, const dVector3 p2,
+			    const dMatrix3 R2, const dVector3 side2)
+{
+  int j,k,j1,j2;
+
+  // for 6 faces from box 2
+  for (int fd=0; fd<3; fd++) {		// direction for face
+
+    for (int fo=0; fo<2; fo++) {	// offset of face
+      // get four points on the face. first get 2 indexes that are not fd
+      int k1=0,k2=0;
+      if (fd==0) { k1 = 1; k2 = 2; }
+      if (fd==1) { k1 = 0; k2 = 2; }
+      if (fd==2) { k1 = 0; k2 = 1; }
+      dVector3 fp[4],tmp;
+      k=0;
+      for (j1=-1; j1<=1; j1+=2) {
+	for (j2=-1; j2<=1; j2+=2) {
+	  fp[k][k1] = j1;
+	  fp[k][k2] = j2;
+	  fp[k][fd] = fo*2-1;
+	  k++;
+	}
+      }
+      for (j=0; j<4; j++) {
+	for (k=0; k<3; k++) fp[j][k] *= 0.5*side2[k];
+	dMULTIPLY0_331 (tmp,R2,fp[j]);
+	for (k=0; k<3; k++) fp[j][k] = tmp[k] + p2[k];
+      }
+
+      // for 8 vertices
+      dReal v1[3];
+      for (v1[0]=-1; v1[0] <= 1; v1[0] += 2) {
+	for (v1[1]=-1; v1[1] <= 1; v1[1] += 2) {
+	  for (v1[2]=-1; v1[2] <= 1; v1[2] += 2) {
+	    // for all possible +ve leading edges from those vertices
+	    for (int ei=0; ei < 3; ei ++) {
+	      if (v1[ei] < 0) {
+		// get vertex1 -> vertex2 = an edge from box 1
+		dVector3 vv1,vv2;
+		for (k=0; k<3; k++) vv1[k] = v1[k] * 0.5*side1[k];
+		for (k=0; k<3; k++) vv2[k] = (v1[k] + (k==ei)*2)*0.5*side1[k];
+		dVector3 vertex1,vertex2;
+		dMULTIPLY0_331 (vertex1,R1,vv1);
+		dMULTIPLY0_331 (vertex2,R1,vv2);
+		for (k=0; k<3; k++) vertex1[k] += p1[k];
+		for (k=0; k<3; k++) vertex2[k] += p1[k];
+
+		// see if vertex1 -> vertex2 interesects face
+		if (edgeIntersectsRect (vertex1,vertex2,fp[0],fp[1],fp[2]))
+		  return 1;
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (box1inside2 (p1,R1,side1,p2,R2,side2)) return 1;
+  if (box1inside2 (p2,R2,side2,p1,R1,side1)) return 1;
+
+  return 0;
+}
+
+//****************************************************************************
+// dBoxTouchesBox() test
+
+int test_dBoxTouchesBox()
+{
+  int k,bt1,bt2;
+  dVector3 p1,p2,side1,side2;
+  dMatrix3 R1,R2;
+
+  dSimpleSpace space(0);
+  dGeomID box1 = dCreateBox (0,1,1,1);
+  dSpaceAdd (space,box1);
+  dGeomID box2 = dCreateBox (0,1,1,1);
+  dSpaceAdd (space,box2);
+
+  dMakeRandomVector (p1,3,0.5);
+  dMakeRandomVector (p2,3,0.5);
+  for (k=0; k<3; k++) side1[k] = dRandReal() + 0.01;
+  for (k=0; k<3; k++) side2[k] = dRandReal() + 0.01;
+  dRFromAxisAndAngle (R1,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+		      dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+  dRFromAxisAndAngle (R2,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+		      dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+
+  dGeomBoxSetLengths (box1,side1[0],side1[1],side1[2]);
+  dGeomBoxSetLengths (box2,side2[0],side2[1],side2[2]);
+  dGeomSetPosition (box1,p1[0],p1[1],p1[2]);
+  dGeomSetRotation (box1,R1);
+  dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
+  dGeomSetRotation (box2,R2);
+  draw_all_objects (space);
+
+  int t1 = testBoxesTouch2 (p1,R1,side1,p2,R2,side2);
+  int t2 = testBoxesTouch2 (p2,R2,side2,p1,R1,side1);
+  bt1 = t1 || t2;
+  bt2 = dBoxTouchesBox (p1,R1,side1,p2,R2,side2);
+
+  if (bt1 != bt2) FAILED();
+
+  /*
+    // some more debugging info if necessary
+    if (bt1 && bt2) printf ("agree - boxes touch\n");
+    if (!bt1 && !bt2) printf ("agree - boxes don't touch\n");
+    if (bt1 && !bt2) printf ("disagree - boxes touch but dBoxTouchesBox "
+			     "says no\n");
+    if (!bt1 && bt2) printf ("disagree - boxes don't touch but dBoxTouchesBox "
+			     "says yes\n");
+  */
+
+  PASSED();
+}
+
+//****************************************************************************
+// test box-box collision
+
+int test_dBoxBox()
+{
+  int k,bt;
+  dVector3 p1,p2,side1,side2,normal,normal2;
+  dMatrix3 R1,R2;
+  dReal depth,depth2;
+  int code;
+  dContactGeom contact[48];
+
+  dSimpleSpace space(0);
+  dGeomID box1 = dCreateBox (0,1,1,1);
+  dSpaceAdd (space,box1);
+  dGeomID box2 = dCreateBox (0,1,1,1);
+  dSpaceAdd (space,box2);
+
+  dMakeRandomVector (p1,3,0.5);
+  dMakeRandomVector (p2,3,0.5);
+  for (k=0; k<3; k++) side1[k] = dRandReal() + 0.01;
+  for (k=0; k<3; k++) side2[k] = dRandReal() + 0.01;
+
+  dRFromAxisAndAngle (R1,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+		      dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+  dRFromAxisAndAngle (R2,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+		      dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+
+  // dRSetIdentity (R1);	// we can also try this
+  // dRSetIdentity (R2);
+
+  dGeomBoxSetLengths (box1,side1[0],side1[1],side1[2]);
+  dGeomBoxSetLengths (box2,side2[0],side2[1],side2[2]);
+  dGeomSetPosition (box1,p1[0],p1[1],p1[2]);
+  dGeomSetRotation (box1,R1);
+  dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
+  dGeomSetRotation (box2,R2);
+
+  code = 0;
+  depth = 0;
+  bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal,&depth,&code,8,contact,
+		sizeof(dContactGeom));
+  if (bt==1) {
+    p2[0] += normal[0] * 0.96 * depth;
+    p2[1] += normal[1] * 0.96 * depth;
+    p2[2] += normal[2] * 0.96 * depth;
+    bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal2,&depth2,&code,8,contact,
+		  sizeof(dContactGeom));
+
+    /*
+    dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
+    draw_all_objects (space);
+    */
+
+    if (bt != 1) {
+      FAILED();
+      dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
+      draw_all_objects (space);
+    }
+
+    p2[0] += normal[0] * 0.08 * depth;
+    p2[1] += normal[1] * 0.08 * depth;
+    p2[2] += normal[2] * 0.08 * depth;
+    bt = dBoxBox (p1,R1,side1,p2,R2,side2,normal2,&depth2,&code,8,contact,
+		  sizeof(dContactGeom));
+    if (bt != 0) FAILED();
+
+    // dGeomSetPosition (box2,p2[0],p2[1],p2[2]);
+    // draw_all_objects (space);
+  }
+
+  // printf ("code=%2d  depth=%.4f  ",code,depth);
+
+  PASSED();
+}
+
+//****************************************************************************
+// graphics
+
+int space_pressed = 0;
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.4807,-1.8023,2.7600};
+  static float hpr[3] = {141.5000,-18.5000,0.0000};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  if (cmd == ' ') space_pressed = 1;
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  do {
+    draw_all_objects_called = 0;
+    unsigned long seed = dRandGetSeed();
+    testslot[graphical_test].test_fn();
+    if (draw_all_objects_called) {
+      if (space_pressed) space_pressed = 0; else dRandSetSeed (seed);
+    }
+  }
+  while (!draw_all_objects_called);
+}
+
+//****************************************************************************
+// do all the tests
+
+void do_tests (int argc, char **argv)
+{
+  int i,j;
+
+  // process command line arguments
+  if (argc >= 2) {
+    graphical_test = atoi (argv[1]);
+  }
+
+  if (graphical_test) {
+    // do one test gaphically and interactively
+
+    if (graphical_test < 1 || graphical_test >= MAX_TESTS ||
+	!testslot[graphical_test].name) {
+      dError (0,"invalid test number");
+    }
+
+    printf ("performing test: %s\n",testslot[graphical_test].name);
+
+    // setup pointers to drawstuff callback functions
+    dsFunctions fn;
+    fn.version = DS_VERSION;
+    fn.start = &start;
+    fn.step = &simLoop;
+    fn.command = &command;
+    fn.stop = 0;
+    fn.path_to_textures = "../../drawstuff/textures";
+
+    dsSetSphereQuality (3);
+    dsSetCapsuleQuality (8);
+    dsSimulationLoop (argc,argv,1280,900,&fn);
+  }
+  else {
+    // do all tests noninteractively
+
+    for (i=0; i<MAX_TESTS; i++) testslot[i].number = i;
+
+    // first put the active tests into a separate array
+    int n=0;
+    for (i=0; i<MAX_TESTS; i++) if (testslot[i].name) n++;
+    TestSlot **ts = (TestSlot**) alloca (n * sizeof(TestSlot*));
+    j = 0;
+    for (i=0; i<MAX_TESTS; i++) if (testslot[i].name) ts[j++] = testslot+i;
+    if (j != n) dDebug (0,"internal");
+
+    // do two test batches. the first test batch has far fewer reps and will
+    // catch problems quickly. if all tests in the first batch passes, the
+    // second batch is run.
+
+    for (i=0; i<n; i++) ts[i]->failcount = 0;
+    int total_reps=0;
+    for (int batch=0; batch<2; batch++) {
+      int reps = (batch==0) ? TEST_REPS1 : TEST_REPS2;
+      total_reps += reps;
+      printf ("testing batch %d (%d reps)...\n",batch+1,reps);
+
+      // run tests
+      for (j=0; j<reps; j++) {
+	for (i=0; i<n; i++) {
+	  current_test = ts[i]->number;
+	  if (ts[i]->test_fn() != 1) ts[i]->failcount++;
+	}
+      }
+
+      // check for failures
+      int total_fail_count=0;
+      for (i=0; i<n; i++) total_fail_count += ts[i]->failcount;
+      if (total_fail_count) break;
+    }
+
+    // print results
+    for (i=0; i<n; i++) {
+      printf ("%3d: %-30s: ",ts[i]->number,ts[i]->name);
+      if (ts[i]->failcount) {
+	printf ("FAILED (%.2f%%) at line %d\n",
+		double(ts[i]->failcount)/double(total_reps)*100.0,
+		ts[i]->last_failed_line);
+      }
+      else {
+	printf ("ok\n");
+      }
+    }
+  }
+}
+
+//****************************************************************************
+
+int main (int argc, char **argv)
+{
+  // setup all tests
+
+  memset (testslot,0,sizeof(testslot));
+  dInitODE();
+
+  MAKE_TEST(1,test_sphere_point_depth);
+  MAKE_TEST(2,test_box_point_depth);
+  MAKE_TEST(3,test_ccylinder_point_depth);
+  MAKE_TEST(4,test_plane_point_depth);
+
+  MAKE_TEST(10,test_ray_and_sphere);
+  MAKE_TEST(11,test_ray_and_box);
+  MAKE_TEST(12,test_ray_and_ccylinder);
+  MAKE_TEST(13,test_ray_and_plane);
+
+  MAKE_TEST(100,test_dBoxTouchesBox);
+  MAKE_TEST(101,test_dBoxBox);
+
+  do_tests (argc,argv);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_convex_cd.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_convex_cd.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_convex_cd.cpp	(revision 216)
@@ -0,0 +1,195 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+//<---- Convex Object
+dReal planes[]= // planes for a cube
+  {
+    1.0f ,0.0f ,0.0f ,0.25f,
+    0.0f ,1.0f ,0.0f ,0.25f,
+    0.0f ,0.0f ,1.0f ,0.25f,
+    -1.0f,0.0f ,0.0f ,0.25f,
+    0.0f ,-1.0f,0.0f ,0.25f,
+    0.0f ,0.0f ,-1.0f,0.25f
+    /*
+    1.0f ,0.0f ,0.0f ,2.0f,
+    0.0f ,1.0f ,0.0f ,1.0f,
+    0.0f ,0.0f ,1.0f ,1.0f,
+    0.0f ,0.0f ,-1.0f,1.0f,
+    0.0f ,-1.0f,0.0f ,1.0f,
+    -1.0f,0.0f ,0.0f ,0.0f
+    */
+  };
+const unsigned int planecount=6;
+
+dReal points[]= // points for a cube
+  {
+    0.25f,0.25f,0.25f,  //  point 0
+    -0.25f,0.25f,0.25f, //  point 1
+
+    0.25f,-0.25f,0.25f, //  point 2
+    -0.25f,-0.25f,0.25f,//  point 3
+
+    0.25f,0.25f,-0.25f, //  point 4
+    -0.25f,0.25f,-0.25f,//  point 5
+
+    0.25f,-0.25f,-0.25f,//  point 6
+    -0.25f,-0.25f,-0.25f,// point 7 
+  };
+const unsigned int pointcount=8;
+unsigned int polygons[] = //Polygons for a cube (6 squares)
+  {
+    4,0,2,6,4, // positive X
+    4,1,0,4,5, // positive Y
+    4,0,1,3,2, // positive Z
+    4,3,1,5,7, // negative X 
+    4,2,3,7,6, // negative Y
+    4,5,4,6,7, // negative Z
+  };
+//----> Convex Object
+
+#ifdef dDOUBLE
+#define dsDrawConvex dsDrawConvexD
+#define dsDrawBox dsDrawBoxD
+#endif
+
+dGeomID geoms[2];
+dSpaceID space;
+dWorldID world;
+dJointGroupID contactgroup;
+
+void start()
+{
+  // adjust the starting viewpoint a bit
+  float xyz[3],hpr[3];
+  dsGetViewpoint (xyz,hpr);
+  hpr[0] += 7;
+  dsSetViewpoint (xyz,hpr);
+  geoms[0]=dCreateConvex (space,
+			  planes,
+			  planecount,
+			  points,
+			  pointcount,
+			  polygons);
+  dGeomSetPosition (geoms[0],0,0,0.25);
+  geoms[1]=dCreateConvex (space,
+			  planes,
+			  planecount,
+			  points,
+			  pointcount,
+			  polygons);
+  dGeomSetPosition (geoms[1],0.25,0.25,0.70);
+  
+}
+
+int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip);
+void simLoop (int pause)
+{
+  static bool DumpInfo=true;
+  const dReal ss[3] = {0.02,0.02,0.02};
+  dContactGeom contacts[8];
+  int contactcount = dCollideConvexConvex(geoms[0],geoms[1],8,contacts,sizeof(dContactGeom));
+  //fprintf(stdout,"Contact Count %d\n",contactcount);
+  const dReal* pos;
+  const dReal* R;
+  dsSetTexture (DS_WOOD);
+  pos = dGeomGetPosition (geoms[0]);
+  R = dGeomGetRotation (geoms[0]);
+  dsSetColor (0.6f,0.6f,1);
+  dsDrawConvex(pos,R,planes,
+	       planecount,
+	       points,
+	       pointcount,
+	       polygons);
+  pos = dGeomGetPosition (geoms[1]);
+  R = dGeomGetRotation (geoms[1]);
+  dsSetColor (0.4f,1,1);
+  dsDrawConvex(pos,R,planes,
+	       planecount,
+	       points,
+	       pointcount,
+	       polygons);
+  /*if (show_contacts) */
+  dMatrix3 RI;
+  dRSetIdentity (RI);
+  dsSetColor (1.0f,0,0);
+  for(int i=0;i<contactcount;++i)
+    {
+      if(DumpInfo)
+	{
+	  //DumpInfo=false;
+	  fprintf(stdout,"Contact %d Normal %f,%f,%f Depth %f\n",
+		  i,
+		  contacts[i].normal[0],
+		  contacts[i].normal[1],
+		  contacts[i].normal[2],
+		  contacts[i].depth);
+	}
+      dsDrawBox (contacts[i].pos,RI,ss);
+    }
+  if(DumpInfo)
+    DumpInfo=false;
+
+}
+
+
+void command (int cmd)
+{
+  dsPrint ("received command %d (`%c')\n",cmd,cmd);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";	// uses default
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,400,400,&fn);
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_crash.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_crash.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_crash.cpp	(revision 216)
@@ -0,0 +1,635 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// This is a demo of the QuickStep and StepFast methods,
+// originally by David Whittaker.
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// select the method you want to test here (only uncomment *one* line)
+#define QUICKSTEP 1
+//#define STEPFAST 1
+
+// some constants
+
+#define LENGTH 3.5		// chassis length
+#define WIDTH 2.5		// chassis width
+#define HEIGHT 1.0		// chassis height
+#define RADIUS 0.5		// wheel radius
+#define STARTZ 1.0		// starting height of chassis
+#define CMASS 1			// chassis mass
+#define WMASS 1			// wheel mass
+#define COMOFFSET -5		// center of mass offset
+#define WALLMASS 1		// wall box mass
+#define BALLMASS 1		// ball mass
+#define FMAX 25			// car engine fmax
+#define ROWS 1			// rows of cars
+#define COLS 1			// columns of cars
+#define ITERS 20		// number of iterations
+#define WBOXSIZE 1.0		// size of wall boxes
+#define WALLWIDTH 12		// width of wall
+#define WALLHEIGHT 10		// height of wall
+#define DISABLE_THRESHOLD 0.008	// maximum velocity (squared) a body can have and be disabled
+#define DISABLE_STEPS 10	// number of steps a box has to have been disable-able before it will be disabled
+#define CANNON_X -10		// x position of cannon
+#define CANNON_Y 5		// y position of cannon
+#define CANNON_BALL_MASS 10	// mass of the cannon ball
+#define CANNON_BALL_RADIUS 0.5
+
+//#define BOX
+#define CARS
+#define WALL
+//#define BALLS
+//#define BALLSTACK
+//#define ONEBALL
+//#define CENTIPEDE
+#define CANNON
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+static dBodyID body[10000];
+static int bodies;
+static dJointID joint[100000];
+static int joints;
+static dJointGroupID contactgroup;
+static dGeomID ground;
+static dGeomID box[10000];
+static int boxes;
+static dGeomID sphere[10000];
+static int spheres;
+static dGeomID wall_boxes[10000];
+static dBodyID wall_bodies[10000];
+static dGeomID cannon_ball_geom;
+static dBodyID cannon_ball_body;
+static int wb_stepsdis[10000];
+static int wb;
+static bool doFast;
+static dBodyID b;
+static dMass m;
+
+
+// things that the user controls
+
+static dReal turn = 0, speed = 0;	// user commands
+static dReal cannon_angle=0,cannon_elevation=-1.2;
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+	int i,n;
+	
+	dBodyID b1 = dGeomGetBody(o1);
+	dBodyID b2 = dGeomGetBody(o2);
+	if (b1 && b2 && dAreConnected(b1, b2))
+		return;
+	
+	const int N = 4;
+	dContact contact[N];
+	n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
+	if (n > 0) {
+		for (i=0; i<n; i++) {
+			contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1;
+			if (dGeomGetClass(o1) == dSphereClass || dGeomGetClass(o2) == dSphereClass)
+				contact[i].surface.mu = 20;
+			else
+				contact[i].surface.mu = 0.5;
+			contact[i].surface.slip1 = 0.0;
+			contact[i].surface.slip2 = 0.0;
+			contact[i].surface.soft_erp = 0.8;
+			contact[i].surface.soft_cfm = 0.01;
+			dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+			dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
+		}
+	}
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+	static float xyz[3] = {3.8548f,9.0843f,7.5900f};
+	static float hpr[3] = {-145.5f,-22.5f,0.25f};
+	dsSetViewpoint (xyz,hpr);
+	printf ("Press:\t'a' to increase speed.\n"
+			"\t'z' to decrease speed.\n"
+			"\t',' to steer left.\n"
+			"\t'.' to steer right.\n"
+			"\t' ' to reset speed and steering.\n"
+			"\t'[' to turn the cannon left.\n"
+			"\t']' to turn the cannon right.\n"
+			"\t'1' to raise the cannon.\n"
+			"\t'2' to lower the cannon.\n"
+			"\t'x' to shoot from the cannon.\n"
+			"\t'f' to toggle fast step mode.\n"
+			"\t'+' to increase AutoEnableDepth.\n"
+			"\t'-' to decrease AutoEnableDepth.\n"
+			"\t'r' to reset simulation.\n");
+}
+
+
+void makeCar(dReal x, dReal y, int &bodyI, int &jointI, int &boxI, int &sphereI)
+{
+	int i;
+	dMass m;
+	
+	// chassis body
+	body[bodyI] = dBodyCreate (world);
+	dBodySetPosition (body[bodyI],x,y,STARTZ);
+	dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
+	dMassAdjust (&m,CMASS/2.0);
+	dBodySetMass (body[bodyI],&m);
+	box[boxI] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
+	dGeomSetBody (box[boxI],body[bodyI]);
+	
+	// wheel bodies
+	for (i=1; i<=4; i++) {
+		body[bodyI+i] = dBodyCreate (world);
+		dQuaternion q;
+		dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
+		dBodySetQuaternion (body[bodyI+i],q);
+		dMassSetSphere (&m,1,RADIUS);
+		dMassAdjust (&m,WMASS);
+		dBodySetMass (body[bodyI+i],&m);
+		sphere[sphereI+i-1] = dCreateSphere (space,RADIUS);
+		dGeomSetBody (sphere[sphereI+i-1],body[bodyI+i]);
+	}
+	dBodySetPosition (body[bodyI+1],x+0.4*LENGTH-0.5*RADIUS,y+WIDTH*0.5,STARTZ-HEIGHT*0.5);
+	dBodySetPosition (body[bodyI+2],x+0.4*LENGTH-0.5*RADIUS,y-WIDTH*0.5,STARTZ-HEIGHT*0.5);
+	dBodySetPosition (body[bodyI+3],x-0.4*LENGTH+0.5*RADIUS,y+WIDTH*0.5,STARTZ-HEIGHT*0.5);
+	dBodySetPosition (body[bodyI+4],x-0.4*LENGTH+0.5*RADIUS,y-WIDTH*0.5,STARTZ-HEIGHT*0.5);
+	
+	// front and back wheel hinges
+	for (i=0; i<4; i++) {
+		joint[jointI+i] = dJointCreateHinge2 (world,0);
+		dJointAttach (joint[jointI+i],body[bodyI],body[bodyI+i+1]);
+		const dReal *a = dBodyGetPosition (body[bodyI+i+1]);
+		dJointSetHinge2Anchor (joint[jointI+i],a[0],a[1],a[2]);
+		dJointSetHinge2Axis1 (joint[jointI+i],0,0,(i<2 ? 1 : -1));
+		dJointSetHinge2Axis2 (joint[jointI+i],0,1,0);
+		dJointSetHinge2Param (joint[jointI+i],dParamSuspensionERP,0.8);
+		dJointSetHinge2Param (joint[jointI+i],dParamSuspensionCFM,1e-5);
+		dJointSetHinge2Param (joint[jointI+i],dParamVel2,0);
+		dJointSetHinge2Param (joint[jointI+i],dParamFMax2,FMAX);
+	}
+	
+	//center of mass offset body. (hang another copy of the body COMOFFSET units below it by a fixed joint)
+	dBodyID b = dBodyCreate (world);
+	dBodySetPosition (b,x,y,STARTZ+COMOFFSET);
+	dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
+	dMassAdjust (&m,CMASS/2.0);
+	dBodySetMass (b,&m);
+	dJointID j = dJointCreateFixed(world, 0);
+	dJointAttach(j, body[bodyI], b);
+	dJointSetFixed(j);
+	//box[boxI+1] = dCreateBox(space,LENGTH,WIDTH,HEIGHT);
+	//dGeomSetBody (box[boxI+1],b);
+	
+	bodyI	+= 5;
+	jointI	+= 4;
+	boxI	+= 1;
+	sphereI	+= 4;
+}
+
+
+void resetSimulation()
+{
+	int i;
+	i = 0;
+	// destroy world if it exists
+	if (bodies)
+	{
+		dJointGroupDestroy (contactgroup);
+		dSpaceDestroy (space);
+		dWorldDestroy (world);
+	}
+	
+	for (i = 0; i < 1000; i++)
+		wb_stepsdis[i] = 0;
+
+	// recreate world
+	
+	world = dWorldCreate();
+	space = dHashSpaceCreate (0);
+	contactgroup = dJointGroupCreate (0);
+	dWorldSetGravity (world,0,0,-1.5);
+	dWorldSetCFM (world, 1e-5);
+	dWorldSetERP (world, 0.8);
+	dWorldSetQuickStepNumIterations (world,ITERS);
+	ground = dCreatePlane (space,0,0,1,0);
+	
+	bodies = 0;
+	joints = 0;
+	boxes = 0;
+	spheres = 0;
+	wb = 0;
+	
+#ifdef CARS
+	for (dReal x = 0.0; x < COLS*(LENGTH+RADIUS); x += LENGTH+RADIUS)
+		for (dReal y = -((ROWS-1)*(WIDTH/2+RADIUS)); y <= ((ROWS-1)*(WIDTH/2+RADIUS)); y += WIDTH+RADIUS*2)
+			makeCar(x, y, bodies, joints, boxes, spheres);
+#endif
+#ifdef WALL
+	bool offset = false;
+	for (dReal z = WBOXSIZE/2.0; z <= WALLHEIGHT; z+=WBOXSIZE)
+	{
+		offset = !offset;
+		for (dReal y = (-WALLWIDTH+z)/2; y <= (WALLWIDTH-z)/2; y+=WBOXSIZE)
+		{
+			wall_bodies[wb] = dBodyCreate (world);
+			dBodySetPosition (wall_bodies[wb],-20,y,z);
+			dMassSetBox (&m,1,WBOXSIZE,WBOXSIZE,WBOXSIZE);
+			dMassAdjust (&m, WALLMASS);
+			dBodySetMass (wall_bodies[wb],&m);
+			wall_boxes[wb] = dCreateBox (space,WBOXSIZE,WBOXSIZE,WBOXSIZE);
+			dGeomSetBody (wall_boxes[wb],wall_bodies[wb]);
+			//dBodyDisable(wall_bodies[wb++]);
+			wb++;
+		}
+	}
+	dMessage(0,"wall boxes: %i", wb);
+#endif
+#ifdef BALLS
+	for (dReal x = -7; x <= -4; x+=1)
+		for (dReal y = -1.5; y <= 1.5; y+=1)
+			for (dReal z = 1; z <= 4; z+=1)
+			{
+				b = dBodyCreate (world);
+				dBodySetPosition (b,x*RADIUS*2,y*RADIUS*2,z*RADIUS*2);
+				dMassSetSphere (&m,1,RADIUS);
+				dMassAdjust (&m, BALLMASS);
+				dBodySetMass (b,&m);
+				sphere[spheres] = dCreateSphere (space,RADIUS);
+				dGeomSetBody (sphere[spheres++],b);
+			}
+#endif
+#ifdef ONEBALL
+	b = dBodyCreate (world);
+	dBodySetPosition (b,0,0,2);
+	dMassSetSphere (&m,1,RADIUS);
+	dMassAdjust (&m, 1);
+	dBodySetMass (b,&m);
+	sphere[spheres] = dCreateSphere (space,RADIUS);
+	dGeomSetBody (sphere[spheres++],b);
+#endif
+#ifdef BALLSTACK
+	for (dReal z = 1; z <= 6; z+=1)
+	{
+		b = dBodyCreate (world);
+		dBodySetPosition (b,0,0,z*RADIUS*2);
+		dMassSetSphere (&m,1,RADIUS);
+		dMassAdjust (&m, 0.1);
+		dBodySetMass (b,&m);
+		sphere[spheres] = dCreateSphere (space,RADIUS);
+		dGeomSetBody (sphere[spheres++],b);
+	}
+#endif
+#ifdef CENTIPEDE
+	dBodyID lastb = 0;
+	for (dReal y = 0; y < 10*LENGTH; y+=LENGTH+0.1)
+	{
+		// chassis body
+		
+		b = body[bodies] = dBodyCreate (world);
+		dBodySetPosition (body[bodies],-15,y,STARTZ);
+		dMassSetBox (&m,1,WIDTH,LENGTH,HEIGHT);
+		dMassAdjust (&m,CMASS);
+		dBodySetMass (body[bodies],&m);
+		box[boxes] = dCreateBox (space,WIDTH,LENGTH,HEIGHT);
+		dGeomSetBody (box[boxes++],body[bodies++]);
+		
+		for (dReal x = -17; x > -20; x-=RADIUS*2)
+		{
+			body[bodies] = dBodyCreate (world);
+			dBodySetPosition(body[bodies], x, y, STARTZ);
+			dMassSetSphere(&m, 1, RADIUS);
+			dMassAdjust(&m, WMASS);
+			dBodySetMass(body[bodies], &m);
+			sphere[spheres] = dCreateSphere (space, RADIUS);
+			dGeomSetBody (sphere[spheres++], body[bodies]);
+			
+			joint[joints] = dJointCreateHinge2 (world,0);
+			if (x == -17)
+				dJointAttach (joint[joints],b,body[bodies]);
+			else
+				dJointAttach (joint[joints],body[bodies-2],body[bodies]);
+			const dReal *a = dBodyGetPosition (body[bodies++]);
+			dJointSetHinge2Anchor (joint[joints],a[0],a[1],a[2]);
+			dJointSetHinge2Axis1 (joint[joints],0,0,1);
+			dJointSetHinge2Axis2 (joint[joints],1,0,0);
+			dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0);
+			dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5);
+			dJointSetHinge2Param (joint[joints],dParamLoStop,0);
+			dJointSetHinge2Param (joint[joints],dParamHiStop,0);
+			dJointSetHinge2Param (joint[joints],dParamVel2,-10.0);
+			dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX);
+
+			body[bodies] = dBodyCreate (world);
+			dBodySetPosition(body[bodies], -30 - x, y, STARTZ);
+			dMassSetSphere(&m, 1, RADIUS);
+			dMassAdjust(&m, WMASS);
+			dBodySetMass(body[bodies], &m);
+			sphere[spheres] = dCreateSphere (space, RADIUS);
+			dGeomSetBody (sphere[spheres++], body[bodies]);
+			
+			joint[joints] = dJointCreateHinge2 (world,0);
+			if (x == -17)
+				dJointAttach (joint[joints],b,body[bodies]);
+			else
+				dJointAttach (joint[joints],body[bodies-2],body[bodies]);
+			const dReal *b = dBodyGetPosition (body[bodies++]);
+			dJointSetHinge2Anchor (joint[joints],b[0],b[1],b[2]);
+			dJointSetHinge2Axis1 (joint[joints],0,0,1);
+			dJointSetHinge2Axis2 (joint[joints],1,0,0);
+			dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0);
+			dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5);
+			dJointSetHinge2Param (joint[joints],dParamLoStop,0);
+			dJointSetHinge2Param (joint[joints],dParamHiStop,0);
+			dJointSetHinge2Param (joint[joints],dParamVel2,10.0);
+			dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX);
+		}
+		if (lastb)
+		{
+			dJointID j = dJointCreateFixed(world,0);
+			dJointAttach (j, b, lastb);
+			dJointSetFixed(j);
+		}
+		lastb = b;
+	}
+#endif
+#ifdef BOX
+	body[bodies] = dBodyCreate (world);
+	dBodySetPosition (body[bodies],0,0,HEIGHT/2);
+	dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
+	dMassAdjust (&m, 1);
+	dBodySetMass (body[bodies],&m);
+	box[boxes] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
+	dGeomSetBody (box[boxes++],body[bodies++]);	
+#endif
+#ifdef CANNON
+	cannon_ball_body = dBodyCreate (world);
+	cannon_ball_geom = dCreateSphere (space,CANNON_BALL_RADIUS);
+	dMassSetSphereTotal (&m,CANNON_BALL_MASS,CANNON_BALL_RADIUS);
+	dBodySetMass (cannon_ball_body,&m);
+	dGeomSetBody (cannon_ball_geom,cannon_ball_body);
+	dBodySetPosition (cannon_ball_body,CANNON_X,CANNON_Y,CANNON_BALL_RADIUS);
+#endif
+}
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+	switch (cmd) {
+	case 'a': case 'A':
+		speed += 0.3;
+		break;
+	case 'z': case 'Z':
+		speed -= 0.3;
+		break;
+	case ',':
+		turn += 0.1;
+		if (turn > 0.3)
+			turn = 0.3;
+		break;
+	case '.':
+		turn -= 0.1;
+		if (turn < -0.3)
+			turn = -0.3;
+		break;
+	case ' ':
+		speed = 0;
+		turn = 0;
+		break;
+	case 'f': case 'F':
+		doFast = !doFast;
+		break;
+	case '+':
+		dWorldSetAutoEnableDepthSF1 (world, dWorldGetAutoEnableDepthSF1 (world) + 1);
+		break;
+	case '-':
+		dWorldSetAutoEnableDepthSF1 (world, dWorldGetAutoEnableDepthSF1 (world) - 1);
+		break;
+	case 'r': case 'R':
+		resetSimulation();
+		break;
+	case '[':
+		cannon_angle += 0.1;
+		break;
+	case ']':
+		cannon_angle -= 0.1;
+		break;
+	case '1':
+		cannon_elevation += 0.1;
+		break;
+	case '2':
+		cannon_elevation -= 0.1;
+		break;
+	case 'x': case 'X': {
+		dMatrix3 R2,R3,R4;
+		dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
+		dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
+		dMultiply0 (R4,R2,R3,3,3,3);
+		dReal cpos[3] = {CANNON_X,CANNON_Y,1};
+		for (int i=0; i<3; i++) cpos[i] += 3*R4[i*4+2];
+		dBodySetPosition (cannon_ball_body,cpos[0],cpos[1],cpos[2]);
+		dReal force = 10;
+		dBodySetLinearVel (cannon_ball_body,force*R4[2],force*R4[6],force*R4[10]);
+		dBodySetAngularVel (cannon_ball_body,0,0,0);
+		break;
+	}
+	}
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+	int i, j;
+		
+	dsSetTexture (DS_WOOD);
+
+	if (!pause) {
+#ifdef BOX
+		dBodyAddForce(body[bodies-1],lspeed,0,0);
+#endif
+		for (j = 0; j < joints; j++)
+		{
+			dReal curturn = dJointGetHinge2Angle1 (joint[j]);
+			//dMessage (0,"curturn %e, turn %e, vel %e", curturn, turn, (turn-curturn)*1.0);
+			dJointSetHinge2Param(joint[j],dParamVel,(turn-curturn)*1.0);
+			dJointSetHinge2Param(joint[j],dParamFMax,dInfinity);
+			dJointSetHinge2Param(joint[j],dParamVel2,speed);
+			dJointSetHinge2Param(joint[j],dParamFMax2,FMAX);
+			dBodyEnable(dJointGetBody(joint[j],0));
+			dBodyEnable(dJointGetBody(joint[j],1));
+		}		
+		if (doFast)
+		{
+			dSpaceCollide (space,0,&nearCallback);
+#if defined(QUICKSTEP)
+			dWorldQuickStep (world,0.05);
+#elif defined(STEPFAST)
+			dWorldStepFast1 (world,0.05,ITERS);
+#endif
+			dJointGroupEmpty (contactgroup);
+		}
+		else
+		{
+			dSpaceCollide (space,0,&nearCallback);
+			dWorldStep (world,0.05);
+			dJointGroupEmpty (contactgroup);
+		}
+		
+		for (i = 0; i < wb; i++)
+		{
+			b = dGeomGetBody(wall_boxes[i]);
+			if (dBodyIsEnabled(b)) 
+			{
+				bool disable = true;
+				const dReal *lvel = dBodyGetLinearVel(b);
+				dReal lspeed = lvel[0]*lvel[0]+lvel[1]*lvel[1]+lvel[2]*lvel[2];
+				if (lspeed > DISABLE_THRESHOLD)
+					disable = false;
+				const dReal *avel = dBodyGetAngularVel(b);
+				dReal aspeed = avel[0]*avel[0]+avel[1]*avel[1]+avel[2]*avel[2];
+				if (aspeed > DISABLE_THRESHOLD)
+					disable = false;
+				
+				if (disable)
+					wb_stepsdis[i]++;
+				else
+					wb_stepsdis[i] = 0;
+				
+				if (wb_stepsdis[i] > DISABLE_STEPS)
+				{
+					dBodyDisable(b);
+					dsSetColor(0.5,0.5,1);
+				}
+				else
+					dsSetColor(1,1,1);
+
+			}
+			else
+				dsSetColor(0.4,0.4,0.4);
+			dVector3 ss;
+			dGeomBoxGetLengths (wall_boxes[i], ss);
+			dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss);
+		}
+	}
+	else
+	{
+		for (i = 0; i < wb; i++)
+		{
+			b = dGeomGetBody(wall_boxes[i]);
+			if (dBodyIsEnabled(b))
+				dsSetColor(1,1,1);
+			else
+				dsSetColor(0.4,0.4,0.4);
+			dVector3 ss;
+			dGeomBoxGetLengths (wall_boxes[i], ss);
+			dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss);
+		}
+	}
+	
+	dsSetColor (0,1,1);
+	dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
+	for (i = 0; i < boxes; i++)
+		dsDrawBox (dGeomGetPosition(box[i]),dGeomGetRotation(box[i]),sides);
+	dsSetColor (1,1,1);
+	for (i=0; i< spheres; i++) dsDrawSphere (dGeomGetPosition(sphere[i]),
+				   dGeomGetRotation(sphere[i]),RADIUS);
+	
+	// draw the cannon
+	dsSetColor (1,1,0);
+	dMatrix3 R2,R3,R4;
+	dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
+	dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
+	dMultiply0 (R4,R2,R3,3,3,3);
+	dReal cpos[3] = {CANNON_X,CANNON_Y,1};
+	dReal csides[3] = {2,2,2};
+	dsDrawBox (cpos,R2,csides);
+	for (i=0; i<3; i++) cpos[i] += 1.5*R4[i*4+2];
+	dsDrawCylinder (cpos,R4,3,0.5);
+	
+	// draw the cannon ball
+	dsDrawSphere (dBodyGetPosition(cannon_ball_body),dBodyGetRotation(cannon_ball_body),
+		      CANNON_BALL_RADIUS);
+}
+
+int main (int argc, char **argv)
+{
+	doFast = true;
+	
+	// setup pointers to drawstuff callback functions
+	dsFunctions fn;
+	fn.version = DS_VERSION;
+	fn.start = &start;
+	fn.step = &simLoop;
+	fn.command = &command;
+	fn.stop = 0;
+	fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+	
+	dInitODE();
+
+	bodies = 0;
+	joints = 0;
+	boxes = 0;
+	spheres = 0;
+	
+	resetSimulation();
+	
+	// run simulation
+	dsSimulationLoop (argc,argv,352,288,&fn);
+	
+	dJointGroupDestroy (contactgroup);
+	dSpaceDestroy (space);
+	dWorldDestroy (world);
+	dCloseODE();
+	return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_cyl.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_cyl.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_cyl.cpp	(revision 216)
@@ -0,0 +1,318 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// Test for non-capped cylinder, by Bram Stolk
+#include <ode/config.h>
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#include "world_geom3.h" // this is our world mesh
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+#define BOX
+#define CYL
+
+// some constants
+
+#define RADIUS 0.22	// wheel radius
+#define WMASS 0.2	// wheel mass
+#define WHEELW 0.2	// wheel width
+#define BOXSZ 0.4	// box size
+//#define CYL_GEOM_OFFSET // rotate cylinder using geom offset
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+#ifdef BOX
+static dBodyID boxbody;
+static dGeomID boxgeom;
+#endif
+#ifdef CYL
+static dBodyID cylbody;
+static dGeomID cylgeom;
+#endif
+static dJointGroupID contactgroup;
+static dGeomID world_mesh;
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  assert(o1);
+  assert(o2);
+
+  if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
+  {
+    fprintf(stderr,"testing space %p %p\n", o1,o2);
+    // colliding a space with something
+    dSpaceCollide2(o1,o2,data,&nearCallback);
+    // Note we do not want to test intersections within a space,
+    // only between spaces.
+    return;
+  }
+
+//  fprintf(stderr,"testing geoms %p %p\n", o1, o2);
+
+  const int N = 32;
+  dContact contact[N];
+  int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
+  if (n > 0) 
+  {
+    for (int i=0; i<n; i++) 
+    {
+      contact[i].surface.slip1 = 0.7;
+      contact[i].surface.slip2 = 0.7;
+      contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
+      contact[i].surface.mu = 50.0; // was: dInfinity
+      contact[i].surface.soft_erp = 0.96;
+      contact[i].surface.soft_cfm = 0.04;
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c,
+		    dGeomGetBody(contact[i].geom.g1),
+		    dGeomGetBody(contact[i].geom.g2));
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {-8,-9,3};
+  static float hpr[3] = {45.0000f,-27.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+
+static void reset_state(void)
+{
+  float sx=-4, sy=-4, sz=2;
+  dQuaternion q;
+  dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
+#ifdef BOX
+  dBodySetPosition (boxbody, sx, sy+1, sz);
+  dBodySetLinearVel (boxbody, 0,0,0);
+  dBodySetAngularVel (boxbody, 0,0,0);
+  dBodySetQuaternion (boxbody, q);
+#endif
+#ifdef CYL
+  dBodySetPosition (cylbody, sx, sy, sz);
+  dBodySetLinearVel (cylbody, 0,0,0);
+  dBodySetAngularVel (cylbody, 0,0,0);
+  dBodySetQuaternion (cylbody, q);
+#endif
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  switch (cmd) 
+  {
+    case ' ':
+	  reset_state();
+      break;
+  }
+}
+
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  double simstep = 0.005; // 5ms simulation steps
+  double dt = dsElapsedTime();
+  int nrofsteps = (int) ceilf(dt/simstep);
+  for (int i=0; i<nrofsteps && !pause; i++)
+  {
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldQuickStep (world, simstep);
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (1,1,1);
+#ifdef BOX
+  const dReal *BPos = dBodyGetPosition(boxbody);
+  const dReal *BRot = dBodyGetRotation(boxbody);
+  float bpos[3] = {BPos[0], BPos[1], BPos[2]};
+  float brot[12] = { BRot[0], BRot[1], BRot[2], BRot[3], BRot[4], BRot[5], BRot[6], BRot[7], BRot[8], BRot[9], BRot[10], BRot[11] };
+  float sides[3] = {BOXSZ, BOXSZ, BOXSZ};
+  dsDrawBox
+  (
+    bpos, 
+    brot, 
+    sides
+  ); // single precision
+#endif
+#ifdef CYL
+  const dReal *CPos = dGeomGetPosition(cylgeom);
+  const dReal *CRot = dGeomGetRotation(cylgeom);
+  float cpos[3] = {CPos[0], CPos[1], CPos[2]};
+  float crot[12] = { CRot[0], CRot[1], CRot[2], CRot[3], CRot[4], CRot[5], CRot[6], CRot[7], CRot[8], CRot[9], CRot[10], CRot[11] };
+  dsDrawCylinder
+  ( 
+//    dBodyGetPosition(cylbody),
+//    dBodyGetRotation(cylbody),
+    cpos,
+    crot,
+    WHEELW,
+    RADIUS
+  ); // single precision
+#endif
+
+  // draw world trimesh
+  dsSetColor(0.7,0.7,0.4);
+  dsSetTexture (DS_NONE);
+
+  const dReal* Pos = dGeomGetPosition(world_mesh);
+  float pos[3] = { Pos[0], Pos[1], Pos[2] };
+
+  const dReal* Rot = dGeomGetRotation(world_mesh);
+  float rot[12] = { Rot[0], Rot[1], Rot[2], Rot[3], Rot[4], Rot[5], Rot[6], Rot[7], Rot[8], Rot[9], Rot[10], Rot[11] };
+
+  int numi = sizeof(world_indices)  / sizeof(int);
+
+  for (int i=0; i<numi/3; i++)
+  {
+    int i0 = world_indices[i*3+0];
+    int i1 = world_indices[i*3+1];
+    int i2 = world_indices[i*3+2];
+    float *v0 = world_vertices+i0*3;
+    float *v1 = world_vertices+i1*3;
+    float *v2 = world_vertices+i2*3;
+    dsDrawTriangle(pos, rot, v0,v1,v2, true); // single precision draw
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  dMass m;
+  dMatrix3 R;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-9.8);
+  dWorldSetQuickStepNumIterations (world, 12);
+
+
+  // Create a static world using a triangle mesh that we can collide with.
+  int numv = sizeof(world_vertices)/(3*sizeof(float));
+  int numi = sizeof(world_indices)/ sizeof(int);
+  printf("numv=%d, numi=%d\n", numv, numi);
+  dTriMeshDataID Data = dGeomTriMeshDataCreate();
+
+  dGeomTriMeshDataBuildSingle
+  (
+    Data, 
+    world_vertices, 
+    3 * sizeof(float), 
+    numv, 
+    world_indices, 
+    numi, 
+    3 * sizeof(int)
+  );
+
+  world_mesh = dCreateTriMesh(space, Data, 0, 0, 0);
+  dGeomSetPosition(world_mesh, 0, 0, 0.5);
+  dRFromAxisAndAngle (R, 0,1,0, 0.0);
+  dGeomSetRotation (world_mesh, R);
+
+
+#ifdef BOX
+  boxbody = dBodyCreate (world);
+  dMassSetBox (&m,1, BOXSZ, BOXSZ, BOXSZ);
+  dMassAdjust (&m, 1);
+  dBodySetMass (boxbody,&m);
+  boxgeom = dCreateBox (0, BOXSZ, BOXSZ, BOXSZ);
+  dGeomSetBody (boxgeom,boxbody);
+  dSpaceAdd (space, boxgeom);
+#endif
+#ifdef CYL
+  cylbody = dBodyCreate (world);
+  dMassSetSphere (&m,1,RADIUS);
+  dMassAdjust (&m,WMASS);
+  dBodySetMass (cylbody,&m);
+  cylgeom = dCreateCylinder(0, RADIUS, WHEELW);
+  dGeomSetBody (cylgeom,cylbody);
+  
+  #if defined(CYL_GEOM_OFFSET)
+  dMatrix3 mat;
+  dRFromAxisAndAngle(mat,1.0f,0.0f,0.0f,M_PI/2.0);
+  dGeomSetOffsetRotation(cylgeom,mat);
+  #endif
+    
+  dSpaceAdd (space, cylgeom);
+#endif
+  reset_state();
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupEmpty (contactgroup);
+  dJointGroupDestroy (contactgroup);
+
+  // First destroy geoms, then space, then the world.
+#ifdef CYL
+  dGeomDestroy (cylgeom);
+#endif
+#ifdef BOX
+  dGeomDestroy (boxgeom);
+#endif
+  dGeomDestroy (world_mesh);
+
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
+
Index: /code/branches/ode/ode-0.9/ode/demo/demo_cylvssphere.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_cylvssphere.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_cylvssphere.cpp	(revision 216)
@@ -0,0 +1,238 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// Test for cylinder vs sphere, by Bram Stolk
+
+#include <ode/config.h>
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+
+static dBodyID cylbody;
+static dGeomID cylgeom;
+
+static dBodyID sphbody;
+static dGeomID sphgeom;
+
+static dJointGroupID contactgroup;
+static dGeomID world_mesh;
+
+static bool show_contacts = true;
+
+#define CYLRADIUS    0.6
+#define CYLLENGTH    2.0
+#define SPHERERADIUS 0.5
+
+    
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawLine dsDrawLineD
+#endif
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  assert(o1);
+  assert(o2);
+
+  if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
+  {
+    fprintf(stderr,"testing space %p %p\n", o1,o2);
+    // colliding a space with something
+    dSpaceCollide2(o1,o2,data,&nearCallback);
+    // Note we do not want to test intersections within a space,
+    // only between spaces.
+    return;
+  }
+
+  const int N = 32;
+  dContact contact[N];
+  int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
+  if (n > 0) 
+  {
+    for (int i=0; i<n; i++) 
+    {
+      contact[i].surface.mode = 0;
+      contact[i].surface.mu = 50.0; // was: dInfinity
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2));
+      if (show_contacts) 
+      {
+        dMatrix3 RI;
+        dRSetIdentity (RI);
+        const dReal ss[3] = {0.12,0.12,0.12};
+        dsSetColorAlpha (0,0,1,0.5);
+        dsDrawBox (contact[i].geom.pos,RI,ss);
+        dReal *pos  = contact[i].geom.pos;
+        dReal depth = contact[i].geom.depth;
+        dReal *norm = contact[i].geom.normal;
+        dReal endp[3] = {pos[0]+depth*norm[0], pos[1]+depth*norm[1], pos[2]+depth*norm[2]};
+        dsSetColorAlpha (1,1,1,1);
+        dsDrawLine (contact[i].geom.pos, endp);
+      }
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {-8,-9,3};
+  static float hpr[3] = {45.0000f,-27.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  switch (cmd) 
+  {
+    case ' ':
+      break;
+  }
+}
+
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  dSpaceCollide (space,0,&nearCallback);
+  if (!pause)
+  {
+    dWorldQuickStep (world, 0.01); // 100 Hz
+  }
+  dJointGroupEmpty (contactgroup);
+
+  dsSetColorAlpha (1,1,0,0.5);
+
+  const dReal *CPos = dBodyGetPosition(cylbody);
+  const dReal *CRot = dBodyGetRotation(cylbody);
+  float cpos[3] = {CPos[0], CPos[1], CPos[2]};
+  float crot[12] = { CRot[0], CRot[1], CRot[2], CRot[3], CRot[4], CRot[5], CRot[6], CRot[7], CRot[8], CRot[9], CRot[10], CRot[11] };
+  dsDrawCylinder
+  (
+    cpos,
+    crot,
+    CYLLENGTH,
+    CYLRADIUS
+  ); // single precision
+
+  const dReal *SPos = dBodyGetPosition(sphbody);
+  const dReal *SRot = dBodyGetRotation(sphbody);
+  float spos[3] = {SPos[0], SPos[1], SPos[2]};
+  float srot[12] = { SRot[0], SRot[1], SRot[2], SRot[3], SRot[4], SRot[5], SRot[6], SRot[7], SRot[8], SRot[9], SRot[10], SRot[11] };
+  dsDrawSphere
+  (
+    spos,
+    srot,
+    SPHERERADIUS
+  ); // single precision
+}
+
+
+int main (int argc, char **argv)
+{
+  dMass m;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    fn.path_to_textures = argv[1];
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-9.8);
+  dWorldSetQuickStepNumIterations (world, 32);
+
+  dCreatePlane (space,0,0,1, 0.0);
+
+  cylbody = dBodyCreate (world);
+  dQuaternion q;
+#if 0
+  dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
+#else
+//  dQFromAxisAndAngle (q,1,0,0, M_PI * 1.0);
+  dQFromAxisAndAngle (q,1,0,0, M_PI * -0.77);
+#endif
+  dBodySetQuaternion (cylbody,q);
+  dMassSetCylinder (&m,1.0,3,CYLRADIUS,CYLLENGTH);
+  dBodySetMass (cylbody,&m);
+  cylgeom = dCreateCylinder(0, CYLRADIUS, CYLLENGTH);
+  dGeomSetBody (cylgeom,cylbody);
+  dBodySetPosition (cylbody, 0, 0, 3);
+  dSpaceAdd (space, cylgeom);
+
+  sphbody = dBodyCreate (world);
+  dMassSetSphere (&m,1,SPHERERADIUS);
+  dBodySetMass (sphbody,&m);
+  sphgeom = dCreateSphere(0, SPHERERADIUS);
+  dGeomSetBody (sphgeom,sphbody);
+  dBodySetPosition (sphbody, 0, 0, 5.5);
+  dSpaceAdd (space, sphgeom);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupEmpty (contactgroup);
+  dJointGroupDestroy (contactgroup);
+
+  dGeomDestroy(sphgeom);
+  dGeomDestroy (cylgeom);
+
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
+
Index: /code/branches/ode/ode-0.9/ode/demo/demo_feedback.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_feedback.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_feedback.cpp	(revision 216)
@@ -0,0 +1,314 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// Test for breaking joints, by Bram Stolk
+
+#include <ode/config.h>
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawCylinder dsDrawCylinderD
+#endif
+
+
+// dynamics and collision objects (chassis, 3 wheels, environment)
+
+static dWorldID world;
+static dSpaceID space;
+
+static const int   STACKCNT=10;	// nr of weights on bridge
+static const int   SEGMCNT=16;	// nr of segments in bridge
+static const float SEGMDIM[3] = { 0.9, 4, 0.1 };
+
+static dGeomID  groundgeom;
+static dBodyID  segbodies[SEGMCNT];
+static dGeomID  seggeoms[SEGMCNT];
+static dBodyID  stackbodies[STACKCNT];
+static dGeomID  stackgeoms[STACKCNT];
+static dJointID hinges[SEGMCNT-1];
+static dJointID sliders[2];
+static dJointFeedback jfeedbacks[SEGMCNT-1];
+static dReal colours[SEGMCNT];
+static int stress[SEGMCNT-1];
+
+static dJointGroupID contactgroup;
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  assert(o1);
+  assert(o2);
+
+  if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
+  {
+    fprintf(stderr,"testing space %p %p\n", o1,o2);
+    // colliding a space with something
+    dSpaceCollide2(o1,o2,data,&nearCallback);
+    // Note we do not want to test intersections within a space,
+    // only between spaces.
+    return;
+  }
+
+  const int N = 32;
+  dContact contact[N];
+  int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
+  if (n > 0) 
+  {
+    for (int i=0; i<n; i++) 
+    {
+      contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1;
+      contact[i].surface.mu = 100.0;
+      contact[i].surface.soft_erp = 0.96;
+      contact[i].surface.soft_cfm = 0.02;
+      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+      dJointAttach (c,
+		    dGeomGetBody(contact[i].geom.g1),
+		    dGeomGetBody(contact[i].geom.g2));
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = { -6, 8, 6};
+  static float hpr[3] = { -65.0f, -27.0f, 0.0f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+}
+
+
+
+void drawGeom (dGeomID g)
+{
+  const dReal *pos = dGeomGetPosition(g);
+  const dReal *R   = dGeomGetRotation(g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass)
+  {
+    dVector3 sides;
+    dGeomBoxGetLengths (g, sides);
+    dsDrawBox (pos,R,sides);
+  }
+  if (type == dCylinderClass)
+  {
+    dReal r,l;
+    dGeomCylinderGetParams(g, &r, &l);
+    dsDrawCylinder (pos, R, l, r);
+  }
+}
+
+
+static void inspectJoints(void)
+{
+  const dReal forcelimit = 2000.0;
+  int i;
+  for (i=0; i<SEGMCNT-1; i++)
+  {
+    if (dJointGetBody(hinges[i], 0))
+    {
+      // This joint has not snapped already... inspect it.
+      dReal l0 = dLENGTH(jfeedbacks[i].f1);
+      dReal l1 = dLENGTH(jfeedbacks[i].f2);
+      colours[i+0] = 0.95*colours[i+0] + 0.05 * l0/forcelimit;
+      colours[i+1] = 0.95*colours[i+1] + 0.05 * l1/forcelimit;
+      if (l0 > forcelimit || l1 > forcelimit)
+        stress[i]++;
+      else
+        stress[i]=0;
+      if (stress[i]>4)
+      {
+        // Low-pass filter the noisy feedback data.
+        // Only after 4 consecutive timesteps with excessive load, snap.
+        fprintf(stderr,"SNAP! (that was the sound of joint %d breaking)\n", i);
+        dJointAttach (hinges[i], 0, 0);
+      }
+    }
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i;
+
+  double simstep = 0.005; // 5ms simulation steps
+  double dt = dsElapsedTime();
+  int nrofsteps = (int) ceilf(dt/simstep);
+  for (i=0; i<nrofsteps && !pause; i++)
+  {
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldQuickStep (world, simstep);
+    dJointGroupEmpty (contactgroup);
+    inspectJoints();
+  }
+
+  for (i=0; i<SEGMCNT; i++)
+  {
+    float r=0,g=0,b=0.2;
+    float v = colours[i];
+    if (v>1.0) v=1.0;
+    if (v<0.5) 
+    {
+      r=2*v;
+      g=1.0;
+    }
+    else
+    {
+      r=1.0;
+      g=2*(1.0-v);
+    }
+    dsSetColor (r,g,b);
+    drawGeom(seggeoms[i]);
+  }
+  dsSetColor (1,1,1);
+  for (i=0; i<STACKCNT; i++)
+    drawGeom(stackgeoms[i]);
+}
+
+
+
+int main (int argc, char **argv)
+{
+  dMass m;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+  {
+    fn.path_to_textures = argv[1];
+  }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-9.8);
+  dWorldSetQuickStepNumIterations (world, 20);
+
+  int i;
+  for (i=0; i<SEGMCNT; i++)
+  {
+    segbodies[i] = dBodyCreate (world);
+    dBodySetPosition(segbodies[i], i - SEGMCNT/2.0, 0, 5);
+    dMassSetBox (&m, 1, SEGMDIM[0], SEGMDIM[1], SEGMDIM[2]);
+    dBodySetMass (segbodies[i], &m);
+    seggeoms[i] = dCreateBox (0, SEGMDIM[0], SEGMDIM[1], SEGMDIM[2]);
+    dGeomSetBody (seggeoms[i], segbodies[i]);
+    dSpaceAdd (space, seggeoms[i]);
+  }
+
+  for (i=0; i<SEGMCNT-1; i++)
+  {
+    hinges[i] = dJointCreateHinge (world,0);
+    dJointAttach (hinges[i], segbodies[i],segbodies[i+1]);
+    dJointSetHingeAnchor (hinges[i], i + 0.5 - SEGMCNT/2.0, 0, 5);
+    dJointSetHingeAxis (hinges[i], 0,1,0);
+    dJointSetHingeParam (hinges[i],dParamFMax,  8000.0);
+    // NOTE:
+    // Here we tell ODE where to put the feedback on the forces for this hinge
+    dJointSetFeedback (hinges[i], jfeedbacks+i);
+    stress[i]=0;
+  }
+
+  for (i=0; i<STACKCNT; i++)
+  {
+    stackbodies[i] = dBodyCreate(world);
+    dMassSetBox (&m, 2.0, 2, 2, 0.6);
+    dBodySetMass(stackbodies[i],&m);
+
+    stackgeoms[i] = dCreateBox(0, 2, 2, 0.6);
+    dGeomSetBody(stackgeoms[i], stackbodies[i]);
+    dBodySetPosition(stackbodies[i], 0,0,8+2*i);
+    dSpaceAdd(space, stackgeoms[i]);
+  }
+
+  sliders[0] = dJointCreateSlider (world,0);
+  dJointAttach(sliders[0], segbodies[0], 0);
+  dJointSetSliderAxis (sliders[0], 1,0,0);
+  dJointSetSliderParam (sliders[0],dParamFMax,  4000.0);
+  dJointSetSliderParam (sliders[0],dParamLoStop,   0.0);
+  dJointSetSliderParam (sliders[0],dParamHiStop,   0.2);
+
+  sliders[1] = dJointCreateSlider (world,0);
+  dJointAttach(sliders[1], segbodies[SEGMCNT-1], 0);
+  dJointSetSliderAxis (sliders[1], 1,0,0);
+  dJointSetSliderParam (sliders[1],dParamFMax,  4000.0);
+  dJointSetSliderParam (sliders[1],dParamLoStop,   0.0);
+  dJointSetSliderParam (sliders[1],dParamHiStop,  -0.2);
+
+  groundgeom = dCreatePlane(space, 0,0,1,0);
+
+  for (i=0; i<SEGMCNT; i++)
+    colours[i]=0.0;
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupEmpty (contactgroup);
+  dJointGroupDestroy (contactgroup);
+
+  // First destroy seggeoms, then space, then the world.
+  for (i=0; i<SEGMCNT; i++)
+    dGeomDestroy (seggeoms[i]);
+  for (i=0; i<STACKCNT; i++)
+    dGeomDestroy (stackgeoms[i]);
+
+  dSpaceDestroy(space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
+
Index: /code/branches/ode/ode-0.9/ode/demo/demo_friction.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_friction.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_friction.cpp	(revision 216)
@@ -0,0 +1,206 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+test the Coulomb friction approximation.
+
+a 10x10 array of boxes is made, each of which rests on the ground.
+a horizantal force is applied to each box to try and get it to slide.
+box[i][j] has a mass (i+1)*MASS and a force (j+1)*FORCE. by the Coloumb
+friction model, the box should only slide if the force is greater than MU
+times the contact normal force, i.e.
+
+  f > MU * body_mass * GRAVITY
+  (j+1)*FORCE > MU * (i+1)*MASS * GRAVITY
+  (j+1) > (i+1) * (MU*MASS*GRAVITY/FORCE)
+  (j+1) > (i+1) * k
+
+this should be independent of the number of contact points, as N contact
+points will each have 1/N'th the normal force but the pushing force will
+have to overcome N contacts. the constants are chosen so that k=1.
+thus you should see a triangle made of half the bodies in the array start to
+slide.
+
+*/
+
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define LENGTH 0.2	// box length & width
+#define HEIGHT 0.05	// box height
+#define MASS 0.2	// mass of box[i][j] = (i+1) * MASS
+#define FORCE 0.05	// force applied to box[i][j] = (j+1) * FORCE
+#define MU 0.5		// the global mu to use
+#define GRAVITY 0.5	// the global gravity to use
+#define N1 10		// number of different forces to try
+#define N2 10		// number of different masses to try
+
+
+// dynamics and collision objects
+
+static dWorldID world;
+static dSpaceID space;
+static dBodyID body[N1][N2];
+static dJointGroupID contactgroup;
+static dGeomID ground;
+static dGeomID box[N1][N2];
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+
+  // only collide things with the ground
+  int g1 = (o1 == ground);
+  int g2 = (o2 == ground);
+  if (!(g1 ^ g2)) return;
+
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+
+  dContact contact[3];		// up to 3 contacts per box
+  for (i=0; i<3; i++) {
+    contact[i].surface.mode = dContactSoftCFM | dContactApprox1;
+    contact[i].surface.mu = MU;
+    contact[i].surface.soft_cfm = 0.01;
+  }
+  if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) {
+    for (i=0; i<numc; i++) {
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {1.7772,-0.7924,2.7600};
+  static float hpr[3] = {90.0000,-54.0000,0.0000};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i;
+  if (!pause) {
+    // apply forces to all bodies
+    for (i=0; i<N1; i++) {
+      for (int j=0; j<N2; j++) {
+	dBodyAddForce (body[i][j],FORCE*(i+1),0,0);
+      }
+    }
+
+    dSpaceCollide (space,0,&nearCallback);
+    dWorldStep (world,0.05);
+
+    // remove all contact joints
+    dJointGroupEmpty (contactgroup);
+  }
+
+  dsSetColor (1,0,1);
+  dReal sides[3] = {LENGTH,LENGTH,HEIGHT};
+  for (i=0; i<N1; i++) {
+    for (int j=0; j<N2; j++) {
+      dsDrawBox (dGeomGetPosition(box[i][j]),dGeomGetRotation(box[i][j]),
+		 sides);
+    }
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  int i,j;
+  dMass m;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = 0;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-GRAVITY);
+  ground = dCreatePlane (space,0,0,1,0);
+
+  // bodies
+  for (i=0; i<N1; i++) {
+    for (j=0; j<N2; j++) {
+      body[i][j] = dBodyCreate (world);
+      dMassSetBox (&m,1,LENGTH,LENGTH,HEIGHT);
+      dMassAdjust (&m,MASS*(j+1));
+      dBodySetMass (body[i][j],&m);
+      dBodySetPosition (body[i][j],i*2*LENGTH,j*2*LENGTH,HEIGHT*0.5);
+
+      box[i][j] = dCreateBox (space,LENGTH,LENGTH,HEIGHT);
+      dGeomSetBody (box[i][j],body[i][j]);
+    }
+  }
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_heightfield.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_heightfield.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_heightfield.cpp	(revision 216)
@@ -0,0 +1,2132 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+#define	DEGTORAD			0.01745329251994329577f				//!< PI / 180.0, convert degrees to radians
+
+
+// Our heightfield geom
+dGeomID gheight;
+
+
+
+// Heightfield dimensions
+
+#define HFIELD_WSTEP			15			// Vertex count along edge >= 2
+#define HFIELD_DSTEP			31
+
+#define HFIELD_WIDTH			REAL( 4.0 )
+#define HFIELD_DEPTH			REAL( 8.0 )
+
+#define HFIELD_WSAMP			( HFIELD_WIDTH / ( HFIELD_WSTEP-1 ) )
+#define HFIELD_DSAMP			( HFIELD_DEPTH / ( HFIELD_DSTEP-1 ) )
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#define dsDrawConvex dsDrawConvexD
+#define dsDrawTriangle dsDrawTriangleD
+#endif
+
+
+
+//<---- Convex Object
+dReal planes[]= // planes for a cube
+  {
+    1.0f ,0.0f ,0.0f ,0.25f,
+    0.0f ,1.0f ,0.0f ,0.25f,
+    0.0f ,0.0f ,1.0f ,0.25f,
+    0.0f ,0.0f ,-1.0f,0.25f,
+    0.0f ,-1.0f,0.0f ,0.25f,
+    -1.0f,0.0f ,0.0f ,0.25f
+    /*
+    1.0f ,0.0f ,0.0f ,2.0f,
+    0.0f ,1.0f ,0.0f ,1.0f,
+    0.0f ,0.0f ,1.0f ,1.0f,
+    0.0f ,0.0f ,-1.0f,1.0f,
+    0.0f ,-1.0f,0.0f ,1.0f,
+    -1.0f,0.0f ,0.0f ,0.0f
+    */
+  };
+const unsigned int planecount=6;
+
+dReal points[]= // points for a cube
+  {
+    0.25f,0.25f,0.25f,  //  point 0
+    -0.25f,0.25f,0.25f, //  point 1
+
+    0.25f,-0.25f,0.25f, //  point 2
+    -0.25f,-0.25f,0.25f,//  point 3
+
+    0.25f,0.25f,-0.25f, //  point 4
+    -0.25f,0.25f,-0.25f,//  point 5
+
+    0.25f,-0.25f,-0.25f,//  point 6
+    -0.25f,-0.25f,-0.25f,// point 7
+  };
+const unsigned int pointcount=8;
+unsigned int polygons[] = //Polygons for a cube (6 squares)
+  {
+    4,0,2,6,4, // positive X
+    4,1,0,4,5, // positive Y
+    4,0,1,3,2, // positive Z
+    4,3,1,5,7, // negative X
+    4,2,3,7,6, // negative Y
+    4,5,4,6,7, // negative Z
+  };
+//----> Convex Object
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#define dsDrawConvex dsDrawConvexD
+#endif
+
+
+// some constants
+
+#define NUM 100			// max number of objects
+#define DENSITY (5.0)		// density of all objects
+#define GPB 3			// maximum number of geometries per body
+#define MAX_CONTACTS 64		// maximum number of contact points per body
+
+
+// dynamics and collision objects
+
+struct MyObject {
+  dBodyID body;			// the body
+  dGeomID geom[GPB];		// geometries representing this body
+
+  // Trimesh only - double buffered matrices for 'last transform' setup
+  dReal matrix_dblbuff[ 16 * 2 ];
+  int last_matrix_index;
+};
+
+static int num=0;		// number of objects in simulation
+static int nextobj=0;		// next object to recycle if num==NUM
+static dWorldID world;
+static dSpaceID space;
+static MyObject obj[NUM];
+static dJointGroupID contactgroup;
+static int selected = -1;	// selected object
+static int show_aabb = 0;	// show geom AABBs?
+static int show_contacts = 0;	// show contact points?
+static int random_pos = 1;	// drop objects from random position?
+static int write_world = 0;
+
+
+
+
+//============================
+
+// Bunny mesh ripped from Opcode
+const int VertexCount = 453;
+const int IndexCount = 902 * 3;
+
+typedef dReal dVector3R[3];
+
+dGeomID TriMesh1;
+dGeomID TriMesh2;
+static dTriMeshDataID TriData1, TriData2;  // reusable static trimesh data
+
+static float Vertices[VertexCount * 3] = {
+	REAL(-0.334392), REAL(0.133007), REAL(0.062259),
+	REAL(-0.350189), REAL(0.150354), REAL(-0.147769),
+	REAL(-0.234201), REAL(0.343811), REAL(-0.174307),
+	REAL(-0.200259), REAL(0.285207), REAL(0.093749),
+	REAL(0.003520), REAL(0.475208), REAL(-0.159365),
+	REAL(0.001856), REAL(0.419203), REAL(0.098582),
+	REAL(-0.252802), REAL(0.093666), REAL(0.237538),
+	REAL(-0.162901), REAL(0.237984), REAL(0.206905),
+	REAL(0.000865), REAL(0.318141), REAL(0.235370),
+	REAL(-0.414624), REAL(0.164083), REAL(-0.278254),
+	REAL(-0.262213), REAL(0.357334), REAL(-0.293246),
+	REAL(0.004628), REAL(0.482694), REAL(-0.338626),
+	REAL(-0.402162), REAL(0.133528), REAL(-0.443247),
+	REAL(-0.243781), REAL(0.324275), REAL(-0.436763),
+	REAL(0.005293), REAL(0.437592), REAL(-0.458332),
+	REAL(-0.339884), REAL(-0.041150), REAL(-0.668211),
+	REAL(-0.248382), REAL(0.255825), REAL(-0.627493),
+	REAL(0.006261), REAL(0.376103), REAL(-0.631506),
+	REAL(-0.216201), REAL(-0.126776), REAL(-0.886936),
+	REAL(-0.171075), REAL(0.011544), REAL(-0.881386),
+	REAL(-0.181074), REAL(0.098223), REAL(-0.814779),
+	REAL(-0.119891), REAL(0.218786), REAL(-0.760153),
+	REAL(-0.078895), REAL(0.276780), REAL(-0.739281),
+	REAL(0.006801), REAL(0.310959), REAL(-0.735661),
+	REAL(-0.168842), REAL(0.102387), REAL(-0.920381),
+	REAL(-0.104072), REAL(0.177278), REAL(-0.952530),
+	REAL(-0.129704), REAL(0.211848), REAL(-0.836678),
+	REAL(-0.099875), REAL(0.310931), REAL(-0.799381),
+	REAL(0.007237), REAL(0.361687), REAL(-0.794439),
+	REAL(-0.077913), REAL(0.258753), REAL(-0.921640),
+	REAL(0.007957), REAL(0.282241), REAL(-0.931680),
+	REAL(-0.252222), REAL(-0.550401), REAL(-0.557810),
+	REAL(-0.267633), REAL(-0.603419), REAL(-0.655209),
+	REAL(-0.446838), REAL(-0.118517), REAL(-0.466159),
+	REAL(-0.459488), REAL(-0.093017), REAL(-0.311341),
+	REAL(-0.370645), REAL(-0.100108), REAL(-0.159454),
+	REAL(-0.371984), REAL(-0.091991), REAL(-0.011044),
+	REAL(-0.328945), REAL(-0.098269), REAL(0.088659),
+	REAL(-0.282452), REAL(-0.018862), REAL(0.311501),
+	REAL(-0.352403), REAL(-0.131341), REAL(0.144902),
+	REAL(-0.364126), REAL(-0.200299), REAL(0.202388),
+	REAL(-0.283965), REAL(-0.231869), REAL(0.023668),
+	REAL(-0.298943), REAL(-0.155218), REAL(0.369716),
+	REAL(-0.293787), REAL(-0.121856), REAL(0.419097),
+	REAL(-0.290163), REAL(-0.290797), REAL(0.107824),
+	REAL(-0.264165), REAL(-0.272849), REAL(0.036347),
+	REAL(-0.228567), REAL(-0.372573), REAL(0.290309),
+	REAL(-0.190431), REAL(-0.286997), REAL(0.421917),
+	REAL(-0.191039), REAL(-0.240973), REAL(0.507118),
+	REAL(-0.287272), REAL(-0.276431), REAL(-0.065444),
+	REAL(-0.295675), REAL(-0.280818), REAL(-0.174200),
+	REAL(-0.399537), REAL(-0.313131), REAL(-0.376167),
+	REAL(-0.392666), REAL(-0.488581), REAL(-0.427494),
+	REAL(-0.331669), REAL(-0.570185), REAL(-0.466054),
+	REAL(-0.282290), REAL(-0.618140), REAL(-0.589220),
+	REAL(-0.374238), REAL(-0.594882), REAL(-0.323298),
+	REAL(-0.381071), REAL(-0.629723), REAL(-0.350777),
+	REAL(-0.382112), REAL(-0.624060), REAL(-0.221577),
+	REAL(-0.272701), REAL(-0.566522), REAL(0.259157),
+	REAL(-0.256702), REAL(-0.663406), REAL(0.286079),
+	REAL(-0.280948), REAL(-0.428359), REAL(0.055790),
+	REAL(-0.184974), REAL(-0.508894), REAL(0.326265),
+	REAL(-0.279971), REAL(-0.526918), REAL(0.395319),
+	REAL(-0.282599), REAL(-0.663393), REAL(0.412411),
+	REAL(-0.188329), REAL(-0.475093), REAL(0.417954),
+	REAL(-0.263384), REAL(-0.663396), REAL(0.466604),
+	REAL(-0.209063), REAL(-0.663393), REAL(0.509344),
+	REAL(-0.002044), REAL(-0.319624), REAL(0.553078),
+	REAL(-0.001266), REAL(-0.371260), REAL(0.413296),
+	REAL(-0.219753), REAL(-0.339762), REAL(-0.040921),
+	REAL(-0.256986), REAL(-0.282511), REAL(-0.006349),
+	REAL(-0.271706), REAL(-0.260881), REAL(0.001764),
+	REAL(-0.091191), REAL(-0.419184), REAL(-0.045912),
+	REAL(-0.114944), REAL(-0.429752), REAL(-0.124739),
+	REAL(-0.113970), REAL(-0.382987), REAL(-0.188540),
+	REAL(-0.243012), REAL(-0.464942), REAL(-0.242850),
+	REAL(-0.314815), REAL(-0.505402), REAL(-0.324768),
+	REAL(0.002774), REAL(-0.437526), REAL(-0.262766),
+	REAL(-0.072625), REAL(-0.417748), REAL(-0.221440),
+	REAL(-0.160112), REAL(-0.476932), REAL(-0.293450),
+	REAL(0.003859), REAL(-0.453425), REAL(-0.443916),
+	REAL(-0.120363), REAL(-0.581567), REAL(-0.438689),
+	REAL(-0.091499), REAL(-0.584191), REAL(-0.294511),
+	REAL(-0.116469), REAL(-0.599861), REAL(-0.188308),
+	REAL(-0.208032), REAL(-0.513640), REAL(-0.134649),
+	REAL(-0.235749), REAL(-0.610017), REAL(-0.040939),
+	REAL(-0.344916), REAL(-0.622487), REAL(-0.085380),
+	REAL(-0.336401), REAL(-0.531864), REAL(-0.212298),
+	REAL(0.001961), REAL(-0.459550), REAL(-0.135547),
+	REAL(-0.058296), REAL(-0.430536), REAL(-0.043440),
+	REAL(0.001378), REAL(-0.449511), REAL(-0.037762),
+	REAL(-0.130135), REAL(-0.510222), REAL(0.079144),
+	REAL(0.000142), REAL(-0.477549), REAL(0.157064),
+	REAL(-0.114284), REAL(-0.453206), REAL(0.304397),
+	REAL(-0.000592), REAL(-0.443558), REAL(0.285401),
+	REAL(-0.056215), REAL(-0.663402), REAL(0.326073),
+	REAL(-0.026248), REAL(-0.568010), REAL(0.273318),
+	REAL(-0.049261), REAL(-0.531064), REAL(0.389854),
+	REAL(-0.127096), REAL(-0.663398), REAL(0.479316),
+	REAL(-0.058384), REAL(-0.663401), REAL(0.372891),
+	REAL(-0.303961), REAL(0.054199), REAL(0.625921),
+	REAL(-0.268594), REAL(0.193403), REAL(0.502766),
+	REAL(-0.277159), REAL(0.126123), REAL(0.443289),
+	REAL(-0.287605), REAL(-0.005722), REAL(0.531844),
+	REAL(-0.231396), REAL(-0.121289), REAL(0.587387),
+	REAL(-0.253475), REAL(-0.081797), REAL(0.756541),
+	REAL(-0.195164), REAL(-0.137969), REAL(0.728011),
+	REAL(-0.167673), REAL(-0.156573), REAL(0.609388),
+	REAL(-0.145917), REAL(-0.169029), REAL(0.697600),
+	REAL(-0.077776), REAL(-0.214247), REAL(0.622586),
+	REAL(-0.076873), REAL(-0.214971), REAL(0.696301),
+	REAL(-0.002341), REAL(-0.233135), REAL(0.622859),
+	REAL(-0.002730), REAL(-0.213526), REAL(0.691267),
+	REAL(-0.003136), REAL(-0.192628), REAL(0.762731),
+	REAL(-0.056136), REAL(-0.201222), REAL(0.763806),
+	REAL(-0.114589), REAL(-0.166192), REAL(0.770723),
+	REAL(-0.155145), REAL(-0.129632), REAL(0.791738),
+	REAL(-0.183611), REAL(-0.058705), REAL(0.847012),
+	REAL(-0.165562), REAL(0.001980), REAL(0.833386),
+	REAL(-0.220084), REAL(0.019914), REAL(0.768935),
+	REAL(-0.255730), REAL(0.090306), REAL(0.670782),
+	REAL(-0.255594), REAL(0.113833), REAL(0.663389),
+	REAL(-0.226380), REAL(0.212655), REAL(0.617740),
+	REAL(-0.003367), REAL(-0.195342), REAL(0.799680),
+	REAL(-0.029743), REAL(-0.210508), REAL(0.827180),
+	REAL(-0.003818), REAL(-0.194783), REAL(0.873636),
+	REAL(-0.004116), REAL(-0.157907), REAL(0.931268),
+	REAL(-0.031280), REAL(-0.184555), REAL(0.889476),
+	REAL(-0.059885), REAL(-0.184448), REAL(0.841330),
+	REAL(-0.135333), REAL(-0.164332), REAL(0.878200),
+	REAL(-0.085574), REAL(-0.170948), REAL(0.925547),
+	REAL(-0.163833), REAL(-0.094170), REAL(0.897114),
+	REAL(-0.138444), REAL(-0.104250), REAL(0.945975),
+	REAL(-0.083497), REAL(-0.084934), REAL(0.979607),
+	REAL(-0.004433), REAL(-0.146642), REAL(0.985872),
+	REAL(-0.150715), REAL(0.032650), REAL(0.884111),
+	REAL(-0.135892), REAL(-0.035520), REAL(0.945455),
+	REAL(-0.070612), REAL(0.036849), REAL(0.975733),
+	REAL(-0.004458), REAL(-0.042526), REAL(1.015670),
+	REAL(-0.004249), REAL(0.046042), REAL(1.003240),
+	REAL(-0.086969), REAL(0.133224), REAL(0.947633),
+	REAL(-0.003873), REAL(0.161605), REAL(0.970499),
+	REAL(-0.125544), REAL(0.140012), REAL(0.917678),
+	REAL(-0.125651), REAL(0.250246), REAL(0.857602),
+	REAL(-0.003127), REAL(0.284070), REAL(0.878870),
+	REAL(-0.159174), REAL(0.125726), REAL(0.888878),
+	REAL(-0.183807), REAL(0.196970), REAL(0.844480),
+	REAL(-0.159890), REAL(0.291736), REAL(0.732480),
+	REAL(-0.199495), REAL(0.207230), REAL(0.779864),
+	REAL(-0.206182), REAL(0.164608), REAL(0.693257),
+	REAL(-0.186315), REAL(0.160689), REAL(0.817193),
+	REAL(-0.192827), REAL(0.166706), REAL(0.782271),
+	REAL(-0.175112), REAL(0.110008), REAL(0.860621),
+	REAL(-0.161022), REAL(0.057420), REAL(0.855111),
+	REAL(-0.172319), REAL(0.036155), REAL(0.816189),
+	REAL(-0.190318), REAL(0.064083), REAL(0.760605),
+	REAL(-0.195072), REAL(0.129179), REAL(0.731104),
+	REAL(-0.203126), REAL(0.410287), REAL(0.680536),
+	REAL(-0.216677), REAL(0.309274), REAL(0.642272),
+	REAL(-0.241515), REAL(0.311485), REAL(0.587832),
+	REAL(-0.002209), REAL(0.366663), REAL(0.749413),
+	REAL(-0.088230), REAL(0.396265), REAL(0.678635),
+	REAL(-0.170147), REAL(0.109517), REAL(0.840784),
+	REAL(-0.160521), REAL(0.067766), REAL(0.830650),
+	REAL(-0.181546), REAL(0.139805), REAL(0.812146),
+	REAL(-0.180495), REAL(0.148568), REAL(0.776087),
+	REAL(-0.180255), REAL(0.129125), REAL(0.744192),
+	REAL(-0.186298), REAL(0.078308), REAL(0.769352),
+	REAL(-0.167622), REAL(0.060539), REAL(0.806675),
+	REAL(-0.189876), REAL(0.102760), REAL(0.802582),
+	REAL(-0.108340), REAL(0.455446), REAL(0.657174),
+	REAL(-0.241585), REAL(0.527592), REAL(0.669296),
+	REAL(-0.265676), REAL(0.513366), REAL(0.634594),
+	REAL(-0.203073), REAL(0.478550), REAL(0.581526),
+	REAL(-0.266772), REAL(0.642330), REAL(0.602061),
+	REAL(-0.216961), REAL(0.564846), REAL(0.535435),
+	REAL(-0.202210), REAL(0.525495), REAL(0.475944),
+	REAL(-0.193888), REAL(0.467925), REAL(0.520606),
+	REAL(-0.265837), REAL(0.757267), REAL(0.500933),
+	REAL(-0.240306), REAL(0.653440), REAL(0.463215),
+	REAL(-0.309239), REAL(0.776868), REAL(0.304726),
+	REAL(-0.271009), REAL(0.683094), REAL(0.382018),
+	REAL(-0.312111), REAL(0.671099), REAL(0.286687),
+	REAL(-0.268791), REAL(0.624342), REAL(0.377231),
+	REAL(-0.302457), REAL(0.533996), REAL(0.360289),
+	REAL(-0.263656), REAL(0.529310), REAL(0.412564),
+	REAL(-0.282311), REAL(0.415167), REAL(0.447666),
+	REAL(-0.239201), REAL(0.442096), REAL(0.495604),
+	REAL(-0.220043), REAL(0.569026), REAL(0.445877),
+	REAL(-0.001263), REAL(0.395631), REAL(0.602029),
+	REAL(-0.057345), REAL(0.442535), REAL(0.572224),
+	REAL(-0.088927), REAL(0.506333), REAL(0.529106),
+	REAL(-0.125738), REAL(0.535076), REAL(0.612913),
+	REAL(-0.126251), REAL(0.577170), REAL(0.483159),
+	REAL(-0.149594), REAL(0.611520), REAL(0.557731),
+	REAL(-0.163188), REAL(0.660791), REAL(0.491080),
+	REAL(-0.172482), REAL(0.663387), REAL(0.415416),
+	REAL(-0.160464), REAL(0.591710), REAL(0.370659),
+	REAL(-0.156445), REAL(0.536396), REAL(0.378302),
+	REAL(-0.136496), REAL(0.444358), REAL(0.425226),
+	REAL(-0.095564), REAL(0.373768), REAL(0.473659),
+	REAL(-0.104146), REAL(0.315912), REAL(0.498104),
+	REAL(-0.000496), REAL(0.384194), REAL(0.473817),
+	REAL(-0.000183), REAL(0.297770), REAL(0.401486),
+	REAL(-0.129042), REAL(0.270145), REAL(0.434495),
+	REAL(0.000100), REAL(0.272963), REAL(0.349138),
+	REAL(-0.113060), REAL(0.236984), REAL(0.385554),
+	REAL(0.007260), REAL(0.016311), REAL(-0.883396),
+	REAL(0.007865), REAL(0.122104), REAL(-0.956137),
+	REAL(-0.032842), REAL(0.115282), REAL(-0.953252),
+	REAL(-0.089115), REAL(0.108449), REAL(-0.950317),
+	REAL(-0.047440), REAL(0.014729), REAL(-0.882756),
+	REAL(-0.104458), REAL(0.013137), REAL(-0.882070),
+	REAL(-0.086439), REAL(-0.584866), REAL(-0.608343),
+	REAL(-0.115026), REAL(-0.662605), REAL(-0.436732),
+	REAL(-0.071683), REAL(-0.665372), REAL(-0.606385),
+	REAL(-0.257884), REAL(-0.665381), REAL(-0.658052),
+	REAL(-0.272542), REAL(-0.665381), REAL(-0.592063),
+	REAL(-0.371322), REAL(-0.665382), REAL(-0.353620),
+	REAL(-0.372362), REAL(-0.665381), REAL(-0.224420),
+	REAL(-0.335166), REAL(-0.665380), REAL(-0.078623),
+	REAL(-0.225999), REAL(-0.665375), REAL(-0.038981),
+	REAL(-0.106719), REAL(-0.665374), REAL(-0.186351),
+	REAL(-0.081749), REAL(-0.665372), REAL(-0.292554),
+	REAL(0.006943), REAL(-0.091505), REAL(-0.858354),
+	REAL(0.006117), REAL(-0.280985), REAL(-0.769967),
+	REAL(0.004495), REAL(-0.502360), REAL(-0.559799),
+	REAL(-0.198638), REAL(-0.302135), REAL(-0.845816),
+	REAL(-0.237395), REAL(-0.542544), REAL(-0.587188),
+	REAL(-0.270001), REAL(-0.279489), REAL(-0.669861),
+	REAL(-0.134547), REAL(-0.119852), REAL(-0.959004),
+	REAL(-0.052088), REAL(-0.122463), REAL(-0.944549),
+	REAL(-0.124463), REAL(-0.293508), REAL(-0.899566),
+	REAL(-0.047616), REAL(-0.289643), REAL(-0.879292),
+	REAL(-0.168595), REAL(-0.529132), REAL(-0.654931),
+	REAL(-0.099793), REAL(-0.515719), REAL(-0.645873),
+	REAL(-0.186168), REAL(-0.605282), REAL(-0.724690),
+	REAL(-0.112970), REAL(-0.583097), REAL(-0.707469),
+	REAL(-0.108152), REAL(-0.665375), REAL(-0.700408),
+	REAL(-0.183019), REAL(-0.665378), REAL(-0.717630),
+	REAL(-0.349529), REAL(-0.334459), REAL(-0.511985),
+	REAL(-0.141182), REAL(-0.437705), REAL(-0.798194),
+	REAL(-0.212670), REAL(-0.448725), REAL(-0.737447),
+	REAL(-0.261111), REAL(-0.414945), REAL(-0.613835),
+	REAL(-0.077364), REAL(-0.431480), REAL(-0.778113),
+	REAL(0.005174), REAL(-0.425277), REAL(-0.651592),
+	REAL(0.089236), REAL(-0.431732), REAL(-0.777093),
+	REAL(0.271006), REAL(-0.415749), REAL(-0.610577),
+	REAL(0.223981), REAL(-0.449384), REAL(-0.734774),
+	REAL(0.153275), REAL(-0.438150), REAL(-0.796391),
+	REAL(0.358414), REAL(-0.335529), REAL(-0.507649),
+	REAL(0.193434), REAL(-0.665946), REAL(-0.715325),
+	REAL(0.118363), REAL(-0.665717), REAL(-0.699021),
+	REAL(0.123515), REAL(-0.583454), REAL(-0.706020),
+	REAL(0.196851), REAL(-0.605860), REAL(-0.722345),
+	REAL(0.109788), REAL(-0.516035), REAL(-0.644590),
+	REAL(0.178656), REAL(-0.529656), REAL(-0.652804),
+	REAL(0.061157), REAL(-0.289807), REAL(-0.878626),
+	REAL(0.138234), REAL(-0.293905), REAL(-0.897958),
+	REAL(0.066933), REAL(-0.122643), REAL(-0.943820),
+	REAL(0.149571), REAL(-0.120281), REAL(-0.957264),
+	REAL(0.280989), REAL(-0.280321), REAL(-0.666487),
+	REAL(0.246581), REAL(-0.543275), REAL(-0.584224),
+	REAL(0.211720), REAL(-0.302754), REAL(-0.843303),
+	REAL(0.086966), REAL(-0.665627), REAL(-0.291520),
+	REAL(0.110634), REAL(-0.665702), REAL(-0.185021),
+	REAL(0.228099), REAL(-0.666061), REAL(-0.036201),
+	REAL(0.337743), REAL(-0.666396), REAL(-0.074503),
+	REAL(0.376722), REAL(-0.666513), REAL(-0.219833),
+	REAL(0.377265), REAL(-0.666513), REAL(-0.349036),
+	REAL(0.281411), REAL(-0.666217), REAL(-0.588670),
+	REAL(0.267564), REAL(-0.666174), REAL(-0.654834),
+	REAL(0.080745), REAL(-0.665602), REAL(-0.605452),
+	REAL(0.122016), REAL(-0.662963), REAL(-0.435280),
+	REAL(0.095767), REAL(-0.585141), REAL(-0.607228),
+	REAL(0.118944), REAL(0.012799), REAL(-0.880702),
+	REAL(0.061944), REAL(0.014564), REAL(-0.882086),
+	REAL(0.104725), REAL(0.108156), REAL(-0.949130),
+	REAL(0.048513), REAL(0.115159), REAL(-0.952753),
+	REAL(0.112696), REAL(0.236643), REAL(0.386937),
+	REAL(0.128177), REAL(0.269757), REAL(0.436071),
+	REAL(0.102643), REAL(0.315600), REAL(0.499370),
+	REAL(0.094535), REAL(0.373481), REAL(0.474824),
+	REAL(0.136270), REAL(0.443946), REAL(0.426895),
+	REAL(0.157071), REAL(0.535923), REAL(0.380222),
+	REAL(0.161350), REAL(0.591224), REAL(0.372630),
+	REAL(0.173035), REAL(0.662865), REAL(0.417531),
+	REAL(0.162808), REAL(0.660299), REAL(0.493077),
+	REAL(0.148250), REAL(0.611070), REAL(0.559555),
+	REAL(0.125719), REAL(0.576790), REAL(0.484702),
+	REAL(0.123489), REAL(0.534699), REAL(0.614440),
+	REAL(0.087621), REAL(0.506066), REAL(0.530188),
+	REAL(0.055321), REAL(0.442365), REAL(0.572915),
+	REAL(0.219936), REAL(0.568361), REAL(0.448571),
+	REAL(0.238099), REAL(0.441375), REAL(0.498528),
+	REAL(0.281711), REAL(0.414315), REAL(0.451121),
+	REAL(0.263833), REAL(0.528513), REAL(0.415794),
+	REAL(0.303284), REAL(0.533081), REAL(0.363998),
+	REAL(0.269687), REAL(0.623528), REAL(0.380528),
+	REAL(0.314255), REAL(0.670153), REAL(0.290524),
+	REAL(0.272023), REAL(0.682273), REAL(0.385343),
+	REAL(0.311480), REAL(0.775931), REAL(0.308527),
+	REAL(0.240239), REAL(0.652714), REAL(0.466159),
+	REAL(0.265619), REAL(0.756464), REAL(0.504187),
+	REAL(0.192562), REAL(0.467341), REAL(0.522972),
+	REAL(0.201605), REAL(0.524885), REAL(0.478417),
+	REAL(0.215743), REAL(0.564193), REAL(0.538084),
+	REAL(0.264969), REAL(0.641527), REAL(0.605317),
+	REAL(0.201031), REAL(0.477940), REAL(0.584002),
+	REAL(0.263086), REAL(0.512567), REAL(0.637832),
+	REAL(0.238615), REAL(0.526867), REAL(0.672237),
+	REAL(0.105309), REAL(0.455123), REAL(0.658482),
+	REAL(0.183993), REAL(0.102195), REAL(0.804872),
+	REAL(0.161563), REAL(0.060042), REAL(0.808692),
+	REAL(0.180748), REAL(0.077754), REAL(0.771600),
+	REAL(0.175168), REAL(0.128588), REAL(0.746368),
+	REAL(0.175075), REAL(0.148030), REAL(0.778264),
+	REAL(0.175658), REAL(0.139265), REAL(0.814333),
+	REAL(0.154191), REAL(0.067291), REAL(0.832578),
+	REAL(0.163818), REAL(0.109013), REAL(0.842830),
+	REAL(0.084760), REAL(0.396004), REAL(0.679695),
+	REAL(0.238888), REAL(0.310760), REAL(0.590775),
+	REAL(0.213380), REAL(0.308625), REAL(0.644905),
+	REAL(0.199666), REAL(0.409678), REAL(0.683003),
+	REAL(0.190143), REAL(0.128597), REAL(0.733463),
+	REAL(0.184833), REAL(0.063516), REAL(0.762902),
+	REAL(0.166070), REAL(0.035644), REAL(0.818261),
+	REAL(0.154361), REAL(0.056943), REAL(0.857042),
+	REAL(0.168542), REAL(0.109489), REAL(0.862725),
+	REAL(0.187387), REAL(0.166131), REAL(0.784599),
+	REAL(0.180428), REAL(0.160135), REAL(0.819438),
+	REAL(0.201823), REAL(0.163991), REAL(0.695756),
+	REAL(0.194206), REAL(0.206635), REAL(0.782275),
+	REAL(0.155438), REAL(0.291260), REAL(0.734412),
+	REAL(0.177696), REAL(0.196424), REAL(0.846693),
+	REAL(0.152305), REAL(0.125256), REAL(0.890786),
+	REAL(0.119546), REAL(0.249876), REAL(0.859104),
+	REAL(0.118369), REAL(0.139643), REAL(0.919173),
+	REAL(0.079410), REAL(0.132973), REAL(0.948652),
+	REAL(0.062419), REAL(0.036648), REAL(0.976547),
+	REAL(0.127847), REAL(-0.035919), REAL(0.947070),
+	REAL(0.143624), REAL(0.032206), REAL(0.885913),
+	REAL(0.074888), REAL(-0.085173), REAL(0.980577),
+	REAL(0.130184), REAL(-0.104656), REAL(0.947620),
+	REAL(0.156201), REAL(-0.094653), REAL(0.899074),
+	REAL(0.077366), REAL(-0.171194), REAL(0.926545),
+	REAL(0.127722), REAL(-0.164729), REAL(0.879810),
+	REAL(0.052670), REAL(-0.184618), REAL(0.842019),
+	REAL(0.023477), REAL(-0.184638), REAL(0.889811),
+	REAL(0.022626), REAL(-0.210587), REAL(0.827500),
+	REAL(0.223089), REAL(0.211976), REAL(0.620493),
+	REAL(0.251444), REAL(0.113067), REAL(0.666494),
+	REAL(0.251419), REAL(0.089540), REAL(0.673887),
+	REAL(0.214360), REAL(0.019258), REAL(0.771595),
+	REAL(0.158999), REAL(0.001490), REAL(0.835374),
+	REAL(0.176696), REAL(-0.059249), REAL(0.849218),
+	REAL(0.148696), REAL(-0.130091), REAL(0.793599),
+	REAL(0.108290), REAL(-0.166528), REAL(0.772088),
+	REAL(0.049820), REAL(-0.201382), REAL(0.764454),
+	REAL(0.071341), REAL(-0.215195), REAL(0.697209),
+	REAL(0.073148), REAL(-0.214475), REAL(0.623510),
+	REAL(0.140502), REAL(-0.169461), REAL(0.699354),
+	REAL(0.163374), REAL(-0.157073), REAL(0.611416),
+	REAL(0.189466), REAL(-0.138550), REAL(0.730366),
+	REAL(0.247593), REAL(-0.082554), REAL(0.759610),
+	REAL(0.227468), REAL(-0.121982), REAL(0.590197),
+	REAL(0.284702), REAL(-0.006586), REAL(0.535347),
+	REAL(0.275741), REAL(0.125287), REAL(0.446676),
+	REAL(0.266650), REAL(0.192594), REAL(0.506044),
+	REAL(0.300086), REAL(0.053287), REAL(0.629620),
+	REAL(0.055450), REAL(-0.663935), REAL(0.375065),
+	REAL(0.122854), REAL(-0.664138), REAL(0.482323),
+	REAL(0.046520), REAL(-0.531571), REAL(0.391918),
+	REAL(0.024824), REAL(-0.568450), REAL(0.275106),
+	REAL(0.053855), REAL(-0.663931), REAL(0.328224),
+	REAL(0.112829), REAL(-0.453549), REAL(0.305788),
+	REAL(0.131265), REAL(-0.510617), REAL(0.080746),
+	REAL(0.061174), REAL(-0.430716), REAL(-0.042710),
+	REAL(0.341019), REAL(-0.532887), REAL(-0.208150),
+	REAL(0.347705), REAL(-0.623533), REAL(-0.081139),
+	REAL(0.238040), REAL(-0.610732), REAL(-0.038037),
+	REAL(0.211764), REAL(-0.514274), REAL(-0.132078),
+	REAL(0.120605), REAL(-0.600219), REAL(-0.186856),
+	REAL(0.096985), REAL(-0.584476), REAL(-0.293357),
+	REAL(0.127621), REAL(-0.581941), REAL(-0.437170),
+	REAL(0.165902), REAL(-0.477425), REAL(-0.291453),
+	REAL(0.077720), REAL(-0.417975), REAL(-0.220519),
+	REAL(0.320892), REAL(-0.506363), REAL(-0.320874),
+	REAL(0.248214), REAL(-0.465684), REAL(-0.239842),
+	REAL(0.118764), REAL(-0.383338), REAL(-0.187114),
+	REAL(0.118816), REAL(-0.430106), REAL(-0.123307),
+	REAL(0.094131), REAL(-0.419464), REAL(-0.044777),
+	REAL(0.274526), REAL(-0.261706), REAL(0.005110),
+	REAL(0.259842), REAL(-0.283292), REAL(-0.003185),
+	REAL(0.222861), REAL(-0.340431), REAL(-0.038210),
+	REAL(0.204445), REAL(-0.664380), REAL(0.513353),
+	REAL(0.259286), REAL(-0.664547), REAL(0.471281),
+	REAL(0.185402), REAL(-0.476020), REAL(0.421718),
+	REAL(0.279163), REAL(-0.664604), REAL(0.417328),
+	REAL(0.277157), REAL(-0.528122), REAL(0.400208),
+	REAL(0.183069), REAL(-0.509812), REAL(0.329995),
+	REAL(0.282599), REAL(-0.429210), REAL(0.059242),
+	REAL(0.254816), REAL(-0.664541), REAL(0.290687),
+	REAL(0.271436), REAL(-0.567707), REAL(0.263966),
+	REAL(0.386561), REAL(-0.625221), REAL(-0.216870),
+	REAL(0.387086), REAL(-0.630883), REAL(-0.346073),
+	REAL(0.380021), REAL(-0.596021), REAL(-0.318679),
+	REAL(0.291269), REAL(-0.619007), REAL(-0.585707),
+	REAL(0.339280), REAL(-0.571198), REAL(-0.461946),
+	REAL(0.400045), REAL(-0.489778), REAL(-0.422640),
+	REAL(0.406817), REAL(-0.314349), REAL(-0.371230),
+	REAL(0.300588), REAL(-0.281718), REAL(-0.170549),
+	REAL(0.290866), REAL(-0.277304), REAL(-0.061905),
+	REAL(0.187735), REAL(-0.241545), REAL(0.509437),
+	REAL(0.188032), REAL(-0.287569), REAL(0.424234),
+	REAL(0.227520), REAL(-0.373262), REAL(0.293102),
+	REAL(0.266526), REAL(-0.273650), REAL(0.039597),
+	REAL(0.291592), REAL(-0.291676), REAL(0.111386),
+	REAL(0.291914), REAL(-0.122741), REAL(0.422683),
+	REAL(0.297574), REAL(-0.156119), REAL(0.373368),
+	REAL(0.286603), REAL(-0.232731), REAL(0.027162),
+	REAL(0.364663), REAL(-0.201399), REAL(0.206850),
+	REAL(0.353855), REAL(-0.132408), REAL(0.149228),
+	REAL(0.282208), REAL(-0.019715), REAL(0.314960),
+	REAL(0.331187), REAL(-0.099266), REAL(0.092701),
+	REAL(0.375463), REAL(-0.093120), REAL(-0.006467),
+	REAL(0.375917), REAL(-0.101236), REAL(-0.154882),
+	REAL(0.466635), REAL(-0.094416), REAL(-0.305669),
+	REAL(0.455805), REAL(-0.119881), REAL(-0.460632),
+	REAL(0.277465), REAL(-0.604242), REAL(-0.651871),
+	REAL(0.261022), REAL(-0.551176), REAL(-0.554667),
+	REAL(0.093627), REAL(0.258494), REAL(-0.920589),
+	REAL(0.114248), REAL(0.310608), REAL(-0.798070),
+	REAL(0.144232), REAL(0.211434), REAL(-0.835001),
+	REAL(0.119916), REAL(0.176940), REAL(-0.951159),
+	REAL(0.184061), REAL(0.101854), REAL(-0.918220),
+	REAL(0.092431), REAL(0.276521), REAL(-0.738231),
+	REAL(0.133504), REAL(0.218403), REAL(-0.758602),
+	REAL(0.194987), REAL(0.097655), REAL(-0.812476),
+	REAL(0.185542), REAL(0.011005), REAL(-0.879202),
+	REAL(0.230315), REAL(-0.127450), REAL(-0.884202),
+	REAL(0.260471), REAL(0.255056), REAL(-0.624378),
+	REAL(0.351567), REAL(-0.042194), REAL(-0.663976),
+	REAL(0.253742), REAL(0.323524), REAL(-0.433716),
+	REAL(0.411612), REAL(0.132299), REAL(-0.438264),
+	REAL(0.270513), REAL(0.356530), REAL(-0.289984),
+	REAL(0.422146), REAL(0.162819), REAL(-0.273130),
+	REAL(0.164724), REAL(0.237490), REAL(0.208912),
+	REAL(0.253806), REAL(0.092900), REAL(0.240640),
+	REAL(0.203608), REAL(0.284597), REAL(0.096223),
+	REAL(0.241006), REAL(0.343093), REAL(-0.171396),
+	REAL(0.356076), REAL(0.149288), REAL(-0.143443),
+	REAL(0.337656), REAL(0.131992), REAL(0.066374)
+};
+
+int Indices[IndexCount / 3][3] = {
+	{126,134,133},
+	{342,138,134},
+	{133,134,138},
+	{126,342,134},
+	{312,316,317},
+	{169,163,162},
+	{312,317,319},
+	{312,319,318},
+	{169,162,164},
+	{169,168,163},
+	{312,314,315},
+	{169,164,165},
+	{169,167,168},
+	{312,315,316},
+	{312,313,314},
+	{169,165,166},
+	{169,166,167},
+	{312,318,313},
+	{308,304,305},
+	{308,305,306},
+	{179,181,188},
+	{177,173,175},
+	{177,175,176},
+	{302,293,300},
+	{322,294,304},
+	{188,176,175},
+	{188,175,179},
+	{158,177,187},
+	{305,293,302},
+	{305,302,306},
+	{322,304,308},
+	{188,181,183},
+	{158,173,177},
+	{293,298,300},
+	{304,294,296},
+	{304,296,305},
+	{185,176,188},
+	{185,188,183},
+	{187,177,176},
+	{187,176,185},
+	{305,296,298},
+	{305,298,293},
+	{436,432, 28},
+	{436, 28, 23},
+	{434,278,431},
+	{ 30,208,209},
+	{ 30,209, 29},
+	{ 19, 20, 24},
+	{208,207,211},
+	{208,211,209},
+	{ 19,210,212},
+	{433,434,431},
+	{433,431,432},
+	{433,432,436},
+	{436,437,433},
+	{277,275,276},
+	{277,276,278},
+	{209,210, 25},
+	{ 21, 26, 24},
+	{ 21, 24, 20},
+	{ 25, 26, 27},
+	{ 25, 27, 29},
+	{435,439,277},
+	{439,275,277},
+	{432,431, 30},
+	{432, 30, 28},
+	{433,437,438},
+	{433,438,435},
+	{434,277,278},
+	{ 24, 25,210},
+	{ 24, 26, 25},
+	{ 29, 27, 28},
+	{ 29, 28, 30},
+	{ 19, 24,210},
+	{208, 30,431},
+	{208,431,278},
+	{435,434,433},
+	{435,277,434},
+	{ 25, 29,209},
+	{ 27, 22, 23},
+	{ 27, 23, 28},
+	{ 26, 22, 27},
+	{ 26, 21, 22},
+	{212,210,209},
+	{212,209,211},
+	{207,208,278},
+	{207,278,276},
+	{439,435,438},
+	{ 12,  9, 10},
+	{ 12, 10, 13},
+	{  2,  3,  5},
+	{  2,  5,  4},
+	{ 16, 13, 14},
+	{ 16, 14, 17},
+	{ 22, 21, 16},
+	{ 13, 10, 11},
+	{ 13, 11, 14},
+	{  1,  0,  3},
+	{  1,  3,  2},
+	{ 15, 12, 16},
+	{ 19, 18, 15},
+	{ 19, 15, 16},
+	{ 19, 16, 20},
+	{  9,  1,  2},
+	{  9,  2, 10},
+	{  3,  7,  8},
+	{  3,  8,  5},
+	{ 16, 17, 23},
+	{ 16, 23, 22},
+	{ 21, 20, 16},
+	{ 10,  2,  4},
+	{ 10,  4, 11},
+	{  0,  6,  7},
+	{  0,  7,  3},
+	{ 12, 13, 16},
+	{451,446,445},
+	{451,445,450},
+	{442,440,439},
+	{442,439,438},
+	{442,438,441},
+	{421,420,422},
+	{412,411,426},
+	{412,426,425},
+	{408,405,407},
+	{413, 67, 68},
+	{413, 68,414},
+	{391,390,412},
+	{ 80,384,386},
+	{404,406,378},
+	{390,391,377},
+	{390,377, 88},
+	{400,415,375},
+	{398,396,395},
+	{398,395,371},
+	{398,371,370},
+	{112,359,358},
+	{112,358,113},
+	{351,352,369},
+	{125,349,348},
+	{345,343,342},
+	{342,340,339},
+	{341,335,337},
+	{328,341,327},
+	{331,323,333},
+	{331,322,323},
+	{327,318,319},
+	{327,319,328},
+	{315,314,324},
+	{302,300,301},
+	{302,301,303},
+	{320,311,292},
+	{285,284,289},
+	{310,307,288},
+	{310,288,290},
+	{321,350,281},
+	{321,281,282},
+	{423,448,367},
+	{272,273,384},
+	{272,384,274},
+	{264,265,382},
+	{264,382,383},
+	{440,442,261},
+	{440,261,263},
+	{252,253,254},
+	{252,254,251},
+	{262,256,249},
+	{262,249,248},
+	{228,243,242},
+	{228, 31,243},
+	{213,215,238},
+	{213,238,237},
+	{ 19,212,230},
+	{224,225,233},
+	{224,233,231},
+	{217,218, 56},
+	{217, 56, 54},
+	{217,216,239},
+	{217,239,238},
+	{217,238,215},
+	{218,217,215},
+	{218,215,214},
+	{  6,102,206},
+	{186,199,200},
+	{197,182,180},
+	{170,171,157},
+	{201,200,189},
+	{170,190,191},
+	{170,191,192},
+	{175,174,178},
+	{175,178,179},
+	{168,167,155},
+	{122,149,158},
+	{122,158,159},
+	{135,153,154},
+	{135,154,118},
+	{143,140,141},
+	{143,141,144},
+	{132,133,136},
+	{130,126,133},
+	{124,125,127},
+	{122,101,100},
+	{122,100,121},
+	{110,108,107},
+	{110,107,109},
+	{ 98, 99, 97},
+	{ 98, 97, 64},
+	{ 98, 64, 66},
+	{ 87, 55, 57},
+	{ 83, 82, 79},
+	{ 83, 79, 84},
+	{ 78, 74, 50},
+	{ 49, 71, 41},
+	{ 49, 41, 37},
+	{ 49, 37, 36},
+	{ 58, 44, 60},
+	{ 60, 59, 58},
+	{ 51, 34, 33},
+	{ 39, 40, 42},
+	{ 39, 42, 38},
+	{243,240, 33},
+	{243, 33,229},
+	{ 39, 38,  6},
+	{ 44, 46, 40},
+	{ 55, 56, 57},
+	{ 64, 62, 65},
+	{ 64, 65, 66},
+	{ 41, 71, 45},
+	{ 75, 50, 51},
+	{ 81, 79, 82},
+	{ 77, 88, 73},
+	{ 93, 92, 94},
+	{ 68, 47, 46},
+	{ 96, 97, 99},
+	{ 96, 99, 95},
+	{110,109,111},
+	{111,112,110},
+	{114,113,123},
+	{114,123,124},
+	{132,131,129},
+	{133,137,136},
+	{135,142,145},
+	{145,152,135},
+	{149,147,157},
+	{157,158,149},
+	{164,150,151},
+	{153,163,168},
+	{153,168,154},
+	{185,183,182},
+	{185,182,184},
+	{161,189,190},
+	{200,199,191},
+	{200,191,190},
+	{180,178,195},
+	{180,195,196},
+	{102,101,204},
+	{102,204,206},
+	{ 43, 48,104},
+	{ 43,104,103},
+	{216,217, 54},
+	{216, 54, 32},
+	{207,224,231},
+	{230,212,211},
+	{230,211,231},
+	{227,232,241},
+	{227,241,242},
+	{235,234,241},
+	{235,241,244},
+	{430,248,247},
+	{272,274,253},
+	{272,253,252},
+	{439,260,275},
+	{225,224,259},
+	{225,259,257},
+	{269,270,407},
+	{269,407,405},
+	{270,269,273},
+	{270,273,272},
+	{273,269,268},
+	{273,268,267},
+	{273,267,266},
+	{273,266,265},
+	{273,265,264},
+	{448,279,367},
+	{281,350,368},
+	{285,286,301},
+	{290,323,310},
+	{290,311,323},
+	{282,281,189},
+	{292,311,290},
+	{292,290,291},
+	{307,306,302},
+	{307,302,303},
+	{316,315,324},
+	{316,324,329},
+	{331,351,350},
+	{330,334,335},
+	{330,335,328},
+	{341,337,338},
+	{344,355,354},
+	{346,345,348},
+	{346,348,347},
+	{364,369,352},
+	{364,352,353},
+	{365,363,361},
+	{365,361,362},
+	{376,401,402},
+	{373,372,397},
+	{373,397,400},
+	{376, 92,377},
+	{381,378,387},
+	{381,387,385},
+	{386, 77, 80},
+	{390,389,412},
+	{416,417,401},
+	{403,417,415},
+	{408,429,430},
+	{419,423,418},
+	{427,428,444},
+	{427,444,446},
+	{437,436,441},
+	{450,445, 11},
+	{450, 11,  4},
+	{447,449,  5},
+	{447,  5,  8},
+	{441,438,437},
+	{425,426,451},
+	{425,451,452},
+	{417,421,415},
+	{408,407,429},
+	{399,403,400},
+	{399,400,397},
+	{394,393,416},
+	{389,411,412},
+	{386,383,385},
+	{408,387,378},
+	{408,378,406},
+	{377,391,376},
+	{ 94,375,415},
+	{372,373,374},
+	{372,374,370},
+	{359,111,360},
+	{359,112,111},
+	{113,358,349},
+	{113,349,123},
+	{346,343,345},
+	{343,340,342},
+	{338,336,144},
+	{338,144,141},
+	{327,341,354},
+	{327,354,326},
+	{331,350,321},
+	{331,321,322},
+	{314,313,326},
+	{314,326,325},
+	{300,298,299},
+	{300,299,301},
+	{288,287,289},
+	{189,292,282},
+	{287,288,303},
+	{284,285,297},
+	{368,280,281},
+	{448,447,279},
+	{274,226,255},
+	{267,268,404},
+	{267,404,379},
+	{429,262,430},
+	{439,440,260},
+	{257,258,249},
+	{257,249,246},
+	{430,262,248},
+	{234,228,242},
+	{234,242,241},
+	{237,238,239},
+	{237,239,236},
+	{ 15, 18,227},
+	{ 15,227,229},
+	{222,223, 82},
+	{222, 82, 83},
+	{214,215,213},
+	{214,213, 81},
+	{ 38,102,  6},
+	{122,159,200},
+	{122,200,201},
+	{174,171,192},
+	{174,192,194},
+	{197,193,198},
+	{190,170,161},
+	{181,179,178},
+	{181,178,180},
+	{166,156,155},
+	{163,153,152},
+	{163,152,162},
+	{120,156,149},
+	{120,149,121},
+	{152,153,135},
+	{140,143,142},
+	{135,131,132},
+	{135,132,136},
+	{130,129,128},
+	{130,128,127},
+	{100,105,119},
+	{100,119,120},
+	{106,104,107},
+	{106,107,108},
+	{ 91, 95, 59},
+	{ 93, 94, 68},
+	{ 91, 89, 92},
+	{ 76, 53, 55},
+	{ 76, 55, 87},
+	{ 81, 78, 79},
+	{ 74, 73, 49},
+	{ 69, 60, 45},
+	{ 58, 62, 64},
+	{ 58, 64, 61},
+	{ 53, 31, 32},
+	{ 32, 54, 53},
+	{ 42, 43, 38},
+	{ 35, 36,  0},
+	{ 35,  0,  1},
+	{ 34, 35,  1},
+	{ 34,  1,  9},
+	{ 44, 40, 41},
+	{ 44, 41, 45},
+	{ 33,240, 51},
+	{ 63, 62, 58},
+	{ 63, 58, 59},
+	{ 45, 71, 70},
+	{ 76, 75, 51},
+	{ 76, 51, 52},
+	{ 86, 85, 84},
+	{ 86, 84, 87},
+	{ 89, 72, 73},
+	{ 89, 73, 88},
+	{ 91, 92, 96},
+	{ 91, 96, 95},
+	{ 72, 91, 60},
+	{ 72, 60, 69},
+	{104,106,105},
+	{119,105,117},
+	{119,117,118},
+	{124,127,128},
+	{117,116,129},
+	{117,129,131},
+	{118,117,131},
+	{135,140,142},
+	{146,150,152},
+	{146,152,145},
+	{149,122,121},
+	{166,165,151},
+	{166,151,156},
+	{158,172,173},
+	{161,160,189},
+	{199,198,193},
+	{199,193,191},
+	{204,201,202},
+	{178,174,194},
+	{200,159,186},
+	{109, 48, 67},
+	{ 48,107,104},
+	{216, 32,236},
+	{216,236,239},
+	{223,214, 81},
+	{223, 81, 82},
+	{ 33, 12, 15},
+	{ 32,228,234},
+	{ 32,234,236},
+	{240, 31, 52},
+	{256,255,246},
+	{256,246,249},
+	{258,263,248},
+	{258,248,249},
+	{275,260,259},
+	{275,259,276},
+	{207,276,259},
+	{270,271,429},
+	{270,429,407},
+	{413,418,366},
+	{413,366,365},
+	{368,367,279},
+	{368,279,280},
+	{303,301,286},
+	{303,286,287},
+	{283,282,292},
+	{283,292,291},
+	{320,292,189},
+	{298,296,297},
+	{298,297,299},
+	{318,327,326},
+	{318,326,313},
+	{329,330,317},
+	{336,333,320},
+	{326,354,353},
+	{334,332,333},
+	{334,333,336},
+	{342,339,139},
+	{342,139,138},
+	{345,342,126},
+	{347,357,356},
+	{369,368,351},
+	{363,356,357},
+	{363,357,361},
+	{366,367,368},
+	{366,368,369},
+	{375,373,400},
+	{ 92, 90,377},
+	{409,387,408},
+	{386,385,387},
+	{386,387,388},
+	{412,394,391},
+	{396,398,399},
+	{408,406,405},
+	{415,421,419},
+	{415,419,414},
+	{425,452,448},
+	{425,448,424},
+	{444,441,443},
+	{448,452,449},
+	{448,449,447},
+	{446,444,443},
+	{446,443,445},
+	{250,247,261},
+	{250,261,428},
+	{421,422,423},
+	{421,423,419},
+	{427,410,250},
+	{417,403,401},
+	{403,402,401},
+	{420,392,412},
+	{420,412,425},
+	{420,425,424},
+	{386,411,389},
+	{383,382,381},
+	{383,381,385},
+	{378,379,404},
+	{372,371,395},
+	{372,395,397},
+	{371,372,370},
+	{361,359,360},
+	{361,360,362},
+	{368,350,351},
+	{349,347,348},
+	{356,355,344},
+	{356,344,346},
+	{344,341,340},
+	{344,340,343},
+	{338,337,336},
+	{328,335,341},
+	{324,352,351},
+	{324,351,331},
+	{320,144,336},
+	{314,325,324},
+	{322,308,309},
+	{310,309,307},
+	{287,286,289},
+	{203,280,279},
+	{203,279,205},
+	{297,295,283},
+	{297,283,284},
+	{447,205,279},
+	{274,384, 80},
+	{274, 80,226},
+	{266,267,379},
+	{266,379,380},
+	{225,257,246},
+	{225,246,245},
+	{256,254,253},
+	{256,253,255},
+	{430,247,250},
+	{226,235,244},
+	{226,244,245},
+	{232,233,244},
+	{232,244,241},
+	{230, 18, 19},
+	{ 32, 31,228},
+	{219,220, 86},
+	{219, 86, 57},
+	{226,213,235},
+	{206,  7,  6},
+	{122,201,101},
+	{201,204,101},
+	{180,196,197},
+	{170,192,171},
+	{200,190,189},
+	{194,193,195},
+	{183,181,180},
+	{183,180,182},
+	{155,154,168},
+	{149,156,151},
+	{149,151,148},
+	{155,156,120},
+	{145,142,143},
+	{145,143,146},
+	{136,137,140},
+	{133,132,130},
+	{128,129,116},
+	{100,120,121},
+	{110,112,113},
+	{110,113,114},
+	{ 66, 65, 63},
+	{ 66, 63, 99},
+	{ 66, 99, 98},
+	{ 96, 46, 61},
+	{ 89, 88, 90},
+	{ 86, 87, 57},
+	{ 80, 78, 81},
+	{ 72, 69, 49},
+	{ 67, 48, 47},
+	{ 67, 47, 68},
+	{ 56, 55, 53},
+	{ 50, 49, 36},
+	{ 50, 36, 35},
+	{ 40, 39, 41},
+	{242,243,229},
+	{242,229,227},
+	{  6, 37, 39},
+	{ 42, 47, 48},
+	{ 42, 48, 43},
+	{ 61, 46, 44},
+	{ 45, 70, 69},
+	{ 69, 70, 71},
+	{ 69, 71, 49},
+	{ 74, 78, 77},
+	{ 83, 84, 85},
+	{ 73, 74, 77},
+	{ 93, 96, 92},
+	{ 68, 46, 93},
+	{ 95, 99, 63},
+	{ 95, 63, 59},
+	{115,108,110},
+	{115,110,114},
+	{125,126,127},
+	{129,130,132},
+	{137,133,138},
+	{137,138,139},
+	{148,146,143},
+	{148,143,147},
+	{119,118,154},
+	{161,147,143},
+	{165,164,151},
+	{158,157,171},
+	{158,171,172},
+	{159,158,187},
+	{159,187,186},
+	{194,192,191},
+	{194,191,193},
+	{189,202,201},
+	{182,197,184},
+	{205,  8,  7},
+	{ 48,109,107},
+	{218,219, 57},
+	{218, 57, 56},
+	{207,231,211},
+	{232,230,231},
+	{232,231,233},
+	{ 53, 52, 31},
+	{388,411,386},
+	{409,430,250},
+	{262,429,254},
+	{262,254,256},
+	{442,444,428},
+	{273,264,383},
+	{273,383,384},
+	{429,271,251},
+	{429,251,254},
+	{413,365,362},
+	{ 67,413,360},
+	{282,283,295},
+	{285,301,299},
+	{202,281,280},
+	{284,283,291},
+	{284,291,289},
+	{320,189,160},
+	{308,306,307},
+	{307,309,308},
+	{319,317,330},
+	{319,330,328},
+	{353,352,324},
+	{332,331,333},
+	{340,341,338},
+	{354,341,344},
+	{349,358,357},
+	{349,357,347},
+	{364,355,356},
+	{364,356,363},
+	{364,365,366},
+	{364,366,369},
+	{374,376,402},
+	{375, 92,373},
+	{ 77,389,390},
+	{382,380,381},
+	{389, 77,386},
+	{393,394,412},
+	{393,412,392},
+	{401,394,416},
+	{415,400,403},
+	{411,410,427},
+	{411,427,426},
+	{422,420,424},
+	{247,248,263},
+	{247,263,261},
+	{445,443, 14},
+	{445, 14, 11},
+	{449,450,  4},
+	{449,  4,  5},
+	{443,441, 17},
+	{443, 17, 14},
+	{436, 23, 17},
+	{436, 17,441},
+	{424,448,422},
+	{448,423,422},
+	{414,419,418},
+	{414,418,413},
+	{406,404,405},
+	{399,397,395},
+	{399,395,396},
+	{420,416,392},
+	{388,410,411},
+	{386,384,383},
+	{390, 88, 77},
+	{375, 94, 92},
+	{415,414, 68},
+	{415, 68, 94},
+	{370,374,402},
+	{370,402,398},
+	{361,357,358},
+	{361,358,359},
+	{125,348,126},
+	{346,344,343},
+	{340,338,339},
+	{337,335,334},
+	{337,334,336},
+	{325,353,324},
+	{324,331,332},
+	{324,332,329},
+	{323,322,309},
+	{323,309,310},
+	{294,295,297},
+	{294,297,296},
+	{289,286,285},
+	{202,280,203},
+	{288,307,303},
+	{282,295,321},
+	{ 67,360,111},
+	{418,423,367},
+	{418,367,366},
+	{272,252,251},
+	{272,251,271},
+	{272,271,270},
+	{255,253,274},
+	{265,266,380},
+	{265,380,382},
+	{442,428,261},
+	{440,263,258},
+	{440,258,260},
+	{409,250,410},
+	{255,226,245},
+	{255,245,246},
+	{ 31,240,243},
+	{236,234,235},
+	{236,235,237},
+	{233,225,245},
+	{233,245,244},
+	{220,221, 85},
+	{220, 85, 86},
+	{ 81,213,226},
+	{ 81,226, 80},
+	{  7,206,205},
+	{186,184,198},
+	{186,198,199},
+	{204,203,205},
+	{204,205,206},
+	{195,193,196},
+	{171,174,172},
+	{173,174,175},
+	{173,172,174},
+	{155,167,166},
+	{160,161,143},
+	{160,143,144},
+	{119,154,155},
+	{148,151,150},
+	{148,150,146},
+	{140,137,139},
+	{140,139,141},
+	{127,126,130},
+	{114,124,128},
+	{114,128,115},
+	{117,105,106},
+	{117,106,116},
+	{104,105,100},
+	{104,100,103},
+	{ 59, 60, 91},
+	{ 97, 96, 61},
+	{ 97, 61, 64},
+	{ 91, 72, 89},
+	{ 87, 84, 79},
+	{ 87, 79, 76},
+	{ 78, 80, 77},
+	{ 49, 50, 74},
+	{ 60, 44, 45},
+	{ 61, 44, 58},
+	{ 51, 50, 35},
+	{ 51, 35, 34},
+	{ 39, 37, 41},
+	{ 33, 34,  9},
+	{ 33,  9, 12},
+	{  0, 36, 37},
+	{  0, 37,  6},
+	{ 40, 46, 47},
+	{ 40, 47, 42},
+	{ 53, 54, 56},
+	{ 65, 62, 63},
+	{ 72, 49, 73},
+	{ 79, 78, 75},
+	{ 79, 75, 76},
+	{ 52, 53, 76},
+	{ 92, 89, 90},
+	{ 96, 93, 46},
+	{102,103,100},
+	{102,100,101},
+	{116,106,108},
+	{116,108,115},
+	{123,125,124},
+	{116,115,128},
+	{118,131,135},
+	{140,135,136},
+	{148,147,149},
+	{120,119,155},
+	{164,162,152},
+	{164,152,150},
+	{157,147,161},
+	{157,161,170},
+	{186,187,185},
+	{186,185,184},
+	{193,197,196},
+	{202,203,204},
+	{194,195,178},
+	{198,184,197},
+	{ 67,111,109},
+	{ 38, 43,103},
+	{ 38,103,102},
+	{214,223,222},
+	{214,222,221},
+	{214,221,220},
+	{214,220,219},
+	{214,219,218},
+	{213,237,235},
+	{221,222, 83},
+	{221, 83, 85},
+	{ 15,229, 33},
+	{227, 18,230},
+	{227,230,232},
+	{ 52, 51,240},
+	{ 75, 78, 50},
+	{408,430,409},
+	{260,258,257},
+	{260,257,259},
+	{224,207,259},
+	{268,269,405},
+	{268,405,404},
+	{413,362,360},
+	{447,  8,205},
+	{299,297,285},
+	{189,281,202},
+	{290,288,289},
+	{290,289,291},
+	{322,321,295},
+	{322,295,294},
+	{333,323,311},
+	{333,311,320},
+	{317,316,329},
+	{320,160,144},
+	{353,325,326},
+	{329,332,334},
+	{329,334,330},
+	{339,338,141},
+	{339,141,139},
+	{348,345,126},
+	{347,356,346},
+	{123,349,125},
+	{364,353,354},
+	{364,354,355},
+	{365,364,363},
+	{376,391,394},
+	{376,394,401},
+	{ 92,376,374},
+	{ 92,374,373},
+	{377, 90, 88},
+	{380,379,378},
+	{380,378,381},
+	{388,387,409},
+	{388,409,410},
+	{416,393,392},
+	{399,398,402},
+	{399,402,403},
+	{250,428,427},
+	{421,417,416},
+	{421,416,420},
+	{426,427,446},
+	{426,446,451},
+	{444,442,441},
+	{452,451,450},
+	{452,450,449}
+};
+
+//============================
+
+
+dReal heightfield_callback( void* pUserData, int x, int z )
+{
+	dIASSERT( x < HFIELD_WSTEP );
+	dIASSERT( z < HFIELD_DSTEP );
+
+	dReal fx = ( ((dReal)x) - ( HFIELD_WSTEP-1 )/2 ) / (dReal)( HFIELD_WSTEP-1 );
+	dReal fz = ( ((dReal)z) - ( HFIELD_DSTEP-1 )/2 ) / (dReal)( HFIELD_DSTEP-1 );
+
+	// Create an interesting 'hump' shape
+	dReal h = REAL( 1.0 ) + ( REAL( -16.0 ) * ( fx*fx*fx + fz*fz*fz ) );
+
+	return h;
+}
+
+
+
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+  // if (o1->body && o2->body) return;
+
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+
+  dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
+  for (i=0; i<MAX_CONTACTS; i++) {
+    contact[i].surface.mode = dContactBounce | dContactSoftCFM;
+    contact[i].surface.mu = dInfinity;
+    contact[i].surface.mu2 = 0;
+    contact[i].surface.bounce = 0.1;
+    contact[i].surface.bounce_vel = 0.1;
+    contact[i].surface.soft_cfm = 0.01;
+  }
+  if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
+			   sizeof(dContact))) {
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    const dReal ss[3] = {0.02,0.02,0.02};
+    for (i=0; i<numc; i++) {
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+      if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("To drop another object, press:\n");
+  printf ("   b for box.\n");
+  printf ("   s for sphere.\n");
+  printf ("   c for capsule.\n");
+  printf ("   y for cylinder.\n");
+  printf ("   v for a convex object.\n");
+  printf ("   x for a composite object.\n");
+  printf ("   m for a trimesh.\n");
+  printf ("To select an object, press space.\n");
+  printf ("To disable the selected object, press d.\n");
+  printf ("To enable the selected object, press e.\n");
+  printf ("To toggle showing the geom AABBs, press a.\n");
+  printf ("To toggle showing the contact points, press t.\n");
+  printf ("To toggle dropping from random position/orientation, press r.\n");
+  printf ("To save the current state to 'state.dif', press 1.\n");
+}
+
+
+char locase (char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+  else return c;
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+	size_t i;
+	int j,k;
+	dReal sides[3];
+	dMass m;
+
+	cmd = locase (cmd);
+
+
+	//
+	// Geom Creation
+	//
+
+	if ( cmd == 'b' || cmd == 's' || cmd == 'c' || 
+		 cmd == 'x' || cmd == 'y' || cmd == 'm' || cmd == 'v' )
+	{
+		if ( num < NUM )
+		{
+			i = num;
+			num++;
+		}
+		else
+		{
+			i = nextobj;
+			nextobj++;
+			if (nextobj >= num) nextobj = 0;
+
+			// destroy the body and geoms for slot i
+			dBodyDestroy (obj[i].body);
+			for (k=0; k < GPB; k++)
+			{
+				if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+			}
+			memset (&obj[i],0,sizeof(obj[i]));
+		}
+
+		obj[i].body = dBodyCreate (world);
+		for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+		dMatrix3 R;
+		if (random_pos) {
+			dBodySetPosition (obj[i].body,
+				(dRandReal()-0.5)*HFIELD_WIDTH*0.75,
+				(dRandReal()-0.5)*HFIELD_DEPTH*0.75,
+				dRandReal() + 2 );
+			dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+				dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+		}
+		else {
+			dReal maxheight = 0;
+			for (k=0; k<num; k++) {
+				const dReal *pos = dBodyGetPosition (obj[k].body);
+				if (pos[2] > maxheight) maxheight = pos[2];
+			}
+			dBodySetPosition (obj[i].body, 0,maxheight+1,0);
+			dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
+		}
+		dBodySetRotation (obj[i].body,R);
+		dBodySetData (obj[i].body,(void*) i);
+
+		if (cmd == 'b')
+		{
+			dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+			obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+		}
+		else if (cmd == 'c')
+		{
+			sides[0] *= 0.5;
+			dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+			obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
+		}
+		//<---- Convex Object
+		else if (cmd == 'v')
+		{
+			dMassSetBox (&m,DENSITY,0.25,0.25,0.25);
+			obj[i].geom[0] = dCreateConvex (space,
+				planes,
+				planecount,
+				points,
+				pointcount,
+				polygons);
+		}
+		//----> Convex Object
+		else if (cmd == 'y')
+		{
+			dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
+			obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
+		}
+		else if (cmd == 's')
+		{
+			sides[0] *= 0.5;
+			dMassSetSphere (&m,DENSITY,sides[0]);
+			obj[i].geom[0] = dCreateSphere (space,sides[0]);
+		}
+#ifdef dTRIMESH_ENABLED
+		else if (cmd == 'm')
+		{
+			dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate();
+			dGeomTriMeshDataBuildSingle(new_tmdata, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
+
+			obj[i].geom[0] = dCreateTriMesh(space, new_tmdata, 0, 0, 0);
+
+			// remember the mesh's dTriMeshDataID on its userdata for convenience.
+			dGeomSetData(obj[i].geom[0], new_tmdata);
+
+			dMassSetTrimesh( &m, DENSITY, obj[i].geom[0] );
+		}
+#endif
+		else if (cmd == 'x')
+		{
+			dGeomID g2[GPB];		// encapsulated geometries
+			dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+			// start accumulating masses for the encapsulated geometries
+			dMass m2;
+			dMassSetZero (&m);
+
+			// set random delta positions
+			for (j=0; j<GPB; j++) {
+				for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+			}
+
+			for (k=0; k<GPB; k++) {
+				obj[i].geom[k] = dCreateGeomTransform (space);
+				dGeomTransformSetCleanup (obj[i].geom[k],1);
+				if (k==0) {
+					dReal radius = dRandReal()*0.25+0.05;
+					g2[k] = dCreateSphere (0,radius);
+					dMassSetSphere (&m2,DENSITY,radius);
+				}
+				else if (k==1) {
+					g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+					dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+				}
+				else {
+					dReal radius = dRandReal()*0.1+0.05;
+					dReal length = dRandReal()*1.0+0.1;
+					g2[k] = dCreateCapsule (0,radius,length);
+					dMassSetCapsule (&m2,DENSITY,3,radius,length);
+				}
+				dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+				// set the transformation (adjust the mass too)
+				dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+				dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+				dMatrix3 Rtx;
+				dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+					dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+				dGeomSetRotation (g2[k],Rtx);
+				dMassRotate (&m2,Rtx);
+
+				// add to the total mass
+				dMassAdd (&m,&m2);
+			}
+
+			// move all encapsulated objects so that the center of mass is (0,0,0)
+			for (k=0; k<2; k++) {
+				dGeomSetPosition (g2[k],
+					dpos[k][0]-m.c[0],
+					dpos[k][1]-m.c[1],
+					dpos[k][2]-m.c[2]);
+			}
+			dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+		}
+
+		for (k=0; k < GPB; k++)
+		{
+			if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+		}
+
+		dBodySetMass (obj[i].body,&m);
+	}
+
+
+	//
+	// Control Commands
+	//
+
+	if (cmd == ' ') {
+		selected++;
+		if (selected >= num) selected = 0;
+		if (selected < 0) selected = 0;
+	}
+	else if (cmd == 'd' && selected >= 0 && selected < num) {
+		dBodyDisable (obj[selected].body);
+	}
+	else if (cmd == 'e' && selected >= 0 && selected < num) {
+		dBodyEnable (obj[selected].body);
+	}
+	else if (cmd == 'a') {
+		show_aabb ^= 1;
+	}
+	else if (cmd == 't') {
+		show_contacts ^= 1;
+	}
+	else if (cmd == 'r') {
+		random_pos ^= 1;
+	}
+	else if (cmd == '1') {
+		write_world = 1;
+	}
+}
+
+
+// draw a geom
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
+{
+  int i;
+
+  if (!g) return;
+  if (!pos) pos = dGeomGetPosition (g);
+  if (!R) R = dGeomGetRotation (g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass) {
+    dVector3 sides;
+    dGeomBoxGetLengths (g,sides);
+    dsDrawBox (pos,R,sides);
+  }
+  else if (type == dSphereClass) {
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+  }
+  else if (type == dCapsuleClass) {
+    dReal radius,length;
+    dGeomCapsuleGetParams (g,&radius,&length);
+    dsDrawCapsule (pos,R,length,radius);
+  }
+  //<---- Convex Object
+  else if (type == dConvexClass)
+    {
+      //dVector3 sides={0.50,0.50,0.50};
+      dsDrawConvex(pos,R,planes,
+		   planecount,
+		   points,
+		   pointcount,
+		   polygons);
+    }
+  //----> Convex Object
+  else if (type == dCylinderClass) {
+    dReal radius,length;
+    dGeomCylinderGetParams (g,&radius,&length);
+    dsDrawCylinder (pos,R,length,radius);
+  }
+  else if (type == dGeomTransformClass) {
+    dGeomID g2 = dGeomTransformGetGeom (g);
+    const dReal *pos2 = dGeomGetPosition (g2);
+    const dReal *R2 = dGeomGetRotation (g2);
+    dVector3 actual_pos;
+    dMatrix3 actual_R;
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+    actual_pos[0] += pos[0];
+    actual_pos[1] += pos[1];
+    actual_pos[2] += pos[2];
+    dMULTIPLY0_333 (actual_R,R,R2);
+    drawGeom (g2,actual_pos,actual_R,0);
+  }
+
+  if (show_aabb) {
+    // draw the bounding box for this geom
+    dReal aabb[6];
+    dGeomGetAABB (g,aabb);
+    dVector3 bbpos;
+    for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+    dVector3 bbsides;
+    for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    dsSetColorAlpha (1,0,0,0.5);
+    dsDrawBox (bbpos,RI,bbsides);
+  }
+
+}
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i,j;
+  
+  dsSetColor (0,0,2);
+  
+  dSpaceCollide (space,0,&nearCallback);
+  
+  //if (!pause) dWorldStep (world,0.05);
+  //if (!pause) dWorldQuickStep (world,0.05);
+  if (!pause) dWorldStepFast1 (world,0.05, 5);
+
+
+  if (write_world) {
+    FILE *f = fopen ("state.dif","wt");
+    if (f) {
+      dWorldExportDIF (world,f,"X");
+      fclose (f);
+    }
+    write_world = 0;
+  }
+
+  // remove all contact joints
+  dJointGroupEmpty (contactgroup);
+
+
+
+	const dReal* pReal = dGeomGetPosition( gheight );
+
+	const dReal* RReal = dGeomGetRotation( gheight );
+
+	//
+	// Draw Heightfield
+	//
+
+	// Set ox and oz to zero for DHEIGHTFIELD_CORNER_ORIGIN mode.
+	int ox = (int) ( -HFIELD_WIDTH/2 );
+	int oz = (int) ( -HFIELD_DEPTH/2 );
+
+//	for ( int tx = -1; tx < 2; ++tx )
+//	for ( int tz = -1; tz < 2; ++tz )
+	{
+		dsSetColorAlpha (0.5,1,0.5,0.5);
+		dsSetTexture( DS_WOOD );
+
+		for ( int i = 0; i < HFIELD_WSTEP - 1; ++i )
+		for ( int j = 0; j < HFIELD_DSTEP - 1; ++j )
+		{
+			dReal a[3], b[3], c[3], d[3];
+
+			a[ 0 ] = ox + ( i ) * HFIELD_WSAMP;
+			a[ 1 ] = heightfield_callback( NULL, i, j );
+			a[ 2 ] = oz + ( j ) * HFIELD_DSAMP;
+
+			b[ 0 ] = ox + ( i + 1 ) * HFIELD_WSAMP;
+			b[ 1 ] = heightfield_callback( NULL, i + 1, j );
+			b[ 2 ] = oz + ( j ) * HFIELD_DSAMP;
+
+			c[ 0 ] = ox + ( i ) * HFIELD_WSAMP;
+			c[ 1 ] = heightfield_callback( NULL, i, j + 1 );
+			c[ 2 ] = oz + ( j + 1 ) * HFIELD_DSAMP;
+
+			d[ 0 ] = ox + ( i + 1 ) * HFIELD_WSAMP;
+			d[ 1 ] = heightfield_callback( NULL, i + 1, j + 1 );
+			d[ 2 ] = oz + ( j + 1 ) * HFIELD_DSAMP;
+
+			dsDrawTriangle( pReal, RReal, a, c, b, 1 );
+			dsDrawTriangle( pReal, RReal, b, c, d, 1 );
+		}
+	}
+
+
+
+
+
+	dsSetColor (1,1,0);
+	dsSetTexture (DS_WOOD);
+	for (i=0; i<num; i++)
+	{
+		for (j=0; j < GPB; j++)
+		{
+			if (i==selected)
+			{
+				dsSetColor (0,0.7,1);
+			}
+			else if (! dBodyIsEnabled (obj[i].body))
+			{
+				dsSetColor (1,0.8,0);
+			}
+			else 
+			{
+				dsSetColor (1,1,0);
+			}
+
+
+			if ( obj[i].geom[j] && dGeomGetClass(obj[i].geom[j]) == dTriMeshClass )
+			{
+				int* Indices = (int*)::Indices;
+
+				// assume all trimeshes are drawn as bunnies
+				const dReal* Pos = dGeomGetPosition(obj[i].geom[j]);
+				const dReal* Rot = dGeomGetRotation(obj[i].geom[j]);
+
+				for (int ii = 0; ii < IndexCount / 3; ii++)
+				{
+					const dReal v[9] = { // explicit conversion from float to dReal
+						Vertices[Indices[ii * 3 + 0] * 3 + 0],
+							Vertices[Indices[ii * 3 + 0] * 3 + 1],
+							Vertices[Indices[ii * 3 + 0] * 3 + 2],
+							Vertices[Indices[ii * 3 + 1] * 3 + 0],
+							Vertices[Indices[ii * 3 + 1] * 3 + 1],
+							Vertices[Indices[ii * 3 + 1] * 3 + 2],
+							Vertices[Indices[ii * 3 + 2] * 3 + 0],
+							Vertices[Indices[ii * 3 + 2] * 3 + 1],
+							Vertices[Indices[ii * 3 + 2] * 3 + 2]
+					};
+					dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 1);
+				}
+
+				// tell the tri-tri collider the current transform of the trimesh --
+				// this is fairly important for good results.
+
+				// Fill in the (4x4) matrix.
+				dReal* p_matrix = obj[i].matrix_dblbuff + ( obj[i].last_matrix_index * 16 );
+
+				p_matrix[ 0 ] = Rot[ 0 ];	p_matrix[ 1 ] = Rot[ 1 ];	p_matrix[ 2 ] = Rot[ 2 ];	p_matrix[ 3 ] = 0;
+				p_matrix[ 4 ] = Rot[ 4 ];	p_matrix[ 5 ] = Rot[ 5 ];	p_matrix[ 6 ] = Rot[ 6 ];	p_matrix[ 7 ] = 0;
+				p_matrix[ 8 ] = Rot[ 8 ];	p_matrix[ 9 ] = Rot[ 9 ];	p_matrix[10 ] = Rot[10 ];	p_matrix[11 ] = 0;
+				p_matrix[12 ] = Pos[ 0 ];	p_matrix[13 ] = Pos[ 1 ];	p_matrix[14 ] = Pos[ 2 ];	p_matrix[15 ] = 1;
+
+				// Flip to other matrix.
+				obj[i].last_matrix_index = !obj[i].last_matrix_index;
+
+				// Apply the 'other' matrix which is the oldest.
+#ifdef dTRIMESH_ENABLED
+				dGeomTriMeshSetLastTransform( obj[i].geom[j], 
+					*(dMatrix4*)( obj[i].matrix_dblbuff + ( obj[i].last_matrix_index * 16 ) ) );
+#endif
+			}
+			else
+			{
+				drawGeom (obj[i].geom[j],0,0,show_aabb);
+			}
+		}
+	}
+
+	if ( show_aabb )
+	{
+		// draw the bounding box for this geom
+		dReal aabb[6];
+		dGeomGetAABB (gheight,aabb);
+		dVector3 bbpos;
+		for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+		dVector3 bbsides;
+		for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
+		dMatrix3 RI;
+		dRSetIdentity (RI);
+		dsSetColorAlpha (1,0,0,0.5);
+		dsDrawBox (bbpos,RI,bbsides);
+	}
+}
+
+
+int main (int argc, char **argv)
+{
+	// setup pointers to drawstuff callback functions
+	dsFunctions fn;
+	fn.version = DS_VERSION;
+	fn.start = &start;
+	fn.step = &simLoop;
+	fn.command = &command;
+	fn.stop = 0;
+	fn.path_to_textures = "../../drawstuff/textures";
+	if(argc==2)
+	{
+		fn.path_to_textures = argv[1];
+	}
+
+	// create world
+	dInitODE();
+	world = dWorldCreate();
+	space = dHashSpaceCreate (0);
+	contactgroup = dJointGroupCreate (0);
+	dWorldSetGravity (world,0,0,-0.05);
+	dWorldSetCFM (world,1e-5);
+	dWorldSetAutoDisableFlag (world,1);
+	dWorldSetContactMaxCorrectingVel (world,0.1);
+	dWorldSetContactSurfaceLayer (world,0.001);
+	memset (obj,0,sizeof(obj));
+
+#if 1
+
+  dWorldSetAutoDisableAverageSamplesCount( world, 1 );
+
+#endif
+
+	// base plane to catch overspill
+	dCreatePlane( space, 0, 0, 1, 0 );
+
+
+	// our heightfield floor
+
+	dHeightfieldDataID heightid = dGeomHeightfieldDataCreate();
+
+	// Create an finite heightfield.
+	dGeomHeightfieldDataBuildCallback( heightid, NULL, heightfield_callback,
+		HFIELD_WIDTH, HFIELD_DEPTH, HFIELD_WSTEP, HFIELD_DSTEP,
+		REAL( 1.0 ), REAL( 0.0 ), REAL( 0.0 ), 0 );
+
+	// Give some very bounds which, while conservative,
+	// makes AABB computation more accurate than +/-INF.
+	dGeomHeightfieldDataSetBounds( heightid, REAL( -4.0 ), REAL( +6.0 ) );
+
+	gheight = dCreateHeightfield( space, heightid, 1 );
+
+	dVector3 pos;
+	pos[ 0 ] = 0;
+	pos[ 1 ] = 0;
+	pos[ 2 ] = 0;
+
+	// Rotate so Z is up, not Y (which is the default orientation)
+	dMatrix3 R;
+	dRSetIdentity( R );
+	dRFromAxisAndAngle( R, 1, 0, 0, DEGTORAD * 90 );
+
+	// Place it.
+	dGeomSetRotation( gheight, R );
+	dGeomSetPosition( gheight, pos[0], pos[1], pos[2] );
+
+
+
+
+	// run simulation
+	dsSimulationLoop (argc,argv,352,288,&fn);
+
+	dJointGroupDestroy (contactgroup);
+	dSpaceDestroy (space);
+	dWorldDestroy (world);
+	dCloseODE();
+	return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_hinge.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_hinge.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_hinge.cpp	(revision 216)
@@ -0,0 +1,166 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#endif
+
+
+// some constants
+#define SIDE (0.5f)	// side length of a box
+#define MASS (1.0)	// mass of a box
+
+
+// dynamics and collision objects
+static dWorldID world;
+static dBodyID body[2];
+static dJointID hinge;
+
+
+// state set by keyboard commands
+static int occasional_error = 0;
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
+  static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("Press 'e' to start/stop occasional error.\n");
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  if (cmd == 'e' || cmd == 'E') {
+    occasional_error ^= 1;
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  const dReal kd = -0.3;	// angular damping constant
+  if (!pause) {
+    // add an oscillating torque to body 0, and also damp its rotational motion
+    static dReal a=0;
+    const dReal *w = dBodyGetAngularVel (body[0]);
+    dBodyAddTorque (body[0],kd*w[0],kd*w[1]+0.1*cos(a),kd*w[2]+0.1*sin(a));
+    dWorldStep (world,0.05);
+    a += 0.01;
+
+    // occasionally re-orient one of the bodies to create a deliberate error.
+    if (occasional_error) {
+      static int count = 0;
+      if ((count % 20)==0) {
+	// randomly adjust orientation of body[0]
+	const dReal *R1;
+	dMatrix3 R2,R3;
+	R1 = dBodyGetRotation (body[0]);
+	dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5,
+			    dRandReal()-0.5,dRandReal()-0.5);
+	dMultiply0 (R3,R1,R2,3,3,3);
+	dBodySetRotation (body[0],R3);
+
+	// randomly adjust position of body[0]
+	const dReal *pos = dBodyGetPosition (body[0]);
+	dBodySetPosition (body[0],
+			  pos[0]+0.2*(dRandReal()-0.5),
+			  pos[1]+0.2*(dRandReal()-0.5),
+			  pos[2]+0.2*(dRandReal()-0.5));
+      }
+      count++;
+    }
+  }
+
+  dReal sides1[3] = {SIDE,SIDE,SIDE};
+  dReal sides2[3] = {SIDE,SIDE,SIDE*0.8f};
+  dsSetTexture (DS_WOOD);
+  dsSetColor (1,1,0);
+  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
+  dsSetColor (0,1,1);
+  dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+
+  dMass m;
+  dMassSetBox (&m,1,SIDE,SIDE,SIDE);
+  dMassAdjust (&m,MASS);
+
+  dQuaternion q;
+  dQFromAxisAndAngle (q,1,1,0,0.25*M_PI);
+
+  body[0] = dBodyCreate (world);
+  dBodySetMass (body[0],&m);
+  dBodySetPosition (body[0],0.5*SIDE,0.5*SIDE,1);
+  dBodySetQuaternion (body[0],q);
+
+  body[1] = dBodyCreate (world);
+  dBodySetMass (body[1],&m);
+  dBodySetPosition (body[1],-0.5*SIDE,-0.5*SIDE,1);
+  dBodySetQuaternion (body[1],q);
+
+  hinge = dJointCreateHinge (world,0);
+  dJointAttach (hinge,body[0],body[1]);
+  dJointSetHingeAnchor (hinge,0,0,1);
+  dJointSetHingeAxis (hinge,1,-1,1.41421356);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_jointPR.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_jointPR.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_jointPR.cpp	(revision 216)
@@ -0,0 +1,377 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+This file try to demonstrate how the PR joint is working.
+
+The axisP is draw in red and the axisR is in green
+
+*/
+
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+#include <iostream>
+#include <math.h>
+
+
+#define DRAWSTUFF_TEXTURE_PATH "../../drawstuff/textures"
+
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+// select correct drawing functions
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#endif
+
+// physics parameters
+#define BOX1_LENGTH 2    // Size along the X axis 
+#define BOX1_WIDTH 1     // Size along the Y axis
+#define BOX1_HEIGHT 0.4  // Size along the Z axis (up) since gravity is (0,0,-10)
+#define BOX2_LENGTH 0.2
+#define BOX2_WIDTH 0.1
+#define BOX2_HEIGHT 0.4
+#define Mass1 10
+#define Mass2 0.1
+
+
+#define PRISMATIC_ONLY 1
+#define ROTOIDE_ONLY   2
+int flag = 0;
+
+
+//camera view
+static float xyz[3] = {2.0f,-3.5f,2.0000f};
+static float hpr[3] = {90.000f,-25.5000f,0.0000f};
+//world,space,body & geom
+static dWorldID world;
+static dSpaceID space;
+static dSpaceID box1_space;
+static dSpaceID box2_space;
+static dBodyID box1_body[1];
+static dBodyID box2_body[1];
+static dJointID joint[1];
+static dJointGroupID contactgroup;
+static dGeomID ground;
+static dGeomID box1[1];
+static dGeomID box2[1];
+
+
+//collision detection
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+	  int i,n;
+
+		  dBodyID b1 = dGeomGetBody(o1);
+		  dBodyID b2 = dGeomGetBody(o2);
+		  if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+		  const int N = 10;
+		  dContact contact[N];
+		  n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
+		  if (n > 0)
+		  {
+			for (i=0; i<n; i++)
+			{
+				 contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
+				 dContactSoftERP | dContactSoftCFM | dContactApprox1;
+				 contact[i].surface.mu = 0.1;
+				 contact[i].surface.slip1 = 0.02;
+				 contact[i].surface.slip2 = 0.02;
+				 contact[i].surface.soft_erp = 0.1;
+				 contact[i].surface.soft_cfm = 0.0001;
+				 dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
+				 dJointAttach (c,dGeomGetBody(contact[i].geom.g1),dGeomGetBody(contact[i].geom.g2));
+			}
+		  }
+}
+
+
+// start simulation - set viewpoint
+static void start()
+{
+		dsSetViewpoint (xyz,hpr);
+		printf ("Press 'd' to add force along positive x direction.\nPress 'a' to add force along negative x direction.\n");
+		printf ("Press 'w' to add force along positive y direction.\nPress 's' to add force along negative y direction.\n");
+		printf ("Press 'e' to add torque around positive z direction.\nPress 'q' to add torque around negative z direction.\n");
+		printf ("Press 'o' to add force around positive x direction \n");
+}
+
+// function to update camera position at each step.
+void update()
+{
+// 		const dReal *a =(dBodyGetPosition (box1_body[0]));
+// 		float dx=a[0];
+// 		float dy=a[1];
+// 		float dz=a[2];
+// 		xyz[0]=dx;
+// 		xyz[1]=dy-5;
+// 		xyz[2]=dz+2;
+// 		hpr[1]=-22.5000f;
+// 		dsSetViewpoint (xyz,hpr);
+}
+
+
+// called when a key pressed
+static void command (int cmd)
+{
+    switch(cmd)
+	{
+		case 'w': case 'W':
+			dBodyAddForce(box2_body[0],0,500,0);
+			std::cout<<(dBodyGetPosition(box2_body[0])[1]-dBodyGetPosition(box1_body[0])[1])<<'\n';
+			break;
+		case 's': case 'S':
+			dBodyAddForce(box2_body[0],0,-500,0);
+			std::cout<<(dBodyGetPosition(box2_body[0])[1]-dBodyGetPosition(box1_body[0])[1])<<'\n';
+			break;
+		case 'd': case 'D':
+			dBodyAddForce(box2_body[0],500,0,0);
+			std::cout<<(dBodyGetPosition(box2_body[0])[0]-dBodyGetPosition(box1_body[0])[0])<<'\n';
+			break;
+		case 'a': case 'A':
+			dBodyAddForce(box2_body[0],-500,0,0);
+			std::cout<<(dBodyGetPosition(box2_body[0])[0]-dBodyGetPosition(box1_body[0])[0])<<'\n';
+			break;
+		case 'e': case 'E':
+			dBodyAddRelTorque(box2_body[0],0,0,200);
+			break;
+		case 'q': case 'Q':
+			dBodyAddRelTorque(box2_body[0],0,0,-200);
+			break;
+		case 'o': case 'O':
+			dBodyAddForce(box1_body[0],10000,0,0);
+			break;
+	}
+}
+
+
+// simulation loop
+static void simLoop (int pause)
+{
+	if (!pause)
+	{
+		//draw 2 boxes
+		dVector3 ss;
+		dsSetTexture (DS_WOOD);
+
+		const dReal *posBox2 = dGeomGetPosition(box2[0]);
+		const dReal *rotBox2 = dGeomGetRotation(box2[0]);
+		dsSetColor (1,1,0);
+		dGeomBoxGetLengths (box2[0],ss);
+		dsDrawBox (posBox2, rotBox2, ss);
+
+		const dReal *posBox1 = dGeomGetPosition(box1[0]);
+		const dReal *rotBox1 = dGeomGetRotation(box1[0]);
+		dsSetColor (1,1,2);
+		dGeomBoxGetLengths (box1[0], ss);
+		dsDrawBox (posBox1, rotBox1, ss);
+
+		dVector3 anchorPos;
+		dJointGetPRAnchor (joint[0], anchorPos);
+
+		// Draw the axisP 
+		if (ROTOIDE_ONLY != flag )
+		{
+		  dsSetColor (1,0,0);
+		  dVector3 sizeP = {0, 0.1, 0.1};
+		  for (int i=0; i<3; ++i)
+		    sizeP[0] += (anchorPos[i] - posBox1[i])*(anchorPos[i] - posBox1[i]);
+		  sizeP[0] = sqrt(sizeP[0]);
+		  dVector3 posAxisP;
+		  for (int i=0; i<3; ++i)
+		    posAxisP[i] = posBox1[i] + (anchorPos[i] - posBox1[i])/2.0;
+		  dsDrawBox (posAxisP, rotBox1, sizeP);
+		}
+		
+
+		// Draw the axisR 
+		if (PRISMATIC_ONLY != flag )
+		{
+		  dsSetColor (0,1,0);
+		  dVector3 sizeR = {0, 0.1, 0.1};
+		  for (int i=0; i<3; ++i)
+		    sizeR[0] += (anchorPos[i] - posBox2[i])*(anchorPos[i] - posBox2[i]);
+		  sizeR[0] = sqrt(sizeR[0]);
+		  dVector3 posAxisR;
+		  for (int i=0; i<3; ++i)
+		    posAxisR[i] = posBox2[i] + (anchorPos[i] - posBox2[i])/2.0;
+		  dsDrawBox (posAxisR, rotBox2, sizeR);
+		}
+
+		dSpaceCollide (space,0,&nearCallback);
+		dWorldQuickStep (world,0.0001);
+		update();
+		dJointGroupEmpty (contactgroup);
+	  }
+}
+
+
+void Help(char **argv)
+{
+  printf("%s ", argv[0]);
+  printf(" -h | --help : print this help\n");
+  printf(" -b | --both : Display how the complete joint works\n");
+  printf("               Default behavior\n");
+  printf(" -p | --prismatic-only : Display how the prismatic part works\n");
+  printf("                         The anchor pts is set at the center of body 2\n");
+  printf(" -r | --rotoide-only   : Display how the rotoide part works\n");
+  printf("                         The anchor pts is set at the center of body 1\n");
+  printf(" -t | --texture-path path  : Path to the texture.\n");
+  printf("                             Default = %s\n", DRAWSTUFF_TEXTURE_PATH);
+  printf("--------------------------------------------------\n");
+  printf("Hit any key to continue:");
+  getchar();
+
+  exit(0);
+}
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
+  
+  if (argc >= 2 )
+  {
+    for (int i=1; i < argc; ++i)
+    {
+      if(  0 == strcmp("-h", argv[i]) || 0 == strcmp("--help", argv[i]) )
+	Help(argv);
+      
+      if(!flag && (0 == strcmp("-p", argv[i]) ||0 == strcmp("--prismatic-only", argv[i])) )
+	flag = PRISMATIC_ONLY;
+      
+      if(!flag && (0 == strcmp("-r", argv[i]) || 0 == strcmp("--rotoide-only", argv[i])) )
+	flag = ROTOIDE_ONLY;
+      
+      if(0 == strcmp("-t", argv[i]) || 0 == strcmp("--texture-path", argv[i]))
+      {
+	int j = i+1;
+	if ( j+1 > argc      ||  // Check if we have enough arguments
+	     argv[j] == '\0' ||  // We should have a path here
+	     argv[j][0] == '-' ) // We should have a path not a command line
+	  Help(argv);
+	else
+	  fn.path_to_textures = argv[++i]; // Increase i since we use this argument
+      }
+    }
+  }
+  
+  // create world
+  world = dWorldCreate();
+  space = dHashSpaceCreate (0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-10);
+  ground = dCreatePlane (space,0,0,1,0);
+  
+  //create two boxes
+  dMass m;
+  box1_body[0] = dBodyCreate (world);
+  dMassSetBox (&m,1,BOX1_LENGTH,BOX1_WIDTH,BOX1_HEIGHT);
+  dMassAdjust (&m,Mass1);
+  dBodySetMass (box1_body[0],&m);
+  box1[0] = dCreateBox (0,BOX1_LENGTH,BOX1_WIDTH,BOX1_HEIGHT);
+  dGeomSetBody (box1[0],box1_body[0]);
+  
+  box2_body[0] = dBodyCreate (world);
+  dMassSetBox (&m,10,BOX2_LENGTH,BOX2_WIDTH,BOX2_HEIGHT);
+  dMassAdjust (&m,Mass2);
+  dBodySetMass (box2_body[0],&m);
+  box2[0] = dCreateBox (0,BOX2_LENGTH,BOX2_WIDTH,BOX2_HEIGHT);
+  dGeomSetBody (box2[0],box2_body[0]);
+  
+  //set the initial positions of body1 and body2
+  dMatrix3 R;
+  dRSetIdentity(R);
+  dBodySetPosition (box1_body[0],0,0,BOX1_HEIGHT/2.0);
+  dBodySetRotation (box1_body[0], R);
+  
+  dBodySetPosition (box2_body[0],
+		    2.1, 
+		    0.0,
+		    BOX2_HEIGHT/2.0);
+  dBodySetRotation (box2_body[0], R);
+  
+  
+  //set PR joint
+  joint[0] = dJointCreatePR(world,0);
+  dJointAttach (joint[0],box1_body[0],box2_body[0]);  
+  switch (flag)
+  {
+    case PRISMATIC_ONLY:
+      dJointSetPRAnchor (joint[0], 
+			 2.1, 
+			 0.0,
+			 BOX2_HEIGHT/2.0);
+      dJointSetPRParam (joint[0],dParamLoStop, -0.5);
+      dJointSetPRParam (joint[0],dParamHiStop, 1.5);
+      break;
+      
+    case ROTOIDE_ONLY:
+      dJointSetPRAnchor (joint[0], 
+			 0.0, 
+			 0.0,
+			 BOX2_HEIGHT/2.0);
+      dJointSetPRParam (joint[0],dParamLoStop, 0.0);
+      dJointSetPRParam (joint[0],dParamHiStop, 0.0);
+      break;
+      
+    default:
+      dJointSetPRAnchor (joint[0], 
+			 1.1, 
+			 0.0,
+			 BOX2_HEIGHT/2.0);
+      dJointSetPRParam (joint[0],dParamLoStop, -0.5);
+      dJointSetPRParam (joint[0],dParamHiStop, 1.5);
+      break;
+  }
+  
+  dJointSetPRAxis1(joint[0],1,0,0);
+  dJointSetPRAxis2(joint[0],0,0,1);
+// We position  the 2 body
+// The position of the rotoide joint is on the second body so it can rotate on itself
+// and move along the X axis.
+// With this anchor 
+// - A force in X will move only the body 2 inside the low and hi limit
+//   of the prismatic
+// - A force in Y will make the 2 bodies to rotate around on the plane
+  
+  box1_space = dSimpleSpaceCreate (space);
+  dSpaceSetCleanup (box1_space,0);
+  dSpaceAdd(box1_space,box1[0]);
+  
+  // run simulation
+  dsSimulationLoop (argc,argv,400,300,&fn);
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  return 0;
+}
+
Index: /code/branches/ode/ode-0.9/ode/demo/demo_joints.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_joints.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_joints.cpp	(revision 216)
@@ -0,0 +1,1092 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+perform tests on all the joint types.
+this should be done using the double precision version of the library.
+
+usage:
+  test_joints [-nXXX] [-g] [-i] [-e] [path_to_textures]
+
+if a test number is given then that specific test is performed, otherwise
+all the tests are performed. the tests are numbered `xxyy', where xx
+corresponds to the joint type and yy is the sub-test number. not every
+number maps to an actual test.
+
+flags:
+  i: the test is interactive.
+  g: turn off graphical display (can't use this with `i').
+  e: turn on occasional error perturbations
+  n: performe test XXX
+some tests compute and display error values. these values are scaled so
+<1 is good and >1 is bad. other tests just show graphical results which
+you must verify visually.
+
+*/
+
+#include <ctype.h>
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#endif
+
+
+// some constants
+#define NUM_JOINTS 10	// number of joints to test (the `xx' value)
+#define SIDE (0.5f)	// side length of a box - don't change this
+#define MASS (1.0)	// mass of a box
+#define STEPSIZE 0.05
+
+
+// dynamics objects
+static dWorldID world;
+static dBodyID body[2];
+static dJointID joint;
+
+
+// data from the command line arguments
+static int cmd_test_num = -1;
+static int cmd_interactive = 0;
+static int cmd_graphics = 1;
+static char *cmd_path_to_textures = NULL;
+static int cmd_occasional_error = 0;	// perturb occasionally
+
+
+// info about the current test
+struct TestInfo;
+static int test_num = 0;		// number of the current test
+static int iteration = 0;
+static int max_iterations = 0;
+static dReal max_error = 0;
+
+//****************************************************************************
+// utility stuff
+
+static char loCase (char a)
+{
+  if (a >= 'A' && a <= 'Z') return a + ('a'-'A');
+  else return a;
+}
+
+
+static dReal length (dVector3 a)
+{
+  return dSqrt (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
+}
+
+
+// get the max difference between a 3x3 matrix and the identity
+
+dReal cmpIdentity (const dMatrix3 A)
+{
+  dMatrix3 I;
+  dSetZero (I,12);
+  I[0] = 1;
+  I[5] = 1;
+  I[10] = 1;
+  return dMaxDifference (A,I,3,3);
+}
+
+//****************************************************************************
+// test world construction and utilities
+
+void constructWorldForTest (dReal gravity, int bodycount,
+ /* body 1 pos */           dReal pos1x, dReal pos1y, dReal pos1z,
+ /* body 2 pos */           dReal pos2x, dReal pos2y, dReal pos2z,
+ /* body 1 rotation axis */ dReal ax1x, dReal ax1y, dReal ax1z,
+ /* body 1 rotation axis */ dReal ax2x, dReal ax2y, dReal ax2z,
+ /* rotation angles */      dReal a1, dReal a2)
+{
+  // create world
+  world = dWorldCreate();
+  dWorldSetERP (world,0.2);
+  dWorldSetCFM (world,1e-6);
+  dWorldSetGravity (world,0,0,gravity);
+
+  dMass m;
+  dMassSetBox (&m,1,SIDE,SIDE,SIDE);
+  dMassAdjust (&m,MASS);
+
+  body[0] = dBodyCreate (world);
+  dBodySetMass (body[0],&m);
+  dBodySetPosition (body[0], pos1x, pos1y, pos1z);
+  dQuaternion q;
+  dQFromAxisAndAngle (q,ax1x,ax1y,ax1z,a1);
+  dBodySetQuaternion (body[0],q);
+
+  if (bodycount==2) {
+    body[1] = dBodyCreate (world);
+    dBodySetMass (body[1],&m);
+    dBodySetPosition (body[1], pos2x, pos2y, pos2z);
+    dQFromAxisAndAngle (q,ax2x,ax2y,ax2z,a2);
+    dBodySetQuaternion (body[1],q);
+  }
+  else body[1] = 0;
+}
+
+
+// add an oscillating torque to body 0
+
+void addOscillatingTorque (dReal tscale)
+{
+  static dReal a=0;
+  dBodyAddTorque (body[0],tscale*cos(2*a),tscale*cos(2.7183*a),
+		  tscale*cos(1.5708*a));
+  a += 0.01;
+}
+
+
+void addOscillatingTorqueAbout(dReal tscale, dReal x, dReal y, dReal z)
+{
+  static dReal a=0;
+  dBodyAddTorque (body[0], tscale*cos(a) * x, tscale*cos(a) * y,
+		  tscale * cos(a) * z);
+  a += 0.02;
+}
+
+
+// damp the rotational motion of body 0 a bit
+
+void dampRotationalMotion (dReal kd)
+{
+  const dReal *w = dBodyGetAngularVel (body[0]);
+  dBodyAddTorque (body[0],-kd*w[0],-kd*w[1],-kd*w[2]);
+}
+
+
+// add a spring force to keep the bodies together, otherwise they may fly
+// apart with some joints.
+
+void addSpringForce (dReal ks)
+{
+  const dReal *p1 = dBodyGetPosition (body[0]);
+  const dReal *p2 = dBodyGetPosition (body[1]);
+  dBodyAddForce (body[0],ks*(p2[0]-p1[0]),ks*(p2[1]-p1[1]),ks*(p2[2]-p1[2]));
+  dBodyAddForce (body[1],ks*(p1[0]-p2[0]),ks*(p1[1]-p2[1]),ks*(p1[2]-p2[2]));
+}
+
+
+// add an oscillating Force to body 0
+
+void addOscillatingForce (dReal fscale)
+{
+  static dReal a=0;
+  dBodyAddForce (body[0],fscale*cos(2*a),fscale*cos(2.7183*a),
+		  fscale*cos(1.5708*a));
+  a += 0.01;
+}
+
+//****************************************************************************
+// stuff specific to the tests
+//
+//   0xx : fixed
+//   1xx : ball and socket
+//   2xx : hinge
+//   3xx : slider
+//   4xx : hinge 2
+//   5xx : contact
+//   6xx : amotor
+//   7xx : universal joint
+//   8xx : PR joint (Prismatic and Rotoide)
+
+// setup for the given test. return 0 if there is no such test
+
+int setupTest (int n)
+{
+  switch (n) {
+
+  // ********** fixed joint
+
+  case 0: {			// 2 body
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+			   1,1,0, 1,1,0,
+			   0.25*M_PI,0.25*M_PI);
+    joint = dJointCreateFixed (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetFixed (joint);
+    return 1;
+  }
+
+  case 1: {			// 1 body to static env
+    constructWorldForTest (0,1,
+			   0.5*SIDE,0.5*SIDE,1, 0,0,0,
+			   1,0,0, 1,0,0,
+			   0,0);
+    joint = dJointCreateFixed (world,0);
+    dJointAttach (joint,body[0],0);
+    dJointSetFixed (joint);
+    return 1;
+  }
+
+  case 2: {			// 2 body with relative rotation
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+			   1,1,0, 1,1,0,
+			   0.25*M_PI,-0.25*M_PI);
+    joint = dJointCreateFixed (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetFixed (joint);
+    return 1;
+  }
+
+  case 3: {			// 1 body to static env with relative rotation
+    constructWorldForTest (0,1,
+			   0.5*SIDE,0.5*SIDE,1, 0,0,0,
+			   1,0,0, 1,0,0,
+			   0.25*M_PI,0);
+    joint = dJointCreateFixed (world,0);
+    dJointAttach (joint,body[0],0);
+    dJointSetFixed (joint);
+    return 1;
+  }
+
+  // ********** hinge joint
+
+  case 200:			// 2 body
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+			   1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI);
+    joint = dJointCreateHinge (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetHingeAnchor (joint,0,0,1);
+    dJointSetHingeAxis (joint,1,-1,1.41421356);
+    return 1;
+
+  case 220:			// hinge angle polarity test
+  case 221:			// hinge angle rate test
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateHinge (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetHingeAnchor (joint,0,0,1);
+    dJointSetHingeAxis (joint,0,0,1);
+    max_iterations = 50;
+    return 1;
+
+  case 230:			// hinge motor rate (and polarity) test
+  case 231:			// ...with stops
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateHinge (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetHingeAnchor (joint,0,0,1);
+    dJointSetHingeAxis (joint,0,0,1);
+    dJointSetHingeParam (joint,dParamFMax,1);
+    if (n==231) {
+      dJointSetHingeParam (joint,dParamLoStop,-0.5);
+      dJointSetHingeParam (joint,dParamHiStop,0.5);
+    }
+    return 1;
+
+  case 250:			// limit bounce test (gravity down)
+  case 251: {			// ...gravity up
+    constructWorldForTest ((n==251) ? 0.1 : -0.1, 2,
+			   0.5*SIDE,0,1+0.5*SIDE, -0.5*SIDE,0,1-0.5*SIDE,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateHinge (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetHingeAnchor (joint,0,0,1);
+    dJointSetHingeAxis (joint,0,1,0);
+    dJointSetHingeParam (joint,dParamLoStop,-0.9);
+    dJointSetHingeParam (joint,dParamHiStop,0.7854);
+    dJointSetHingeParam (joint,dParamBounce,0.5);
+    // anchor 2nd body with a fixed joint
+    dJointID j = dJointCreateFixed (world,0);
+    dJointAttach (j,body[1],0);
+    dJointSetFixed (j);
+    return 1;
+  }
+
+  // ********** slider
+
+  case 300:			// 2 body
+    constructWorldForTest (0,2,
+			   0,0,1, 0.2,0.2,1.2,
+			   0,0,1, -1,1,0, 0,0.25*M_PI);
+    joint = dJointCreateSlider (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetSliderAxis (joint,1,1,1);
+    return 1;
+
+  case 320:			// slider angle polarity test
+  case 321:			// slider angle rate test
+    constructWorldForTest (0,2,
+			   0,0,1, 0,0,1.2,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateSlider (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetSliderAxis (joint,0,0,1);
+    max_iterations = 50;
+    return 1;
+
+  case 330:			// slider motor rate (and polarity) test
+  case 331:			// ...with stops
+    constructWorldForTest (0, 2,
+			   0,0,1, 0,0,1.2,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateSlider (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetSliderAxis (joint,0,0,1);
+    dJointSetSliderParam (joint,dParamFMax,100);
+    if (n==331) {
+      dJointSetSliderParam (joint,dParamLoStop,-0.4);
+      dJointSetSliderParam (joint,dParamHiStop,0.4);
+    }
+    return 1;
+
+  case 350:			// limit bounce tests
+  case 351: {
+    constructWorldForTest ((n==351) ? 0.1 : -0.1, 2,
+			   0,0,1, 0,0,1.2,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateSlider (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetSliderAxis (joint,0,0,1);
+    dJointSetSliderParam (joint,dParamLoStop,-0.5);
+    dJointSetSliderParam (joint,dParamHiStop,0.5);
+    dJointSetSliderParam (joint,dParamBounce,0.5);
+    // anchor 2nd body with a fixed joint
+    dJointID j = dJointCreateFixed (world,0);
+    dJointAttach (j,body[1],0);
+    dJointSetFixed (j);
+    return 1;
+  }
+
+  // ********** hinge-2 joint
+
+  case 420:			// hinge-2 steering angle polarity test
+  case 421:			// hinge-2 steering angle rate test
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0,1, -0.5*SIDE,0,1,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateHinge2 (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetHinge2Anchor (joint,-0.5*SIDE,0,1);
+    dJointSetHinge2Axis1 (joint,0,0,1);
+    dJointSetHinge2Axis2 (joint,1,0,0);
+    max_iterations = 50;
+    return 1;
+
+  case 430:			// hinge 2 steering motor rate (+polarity) test
+  case 431:			// ...with stops
+  case 432:			// hinge 2 wheel motor rate (+polarity) test
+    constructWorldForTest (0,2,
+			   0.5*SIDE,0,1, -0.5*SIDE,0,1,
+			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateHinge2 (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetHinge2Anchor (joint,-0.5*SIDE,0,1);
+    dJointSetHinge2Axis1 (joint,0,0,1);
+    dJointSetHinge2Axis2 (joint,1,0,0);
+    dJointSetHinge2Param (joint,dParamFMax,1);
+    dJointSetHinge2Param (joint,dParamFMax2,1);
+    if (n==431) {
+      dJointSetHinge2Param (joint,dParamLoStop,-0.5);
+      dJointSetHinge2Param (joint,dParamHiStop,0.5);
+    }
+    return 1;
+
+  // ********** angular motor joint
+
+  case 600:			// test euler angle calculations
+    constructWorldForTest (0,2,
+			   -SIDE*0.5,0,1, SIDE*0.5,0,1,
+			   0,0,1, 0,0,1, 0,0);
+    joint = dJointCreateAMotor (world,0);
+    dJointAttach (joint,body[0],body[1]);
+
+    dJointSetAMotorNumAxes (joint,3);
+    dJointSetAMotorAxis (joint,0,1, 0,0,1);
+    dJointSetAMotorAxis (joint,2,2, 1,0,0);
+    dJointSetAMotorMode (joint,dAMotorEuler);
+    max_iterations = 200;
+    return 1;
+
+    // ********** universal joint
+
+  case 700:			// 2 body
+  case 701:
+  case 702:
+    constructWorldForTest (0,2,
+ 			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+ 			   1,1,0, 1,1,0, 0.25*M_PI,0.25*M_PI);
+    joint = dJointCreateUniversal (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetUniversalAnchor (joint,0,0,1);
+    dJointSetUniversalAxis1 (joint, 1, -1, 1.41421356);
+    dJointSetUniversalAxis2 (joint, 1, -1, -1.41421356);
+    return 1;
+
+  case 720:		// universal transmit torque test
+  case 721:
+  case 722:
+  case 730:		// universal torque about axis 1
+  case 731:
+  case 732:
+  case 740:		// universal torque about axis 2
+  case 741:
+  case 742:
+    constructWorldForTest (0,2,
+ 			   0.5*SIDE,0.5*SIDE,1, -0.5*SIDE,-0.5*SIDE,1,
+ 			   1,0,0, 1,0,0, 0,0);
+    joint = dJointCreateUniversal (world,0);
+    dJointAttach (joint,body[0],body[1]);
+    dJointSetUniversalAnchor (joint,0,0,1);
+    dJointSetUniversalAxis1 (joint,0,0,1);
+    dJointSetUniversalAxis2 (joint, 1, -1,0);
+    max_iterations = 100;
+    return 1;
+
+  // Joint PR (Prismatic and Rotoide)
+  case 800:     // 2 body
+  case 801:     // 2 bodies with spring force and prismatic fixed
+  case 802:     // 2 bodies with torque on body1 and prismatic fixed
+    constructWorldForTest (0, 2,
+                           -1.0, 0.0, 1.0,
+                           1.0, 0.0, 1.0,
+                           1,0,0, 1,0,0,
+                           0, 0);
+    joint = dJointCreatePR (world, 0);
+    dJointAttach (joint, body[0], body[1]);
+    dJointSetPRAnchor (joint,-0.5, 0.0, 1.0);
+    dJointSetPRAxis1 (joint, 0, 1, 0);
+    dJointSetPRAxis2 (joint, 1, 0, 0);
+    dJointSetPRParam (joint,dParamLoStop,-0.5);
+    dJointSetPRParam (joint,dParamHiStop,0.5);
+    dJointSetPRParam (joint,dParamLoStop2,0);
+    dJointSetPRParam (joint,dParamHiStop2,0);
+    return 1;
+  case 803:   // 2 bodies with spring force and prismatic NOT fixed
+  case 804:   // 2 bodies with torque force and prismatic NOT fixed
+  case 805:   // 2 bodies with force only on first body
+    constructWorldForTest (0, 2,
+                           -1.0, 0.0, 1.0,
+                           1.0, 0.0, 1.0,
+                           1,0,0, 1,0,0,
+                           0, 0);
+    joint = dJointCreatePR (world, 0);
+    dJointAttach (joint, body[0], body[1]);
+    dJointSetPRAnchor (joint,-0.5, 0.0, 1.0);
+    dJointSetPRAxis1 (joint, 0, 1, 0);
+    dJointSetPRAxis2 (joint, 1, 0, 0);
+    dJointSetPRParam (joint,dParamLoStop,-0.5);
+    dJointSetPRParam (joint,dParamHiStop,0.5);
+    dJointSetPRParam (joint,dParamLoStop2,-0.5);
+    dJointSetPRParam (joint,dParamHiStop2,0.5);
+    return 1;
+  }
+  return 0;
+}
+
+
+// do stuff specific to this test each iteration. you can check some
+// invariants for the test -- the return value is some scaled error measurement
+// that must be less than 1.
+// return a dInfinity if error is not measured for this n.
+
+dReal doStuffAndGetError (int n)
+{
+  switch (n) {
+
+  // ********** fixed joint
+
+  case 0: {			// 2 body
+    addOscillatingTorque (0.1);
+    dampRotationalMotion (0.1);
+    // check the orientations are the same
+    const dReal *R1 = dBodyGetRotation (body[0]);
+    const dReal *R2 = dBodyGetRotation (body[1]);
+    dReal err1 = dMaxDifference (R1,R2,3,3);
+    // check the body offset is correct
+    dVector3 p,pp;
+    const dReal *p1 = dBodyGetPosition (body[0]);
+    const dReal *p2 = dBodyGetPosition (body[1]);
+    for (int i=0; i<3; i++) p[i] = p2[i] - p1[i];
+    dMULTIPLY1_331 (pp,R1,p);
+    pp[0] += 0.5;
+    pp[1] += 0.5;
+    return (err1 + length (pp)) * 300;
+  }
+
+  case 1: {			// 1 body to static env
+    addOscillatingTorque (0.1);
+
+    // check the orientation is the identity
+    dReal err1 = cmpIdentity (dBodyGetRotation (body[0]));
+
+    // check the body offset is correct
+    dVector3 p;
+    const dReal *p1 = dBodyGetPosition (body[0]);
+    for (int i=0; i<3; i++) p[i] = p1[i];
+    p[0] -= 0.25;
+    p[1] -= 0.25;
+    p[2] -= 1;
+    return (err1 + length (p)) * 1e6;
+  }
+
+  case 2: {			// 2 body
+    addOscillatingTorque (0.1);
+    dampRotationalMotion (0.1);
+    // check the body offset is correct
+    // Should really check body rotation too.  Oh well.
+    const dReal *R1 = dBodyGetRotation (body[0]);
+    dVector3 p,pp;
+    const dReal *p1 = dBodyGetPosition (body[0]);
+    const dReal *p2 = dBodyGetPosition (body[1]);
+    for (int i=0; i<3; i++) p[i] = p2[i] - p1[i];
+    dMULTIPLY1_331 (pp,R1,p);
+    pp[0] += 0.5;
+    pp[1] += 0.5;
+    return length(pp) * 300;
+  }
+
+  case 3: {			// 1 body to static env with relative rotation
+    addOscillatingTorque (0.1);
+
+    // check the body offset is correct
+    dVector3 p;
+    const dReal *p1 = dBodyGetPosition (body[0]);
+    for (int i=0; i<3; i++) p[i] = p1[i];
+    p[0] -= 0.25;
+    p[1] -= 0.25;
+    p[2] -= 1;
+    return  length (p) * 1e6;
+  }
+
+
+  // ********** hinge joint
+
+  case 200:			// 2 body
+    addOscillatingTorque (0.1);
+    dampRotationalMotion (0.1);
+    return dInfinity;
+
+  case 220:			// hinge angle polarity test
+    dBodyAddTorque (body[0],0,0,0.01);
+    dBodyAddTorque (body[1],0,0,-0.01);
+    if (iteration == 40) {
+      dReal a = dJointGetHingeAngle (joint);
+      if (a > 0.5 && a < 1) return 0; else return 10;
+    }
+    return 0;
+
+  case 221: {			// hinge angle rate test
+    static dReal last_angle = 0;
+    dBodyAddTorque (body[0],0,0,0.01);
+    dBodyAddTorque (body[1],0,0,-0.01);
+    dReal a = dJointGetHingeAngle (joint);
+    dReal r = dJointGetHingeAngleRate (joint);
+    dReal er = (a-last_angle)/STEPSIZE;		// estimated rate
+    last_angle = a;
+    return fabs(r-er) * 4e4;
+  }
+
+  case 230:			// hinge motor rate (and polarity) test
+  case 231: {			// ...with stops
+    static dReal a = 0;
+    dReal r = dJointGetHingeAngleRate (joint);
+    dReal err = fabs (cos(a) - r);
+    if (a==0) err = 0;
+    a += 0.03;
+    dJointSetHingeParam (joint,dParamVel,cos(a));
+    if (n==231) return dInfinity;
+    return err * 1e6;
+  }
+
+  // ********** slider joint
+
+  case 300:			// 2 body
+    addOscillatingTorque (0.05);
+    dampRotationalMotion (0.1);
+    addSpringForce (0.5);
+    return dInfinity;
+
+  case 320:			// slider angle polarity test
+    dBodyAddForce (body[0],0,0,0.1);
+    dBodyAddForce (body[1],0,0,-0.1);
+    if (iteration == 40) {
+      dReal a = dJointGetSliderPosition (joint);
+      if (a > 0.2 && a < 0.5) return 0; else return 10;
+      return a;
+    }
+    return 0;
+
+  case 321: {			// slider angle rate test
+    static dReal last_pos = 0;
+    dBodyAddForce (body[0],0,0,0.1);
+    dBodyAddForce (body[1],0,0,-0.1);
+    dReal p = dJointGetSliderPosition (joint);
+    dReal r = dJointGetSliderPositionRate (joint);
+    dReal er = (p-last_pos)/STEPSIZE;	// estimated rate (almost exact)
+    last_pos = p;
+    return fabs(r-er) * 1e9;
+  }
+
+  case 330:			// slider motor rate (and polarity) test
+  case 331: {			// ...with stops
+    static dReal a = 0;
+    dReal r = dJointGetSliderPositionRate (joint);
+    dReal err = fabs (0.7*cos(a) - r);
+    if (a < 0.04) err = 0;
+    a += 0.03;
+    dJointSetSliderParam (joint,dParamVel,0.7*cos(a));
+    if (n==331) return dInfinity;
+    return err * 1e6;
+  }
+
+  // ********** hinge-2 joint
+
+  case 420:			// hinge-2 steering angle polarity test
+    dBodyAddTorque (body[0],0,0,0.01);
+    dBodyAddTorque (body[1],0,0,-0.01);
+    if (iteration == 40) {
+      dReal a = dJointGetHinge2Angle1 (joint);
+      if (a > 0.5 && a < 0.6) return 0; else return 10;
+    }
+    return 0;
+
+  case 421: {			// hinge-2 steering angle rate test
+    static dReal last_angle = 0;
+    dBodyAddTorque (body[0],0,0,0.01);
+    dBodyAddTorque (body[1],0,0,-0.01);
+    dReal a = dJointGetHinge2Angle1 (joint);
+    dReal r = dJointGetHinge2Angle1Rate (joint);
+    dReal er = (a-last_angle)/STEPSIZE;		// estimated rate
+    last_angle = a;
+    return fabs(r-er)*2e4;
+  }
+
+  case 430:			// hinge 2 steering motor rate (+polarity) test
+  case 431: {			// ...with stops
+    static dReal a = 0;
+    dReal r = dJointGetHinge2Angle1Rate (joint);
+    dReal err = fabs (cos(a) - r);
+    if (a==0) err = 0;
+    a += 0.03;
+    dJointSetHinge2Param (joint,dParamVel,cos(a));
+    if (n==431) return dInfinity;
+    return err * 1e6;
+  }
+
+  case 432: {			// hinge 2 wheel motor rate (+polarity) test
+    static dReal a = 0;
+    dReal r = dJointGetHinge2Angle2Rate (joint);
+    dReal err = fabs (cos(a) - r);
+    if (a==0) err = 0;
+    a += 0.03;
+    dJointSetHinge2Param (joint,dParamVel2,cos(a));
+    return err * 1e6;
+  }
+
+  // ********** angular motor joint
+
+  case 600: {			// test euler angle calculations
+    // desired euler angles from last iteration
+    static dReal a1,a2,a3;
+
+    // find actual euler angles
+    dReal aa1 = dJointGetAMotorAngle (joint,0);
+    dReal aa2 = dJointGetAMotorAngle (joint,1);
+    dReal aa3 = dJointGetAMotorAngle (joint,2);
+    // printf ("actual  = %.4f %.4f %.4f\n\n",aa1,aa2,aa3);
+
+    dReal err = dInfinity;
+    if (iteration > 0) {
+      err = dFabs(aa1-a1) + dFabs(aa2-a2) + dFabs(aa3-a3);
+      err *= 1e10;
+    }
+
+    // get random base rotation for both bodies
+    dMatrix3 Rbase;
+    dRFromAxisAndAngle (Rbase, 3*(dRandReal()-0.5), 3*(dRandReal()-0.5),
+			3*(dRandReal()-0.5), 3*(dRandReal()-0.5));
+    dBodySetRotation (body[0],Rbase);
+
+    // rotate body 2 by random euler angles w.r.t. body 1
+    a1 = 3.14 * 2 * (dRandReal()-0.5);
+    a2 = 1.57 * 2 * (dRandReal()-0.5);
+    a3 = 3.14 * 2 * (dRandReal()-0.5);
+    dMatrix3 R1,R2,R3,Rtmp1,Rtmp2;
+    dRFromAxisAndAngle (R1,0,0,1,-a1);
+    dRFromAxisAndAngle (R2,0,1,0,a2);
+    dRFromAxisAndAngle (R3,1,0,0,-a3);
+    dMultiply0 (Rtmp1,R2,R3,3,3,3);
+    dMultiply0 (Rtmp2,R1,Rtmp1,3,3,3);
+    dMultiply0 (Rtmp1,Rbase,Rtmp2,3,3,3);
+    dBodySetRotation (body[1],Rtmp1);
+    // printf ("desired = %.4f %.4f %.4f\n",a1,a2,a3);
+
+    return err;
+  }
+
+  // ********** universal joint
+
+  case 700: {		// 2 body: joint constraint
+    dVector3 ax1, ax2;
+
+    addOscillatingTorque (0.1);
+    dampRotationalMotion (0.1);
+    dJointGetUniversalAxis1(joint, ax1);
+    dJointGetUniversalAxis2(joint, ax2);
+    return fabs(10*dDOT(ax1, ax2));
+  }
+
+  case 701: {		// 2 body: angle 1 rate
+    static dReal last_angle = 0;
+    addOscillatingTorque (0.1);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle1(joint);
+    dReal r = dJointGetUniversalAngle1Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    // I'm not sure why the error is so large here.
+    return fabs(r - er) * 1e1;
+  }
+
+  case 702: {		// 2 body: angle 2 rate
+    static dReal last_angle = 0;
+    addOscillatingTorque (0.1);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle2(joint);
+    dReal r = dJointGetUniversalAngle2Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    // I'm not sure why the error is so large here.
+    return fabs(r - er) * 1e1;
+  }
+
+  case 720: {		// universal transmit torque test: constraint error
+    dVector3 ax1, ax2;
+    addOscillatingTorqueAbout (0.1, 1, 1, 0);
+    dampRotationalMotion (0.1);
+    dJointGetUniversalAxis1(joint, ax1);
+    dJointGetUniversalAxis2(joint, ax2);
+    return fabs(10*dDOT(ax1, ax2));
+  }
+
+  case 721: {		// universal transmit torque test: angle1 rate
+    static dReal last_angle = 0;
+    addOscillatingTorqueAbout (0.1, 1, 1, 0);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle1(joint);
+    dReal r = dJointGetUniversalAngle1Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    return fabs(r - er) * 1e10;
+  }
+
+  case 722: {		// universal transmit torque test: angle2 rate
+    static dReal last_angle = 0;
+    addOscillatingTorqueAbout (0.1, 1, 1, 0);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle2(joint);
+    dReal r = dJointGetUniversalAngle2Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    return fabs(r - er) * 1e10;
+  }
+
+  case 730:{
+    dVector3 ax1, ax2;
+    dJointGetUniversalAxis1(joint, ax1);
+    dJointGetUniversalAxis2(joint, ax2);
+    addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]);
+    dampRotationalMotion (0.1);
+    return fabs(10*dDOT(ax1, ax2));
+  }
+
+  case 731:{
+    dVector3 ax1;
+    static dReal last_angle = 0;
+    dJointGetUniversalAxis1(joint, ax1);
+    addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle1(joint);
+    dReal r = dJointGetUniversalAngle1Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    return fabs(r - er) * 2e3;
+  }
+
+  case 732:{
+    dVector3 ax1;
+    static dReal last_angle = 0;
+    dJointGetUniversalAxis1(joint, ax1);
+    addOscillatingTorqueAbout (0.1, ax1[0], ax1[1], ax1[2]);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle2(joint);
+    dReal r = dJointGetUniversalAngle2Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    return fabs(r - er) * 1e10;
+  }
+
+  case 740:{
+    dVector3 ax1, ax2;
+    dJointGetUniversalAxis1(joint, ax1);
+    dJointGetUniversalAxis2(joint, ax2);
+    addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]);
+    dampRotationalMotion (0.1);
+    return fabs(10*dDOT(ax1, ax2));
+  }
+
+  case 741:{
+    dVector3 ax2;
+    static dReal last_angle = 0;
+    dJointGetUniversalAxis2(joint, ax2);
+    addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle1(joint);
+    dReal r = dJointGetUniversalAngle1Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    return fabs(r - er) * 1e10;
+  }
+
+  case 742:{
+    dVector3 ax2;
+    static dReal last_angle = 0;
+    dJointGetUniversalAxis2(joint, ax2);
+    addOscillatingTorqueAbout (0.1, ax2[0], ax2[1], ax2[2]);
+    dampRotationalMotion (0.1);
+    dReal a = dJointGetUniversalAngle2(joint);
+    dReal r = dJointGetUniversalAngle2Rate(joint);
+    dReal diff = a - last_angle;
+    if (diff > M_PI) diff -= 2*M_PI;
+    if (diff < -M_PI) diff += 2*M_PI;
+    dReal er = diff / STEPSIZE;    // estimated rate
+    last_angle = a;
+    return fabs(r - er) * 1e4;
+  }
+
+  // ********** slider joint
+  case 801:
+  case 803:
+    addSpringForce (0.25);
+    return dInfinity;
+
+	case 802:
+	case 804: {
+    static dReal a = 0;
+    dBodyAddTorque (body[0], 0, 0.01*cos(1.5708*a), 0);
+    a += 0.01;
+    return dInfinity;
+	}
+
+  case 805:
+    addOscillatingForce (0.1);
+    return dInfinity;
+	}
+
+
+  return dInfinity;
+}
+
+//****************************************************************************
+// simulation stuff common to all the tests
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
+  static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  // stop after a given number of iterations, as long as we are not in
+  // interactive mode
+  if (cmd_graphics && !cmd_interactive &&
+      (iteration >= max_iterations)) {
+    dsStop();
+    return;
+  }
+  iteration++;
+
+  if (!pause) {
+    // do stuff for this test and check to see if the joint is behaving well
+    dReal error = doStuffAndGetError (test_num);
+    if (error > max_error) max_error = error;
+    if (cmd_interactive && error < dInfinity) {
+      printf ("scaled error = %.4e\n",error);
+    }
+
+    // take a step
+    dWorldStep (world,STEPSIZE);
+
+    // occasionally re-orient the first body to create a deliberate error.
+    if (cmd_occasional_error) {
+      static int count = 0;
+      if ((count % 20)==0) {
+	// randomly adjust orientation of body[0]
+	const dReal *R1;
+	dMatrix3 R2,R3;
+	R1 = dBodyGetRotation (body[0]);
+	dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5,
+			    dRandReal()-0.5,dRandReal()-0.5);
+	dMultiply0 (R3,R1,R2,3,3,3);
+	dBodySetRotation (body[0],R3);
+
+	// randomly adjust position of body[0]
+	const dReal *pos = dBodyGetPosition (body[0]);
+	dBodySetPosition (body[0],
+			  pos[0]+0.2*(dRandReal()-0.5),
+			  pos[1]+0.2*(dRandReal()-0.5),
+			  pos[2]+0.2*(dRandReal()-0.5));
+      }
+      count++;
+    }
+  }
+
+  if (cmd_graphics) {
+    dReal sides1[3] = {SIDE,SIDE,SIDE};
+    dReal sides2[3] = {SIDE*0.99f,SIDE*0.99f,SIDE*0.99f};
+    dsSetTexture (DS_WOOD);
+    dsSetColor (1,1,0);
+    dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
+    if (body[1]) {
+      dsSetColor (0,1,1);
+      dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
+    }
+  }
+}
+
+//****************************************************************************
+// conduct a specific test, and report the results
+
+void doTest (int argc, char **argv, int n, int fatal_if_bad_n)
+{
+  test_num = n;
+  iteration = 0;
+  max_iterations = 300;
+  max_error = 0;
+
+  if (! setupTest (n)) {
+    if (fatal_if_bad_n) dError (0,"bad test number");
+    return;
+  }
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = 0;
+  fn.stop = 0;
+  if (cmd_path_to_textures)
+    fn.path_to_textures = cmd_path_to_textures;
+  else
+  fn.path_to_textures = "../../drawstuff/textures";
+
+  // run simulation
+  if (cmd_graphics) {
+    dsSimulationLoop (argc,argv,352,288,&fn);
+  }
+  else {
+    for (int i=0; i < max_iterations; i++) simLoop (0);
+  }
+  dWorldDestroy (world);
+  body[0] = 0;
+  body[1] = 0;
+  joint = 0;
+
+  // print results
+  printf ("test %d: ",n);
+  if (max_error == dInfinity) printf ("error not computed\n");
+  else {
+    printf ("max scaled error = %.4e",max_error);
+    if (max_error < 1) printf (" - passed\n");
+    else printf (" - FAILED\n");
+  }
+}
+
+//****************************************************************************
+// main
+
+int main (int argc, char **argv)
+{
+  int i;
+  dInitODE();
+
+  // process the command line args. anything that starts with `-' is assumed
+  // to be a drawstuff argument.
+  for (i=1; i<argc; i++) {
+    if ( argv[i][0]=='-' && argv[i][1]=='i' && argv[i][2]==0) cmd_interactive = 1;
+    else if ( argv[i][0]=='-' && argv[i][1]=='g' && argv[i][2]==0) cmd_graphics = 0;
+    else if ( argv[i][0]=='-' && argv[i][1]=='e' && argv[i][2]==0) cmd_graphics = 0;
+    else if ( argv[i][0]=='-' && argv[i][1]=='n' && isdigit(argv[i][2]) ) {
+      char *endptr;
+      long int n = strtol (&(argv[i][2]),&endptr,10);
+			if (*endptr == 0) cmd_test_num = n;
+		}
+    else
+      cmd_path_to_textures = argv[i];
+  }
+
+  // do the tests
+  if (cmd_test_num == -1) {
+    for (i=0; i<NUM_JOINTS*100; i++) doTest (argc,argv,i,0);
+  }
+  else {
+    doTest (argc,argv,cmd_test_num,1);
+  }
+
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_motor.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_motor.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_motor.cpp	(revision 216)
@@ -0,0 +1,210 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#endif
+
+
+// some constants
+#define SIDE (0.5f)	// side length of a box
+#define MASS (1.0)	// mass of a box
+
+
+// dynamics and collision objects
+static dWorldID world;
+static dBodyID body[2];
+static dGeomID geom[2];
+static dJointID lmotor[2];
+static dJointID amotor[2];
+static dSpaceID space;
+static dJointGroupID contactgroup;
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
+  static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("Press 'q,a,z' to control one axis of lmotor connectiong two bodies. (q is +,a is 0, z is -)\n");
+  printf ("Press 'w,e,r' to control one axis of lmotor connectiong first body with world. (w is +,e is 0, r is -)\n");
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  if (cmd == 'q' || cmd == 'Q') {
+  	dJointSetLMotorParam(lmotor[0],dParamVel,0);
+  	dJointSetLMotorParam(lmotor[0],dParamVel2,0);
+  	dJointSetLMotorParam(lmotor[0],dParamVel3,0.1);
+  } else if (cmd == 'a' || cmd == 'A') {
+  	dJointSetLMotorParam(lmotor[0],dParamVel,0);
+  	dJointSetLMotorParam(lmotor[0],dParamVel2,0);
+  	dJointSetLMotorParam(lmotor[0],dParamVel3,0);
+  } else if (cmd == 'z' || cmd == 'Z') {
+  	dJointSetLMotorParam(lmotor[0],dParamVel,0);
+  	dJointSetLMotorParam(lmotor[0],dParamVel2,0);
+  	dJointSetLMotorParam(lmotor[0],dParamVel3,-0.1);
+  } else if (cmd == 'w' || cmd == 'W') {
+  	dJointSetLMotorParam(lmotor[1],dParamVel,0.1);
+  	dJointSetLMotorParam(lmotor[1],dParamVel2,0);
+  	dJointSetLMotorParam(lmotor[1],dParamVel3,0);
+  } else if (cmd == 'e' || cmd == 'E') {
+  	dJointSetLMotorParam(lmotor[1],dParamVel,0);
+  	dJointSetLMotorParam(lmotor[1],dParamVel2,0);
+  	dJointSetLMotorParam(lmotor[1],dParamVel3,0);
+  } else if (cmd == 'r' || cmd == 'R') {
+  	dJointSetLMotorParam(lmotor[1],dParamVel,-0.1);
+  	dJointSetLMotorParam(lmotor[1],dParamVel2,0);
+  	dJointSetLMotorParam(lmotor[1],dParamVel3,0);
+  }
+  
+}
+
+
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+
+  dContact contact;
+  contact.surface.mode = 0;
+  contact.surface.mu = dInfinity;
+  if (dCollide (o1,o2,1,&contact.geom,sizeof(dContactGeom))) {
+    dJointID c = dJointCreateContact (world,contactgroup,&contact);
+    dJointAttach (c,b1,b2);
+  }
+}
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  if (!pause) {
+    dSpaceCollide(space,0,&nearCallback);
+    dWorldQuickStep (world,0.05);
+	dJointGroupEmpty(contactgroup);
+  }
+
+  dReal sides1[3];
+  dGeomBoxGetLengths(geom[0], sides1);
+  dReal sides2[3];
+  dGeomBoxGetLengths(geom[1], sides2);
+  dsSetTexture (DS_WOOD);
+  dsSetColor (1,1,0);
+  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
+  dsSetColor (0,1,1);
+  dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc>=2)
+  {
+    fn.path_to_textures = argv[1];
+  }
+
+  // create world
+  dInitODE();
+  contactgroup = dJointGroupCreate(0);
+  world = dWorldCreate();
+  space = dSimpleSpaceCreate(0);
+  dMass m;
+  dMassSetBox (&m,1,SIDE,SIDE,SIDE);
+  dMassAdjust (&m,MASS);
+
+  body[0] = dBodyCreate (world);
+  dBodySetMass (body[0],&m);
+  dBodySetPosition (body[0],0,0,1);
+  geom[0] = dCreateBox(space,SIDE,SIDE,SIDE);
+  body[1] = dBodyCreate (world);
+  dBodySetMass (body[1],&m);
+  dBodySetPosition (body[1],0,0,2);
+  geom[1] = dCreateBox(space,SIDE,SIDE,SIDE); 
+
+  dGeomSetBody(geom[0],body[0]);
+  dGeomSetBody(geom[1],body[1]);
+
+  lmotor[0] = dJointCreateLMotor (world,0);
+  dJointAttach (lmotor[0],body[0],body[1]);
+  lmotor[1] = dJointCreateLMotor (world,0);
+  dJointAttach (lmotor[1],body[0],0);
+  amotor[0] = dJointCreateAMotor(world,0);
+  dJointAttach(amotor[0], body[0],body[1]);
+  amotor[1] = dJointCreateAMotor(world,0);
+  dJointAttach(amotor[1], body[0], 0);
+  
+  for (int i=0; i<2; i++) {
+	  dJointSetAMotorNumAxes(amotor[i], 3);
+	  dJointSetAMotorAxis(amotor[i],0,1,1,0,0);
+	  dJointSetAMotorAxis(amotor[i],1,1,0,1,0);
+	  dJointSetAMotorAxis(amotor[i],2,1,0,0,1);
+	  dJointSetAMotorParam(amotor[i],dParamFMax,0.00001);
+	  dJointSetAMotorParam(amotor[i],dParamFMax2,0.00001);
+	  dJointSetAMotorParam(amotor[i],dParamFMax3,0.00001);
+
+	  dJointSetAMotorParam(amotor[i],dParamVel,0);
+	  dJointSetAMotorParam(amotor[i],dParamVel2,0);
+	  dJointSetAMotorParam(amotor[i],dParamVel3,0);
+
+	  dJointSetLMotorNumAxes(lmotor[i],3);
+	  dJointSetLMotorAxis(lmotor[i],0,1,1,0,0);
+	  dJointSetLMotorAxis(lmotor[i],1,1,0,1,0);
+	  dJointSetLMotorAxis(lmotor[i],2,1,0,0,1);
+	 
+	  dJointSetLMotorParam(lmotor[i],dParamFMax,0.0001);
+	  dJointSetLMotorParam(lmotor[i],dParamFMax2,0.0001);
+	  dJointSetLMotorParam(lmotor[i],dParamFMax3,0.0001);
+  }
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy(contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_moving_trimesh.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_moving_trimesh.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_moving_trimesh.cpp	(revision 216)
@@ -0,0 +1,1944 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#define dsDrawLine dsDrawLineD
+#define dsDrawTriangle dsDrawTriangleD
+#endif
+
+
+// some constants
+
+#define NUM 200			// max number of objects
+#define DENSITY (5.0)		// density of all objects
+#define GPB 3			// maximum number of geometries per body
+#define MAX_CONTACTS 64		// maximum number of contact points per body
+
+
+// dynamics and collision objects
+
+struct MyObject {
+  dBodyID body;			// the body
+  dGeomID geom[GPB];		// geometries representing this body
+
+  // Trimesh only - double buffered matrices for 'last transform' setup
+  dReal matrix_dblbuff[ 16 * 2 ];
+  int last_matrix_index;
+};
+
+static int num=0;		// number of objects in simulation
+static int nextobj=0;		// next object to recycle if num==NUM
+static dWorldID world;
+static dSpaceID space;
+static MyObject obj[NUM];
+static dJointGroupID contactgroup;
+static int selected = -1;	// selected object
+static int show_aabb = 0;	// show geom AABBs?
+static int show_contacts = 0;	// show contact points?
+static int random_pos = 1;	// drop objects from random position?
+
+// Bunny mesh ripped from Opcode
+const int VertexCount = 453;
+const int IndexCount = 902 * 3;
+
+typedef dReal dVector3R[3];
+
+dGeomID TriMesh1;
+dGeomID TriMesh2;
+static dTriMeshDataID TriData1, TriData2;  // reusable static trimesh data
+
+float Vertices[VertexCount * 3] = {
+	REAL(-0.334392), REAL(0.133007), REAL(0.062259),
+	REAL(-0.350189), REAL(0.150354), REAL(-0.147769),
+	REAL(-0.234201), REAL(0.343811), REAL(-0.174307),
+	REAL(-0.200259), REAL(0.285207), REAL(0.093749),
+	REAL(0.003520), REAL(0.475208), REAL(-0.159365),
+	REAL(0.001856), REAL(0.419203), REAL(0.098582),
+	REAL(-0.252802), REAL(0.093666), REAL(0.237538),
+	REAL(-0.162901), REAL(0.237984), REAL(0.206905),
+	REAL(0.000865), REAL(0.318141), REAL(0.235370),
+	REAL(-0.414624), REAL(0.164083), REAL(-0.278254),
+	REAL(-0.262213), REAL(0.357334), REAL(-0.293246),
+	REAL(0.004628), REAL(0.482694), REAL(-0.338626),
+	REAL(-0.402162), REAL(0.133528), REAL(-0.443247),
+	REAL(-0.243781), REAL(0.324275), REAL(-0.436763),
+	REAL(0.005293), REAL(0.437592), REAL(-0.458332),
+	REAL(-0.339884), REAL(-0.041150), REAL(-0.668211),
+	REAL(-0.248382), REAL(0.255825), REAL(-0.627493),
+	REAL(0.006261), REAL(0.376103), REAL(-0.631506),
+	REAL(-0.216201), REAL(-0.126776), REAL(-0.886936),
+	REAL(-0.171075), REAL(0.011544), REAL(-0.881386),
+	REAL(-0.181074), REAL(0.098223), REAL(-0.814779),
+	REAL(-0.119891), REAL(0.218786), REAL(-0.760153),
+	REAL(-0.078895), REAL(0.276780), REAL(-0.739281),
+	REAL(0.006801), REAL(0.310959), REAL(-0.735661),
+	REAL(-0.168842), REAL(0.102387), REAL(-0.920381),
+	REAL(-0.104072), REAL(0.177278), REAL(-0.952530),
+	REAL(-0.129704), REAL(0.211848), REAL(-0.836678),
+	REAL(-0.099875), REAL(0.310931), REAL(-0.799381),
+	REAL(0.007237), REAL(0.361687), REAL(-0.794439),
+	REAL(-0.077913), REAL(0.258753), REAL(-0.921640),
+	REAL(0.007957), REAL(0.282241), REAL(-0.931680),
+	REAL(-0.252222), REAL(-0.550401), REAL(-0.557810),
+	REAL(-0.267633), REAL(-0.603419), REAL(-0.655209),
+	REAL(-0.446838), REAL(-0.118517), REAL(-0.466159),
+	REAL(-0.459488), REAL(-0.093017), REAL(-0.311341),
+	REAL(-0.370645), REAL(-0.100108), REAL(-0.159454),
+	REAL(-0.371984), REAL(-0.091991), REAL(-0.011044),
+	REAL(-0.328945), REAL(-0.098269), REAL(0.088659),
+	REAL(-0.282452), REAL(-0.018862), REAL(0.311501),
+	REAL(-0.352403), REAL(-0.131341), REAL(0.144902),
+	REAL(-0.364126), REAL(-0.200299), REAL(0.202388),
+	REAL(-0.283965), REAL(-0.231869), REAL(0.023668),
+	REAL(-0.298943), REAL(-0.155218), REAL(0.369716),
+	REAL(-0.293787), REAL(-0.121856), REAL(0.419097),
+	REAL(-0.290163), REAL(-0.290797), REAL(0.107824),
+	REAL(-0.264165), REAL(-0.272849), REAL(0.036347),
+	REAL(-0.228567), REAL(-0.372573), REAL(0.290309),
+	REAL(-0.190431), REAL(-0.286997), REAL(0.421917),
+	REAL(-0.191039), REAL(-0.240973), REAL(0.507118),
+	REAL(-0.287272), REAL(-0.276431), REAL(-0.065444),
+	REAL(-0.295675), REAL(-0.280818), REAL(-0.174200),
+	REAL(-0.399537), REAL(-0.313131), REAL(-0.376167),
+	REAL(-0.392666), REAL(-0.488581), REAL(-0.427494),
+	REAL(-0.331669), REAL(-0.570185), REAL(-0.466054),
+	REAL(-0.282290), REAL(-0.618140), REAL(-0.589220),
+	REAL(-0.374238), REAL(-0.594882), REAL(-0.323298),
+	REAL(-0.381071), REAL(-0.629723), REAL(-0.350777),
+	REAL(-0.382112), REAL(-0.624060), REAL(-0.221577),
+	REAL(-0.272701), REAL(-0.566522), REAL(0.259157),
+	REAL(-0.256702), REAL(-0.663406), REAL(0.286079),
+	REAL(-0.280948), REAL(-0.428359), REAL(0.055790),
+	REAL(-0.184974), REAL(-0.508894), REAL(0.326265),
+	REAL(-0.279971), REAL(-0.526918), REAL(0.395319),
+	REAL(-0.282599), REAL(-0.663393), REAL(0.412411),
+	REAL(-0.188329), REAL(-0.475093), REAL(0.417954),
+	REAL(-0.263384), REAL(-0.663396), REAL(0.466604),
+	REAL(-0.209063), REAL(-0.663393), REAL(0.509344),
+	REAL(-0.002044), REAL(-0.319624), REAL(0.553078),
+	REAL(-0.001266), REAL(-0.371260), REAL(0.413296),
+	REAL(-0.219753), REAL(-0.339762), REAL(-0.040921),
+	REAL(-0.256986), REAL(-0.282511), REAL(-0.006349),
+	REAL(-0.271706), REAL(-0.260881), REAL(0.001764),
+	REAL(-0.091191), REAL(-0.419184), REAL(-0.045912),
+	REAL(-0.114944), REAL(-0.429752), REAL(-0.124739),
+	REAL(-0.113970), REAL(-0.382987), REAL(-0.188540),
+	REAL(-0.243012), REAL(-0.464942), REAL(-0.242850),
+	REAL(-0.314815), REAL(-0.505402), REAL(-0.324768),
+	REAL(0.002774), REAL(-0.437526), REAL(-0.262766),
+	REAL(-0.072625), REAL(-0.417748), REAL(-0.221440),
+	REAL(-0.160112), REAL(-0.476932), REAL(-0.293450),
+	REAL(0.003859), REAL(-0.453425), REAL(-0.443916),
+	REAL(-0.120363), REAL(-0.581567), REAL(-0.438689),
+	REAL(-0.091499), REAL(-0.584191), REAL(-0.294511),
+	REAL(-0.116469), REAL(-0.599861), REAL(-0.188308),
+	REAL(-0.208032), REAL(-0.513640), REAL(-0.134649),
+	REAL(-0.235749), REAL(-0.610017), REAL(-0.040939),
+	REAL(-0.344916), REAL(-0.622487), REAL(-0.085380),
+	REAL(-0.336401), REAL(-0.531864), REAL(-0.212298),
+	REAL(0.001961), REAL(-0.459550), REAL(-0.135547),
+	REAL(-0.058296), REAL(-0.430536), REAL(-0.043440),
+	REAL(0.001378), REAL(-0.449511), REAL(-0.037762),
+	REAL(-0.130135), REAL(-0.510222), REAL(0.079144),
+	REAL(0.000142), REAL(-0.477549), REAL(0.157064),
+	REAL(-0.114284), REAL(-0.453206), REAL(0.304397),
+	REAL(-0.000592), REAL(-0.443558), REAL(0.285401),
+	REAL(-0.056215), REAL(-0.663402), REAL(0.326073),
+	REAL(-0.026248), REAL(-0.568010), REAL(0.273318),
+	REAL(-0.049261), REAL(-0.531064), REAL(0.389854),
+	REAL(-0.127096), REAL(-0.663398), REAL(0.479316),
+	REAL(-0.058384), REAL(-0.663401), REAL(0.372891),
+	REAL(-0.303961), REAL(0.054199), REAL(0.625921),
+	REAL(-0.268594), REAL(0.193403), REAL(0.502766),
+	REAL(-0.277159), REAL(0.126123), REAL(0.443289),
+	REAL(-0.287605), REAL(-0.005722), REAL(0.531844),
+	REAL(-0.231396), REAL(-0.121289), REAL(0.587387),
+	REAL(-0.253475), REAL(-0.081797), REAL(0.756541),
+	REAL(-0.195164), REAL(-0.137969), REAL(0.728011),
+	REAL(-0.167673), REAL(-0.156573), REAL(0.609388),
+	REAL(-0.145917), REAL(-0.169029), REAL(0.697600),
+	REAL(-0.077776), REAL(-0.214247), REAL(0.622586),
+	REAL(-0.076873), REAL(-0.214971), REAL(0.696301),
+	REAL(-0.002341), REAL(-0.233135), REAL(0.622859),
+	REAL(-0.002730), REAL(-0.213526), REAL(0.691267),
+	REAL(-0.003136), REAL(-0.192628), REAL(0.762731),
+	REAL(-0.056136), REAL(-0.201222), REAL(0.763806),
+	REAL(-0.114589), REAL(-0.166192), REAL(0.770723),
+	REAL(-0.155145), REAL(-0.129632), REAL(0.791738),
+	REAL(-0.183611), REAL(-0.058705), REAL(0.847012),
+	REAL(-0.165562), REAL(0.001980), REAL(0.833386),
+	REAL(-0.220084), REAL(0.019914), REAL(0.768935),
+	REAL(-0.255730), REAL(0.090306), REAL(0.670782),
+	REAL(-0.255594), REAL(0.113833), REAL(0.663389),
+	REAL(-0.226380), REAL(0.212655), REAL(0.617740),
+	REAL(-0.003367), REAL(-0.195342), REAL(0.799680),
+	REAL(-0.029743), REAL(-0.210508), REAL(0.827180),
+	REAL(-0.003818), REAL(-0.194783), REAL(0.873636),
+	REAL(-0.004116), REAL(-0.157907), REAL(0.931268),
+	REAL(-0.031280), REAL(-0.184555), REAL(0.889476),
+	REAL(-0.059885), REAL(-0.184448), REAL(0.841330),
+	REAL(-0.135333), REAL(-0.164332), REAL(0.878200),
+	REAL(-0.085574), REAL(-0.170948), REAL(0.925547),
+	REAL(-0.163833), REAL(-0.094170), REAL(0.897114),
+	REAL(-0.138444), REAL(-0.104250), REAL(0.945975),
+	REAL(-0.083497), REAL(-0.084934), REAL(0.979607),
+	REAL(-0.004433), REAL(-0.146642), REAL(0.985872),
+	REAL(-0.150715), REAL(0.032650), REAL(0.884111),
+	REAL(-0.135892), REAL(-0.035520), REAL(0.945455),
+	REAL(-0.070612), REAL(0.036849), REAL(0.975733),
+	REAL(-0.004458), REAL(-0.042526), REAL(1.015670),
+	REAL(-0.004249), REAL(0.046042), REAL(1.003240),
+	REAL(-0.086969), REAL(0.133224), REAL(0.947633),
+	REAL(-0.003873), REAL(0.161605), REAL(0.970499),
+	REAL(-0.125544), REAL(0.140012), REAL(0.917678),
+	REAL(-0.125651), REAL(0.250246), REAL(0.857602),
+	REAL(-0.003127), REAL(0.284070), REAL(0.878870),
+	REAL(-0.159174), REAL(0.125726), REAL(0.888878),
+	REAL(-0.183807), REAL(0.196970), REAL(0.844480),
+	REAL(-0.159890), REAL(0.291736), REAL(0.732480),
+	REAL(-0.199495), REAL(0.207230), REAL(0.779864),
+	REAL(-0.206182), REAL(0.164608), REAL(0.693257),
+	REAL(-0.186315), REAL(0.160689), REAL(0.817193),
+	REAL(-0.192827), REAL(0.166706), REAL(0.782271),
+	REAL(-0.175112), REAL(0.110008), REAL(0.860621),
+	REAL(-0.161022), REAL(0.057420), REAL(0.855111),
+	REAL(-0.172319), REAL(0.036155), REAL(0.816189),
+	REAL(-0.190318), REAL(0.064083), REAL(0.760605),
+	REAL(-0.195072), REAL(0.129179), REAL(0.731104),
+	REAL(-0.203126), REAL(0.410287), REAL(0.680536),
+	REAL(-0.216677), REAL(0.309274), REAL(0.642272),
+	REAL(-0.241515), REAL(0.311485), REAL(0.587832),
+	REAL(-0.002209), REAL(0.366663), REAL(0.749413),
+	REAL(-0.088230), REAL(0.396265), REAL(0.678635),
+	REAL(-0.170147), REAL(0.109517), REAL(0.840784),
+	REAL(-0.160521), REAL(0.067766), REAL(0.830650),
+	REAL(-0.181546), REAL(0.139805), REAL(0.812146),
+	REAL(-0.180495), REAL(0.148568), REAL(0.776087),
+	REAL(-0.180255), REAL(0.129125), REAL(0.744192),
+	REAL(-0.186298), REAL(0.078308), REAL(0.769352),
+	REAL(-0.167622), REAL(0.060539), REAL(0.806675),
+	REAL(-0.189876), REAL(0.102760), REAL(0.802582),
+	REAL(-0.108340), REAL(0.455446), REAL(0.657174),
+	REAL(-0.241585), REAL(0.527592), REAL(0.669296),
+	REAL(-0.265676), REAL(0.513366), REAL(0.634594),
+	REAL(-0.203073), REAL(0.478550), REAL(0.581526),
+	REAL(-0.266772), REAL(0.642330), REAL(0.602061),
+	REAL(-0.216961), REAL(0.564846), REAL(0.535435),
+	REAL(-0.202210), REAL(0.525495), REAL(0.475944),
+	REAL(-0.193888), REAL(0.467925), REAL(0.520606),
+	REAL(-0.265837), REAL(0.757267), REAL(0.500933),
+	REAL(-0.240306), REAL(0.653440), REAL(0.463215),
+	REAL(-0.309239), REAL(0.776868), REAL(0.304726),
+	REAL(-0.271009), REAL(0.683094), REAL(0.382018),
+	REAL(-0.312111), REAL(0.671099), REAL(0.286687),
+	REAL(-0.268791), REAL(0.624342), REAL(0.377231),
+	REAL(-0.302457), REAL(0.533996), REAL(0.360289),
+	REAL(-0.263656), REAL(0.529310), REAL(0.412564),
+	REAL(-0.282311), REAL(0.415167), REAL(0.447666),
+	REAL(-0.239201), REAL(0.442096), REAL(0.495604),
+	REAL(-0.220043), REAL(0.569026), REAL(0.445877),
+	REAL(-0.001263), REAL(0.395631), REAL(0.602029),
+	REAL(-0.057345), REAL(0.442535), REAL(0.572224),
+	REAL(-0.088927), REAL(0.506333), REAL(0.529106),
+	REAL(-0.125738), REAL(0.535076), REAL(0.612913),
+	REAL(-0.126251), REAL(0.577170), REAL(0.483159),
+	REAL(-0.149594), REAL(0.611520), REAL(0.557731),
+	REAL(-0.163188), REAL(0.660791), REAL(0.491080),
+	REAL(-0.172482), REAL(0.663387), REAL(0.415416),
+	REAL(-0.160464), REAL(0.591710), REAL(0.370659),
+	REAL(-0.156445), REAL(0.536396), REAL(0.378302),
+	REAL(-0.136496), REAL(0.444358), REAL(0.425226),
+	REAL(-0.095564), REAL(0.373768), REAL(0.473659),
+	REAL(-0.104146), REAL(0.315912), REAL(0.498104),
+	REAL(-0.000496), REAL(0.384194), REAL(0.473817),
+	REAL(-0.000183), REAL(0.297770), REAL(0.401486),
+	REAL(-0.129042), REAL(0.270145), REAL(0.434495),
+	REAL(0.000100), REAL(0.272963), REAL(0.349138),
+	REAL(-0.113060), REAL(0.236984), REAL(0.385554),
+	REAL(0.007260), REAL(0.016311), REAL(-0.883396),
+	REAL(0.007865), REAL(0.122104), REAL(-0.956137),
+	REAL(-0.032842), REAL(0.115282), REAL(-0.953252),
+	REAL(-0.089115), REAL(0.108449), REAL(-0.950317),
+	REAL(-0.047440), REAL(0.014729), REAL(-0.882756),
+	REAL(-0.104458), REAL(0.013137), REAL(-0.882070),
+	REAL(-0.086439), REAL(-0.584866), REAL(-0.608343),
+	REAL(-0.115026), REAL(-0.662605), REAL(-0.436732),
+	REAL(-0.071683), REAL(-0.665372), REAL(-0.606385),
+	REAL(-0.257884), REAL(-0.665381), REAL(-0.658052),
+	REAL(-0.272542), REAL(-0.665381), REAL(-0.592063),
+	REAL(-0.371322), REAL(-0.665382), REAL(-0.353620),
+	REAL(-0.372362), REAL(-0.665381), REAL(-0.224420),
+	REAL(-0.335166), REAL(-0.665380), REAL(-0.078623),
+	REAL(-0.225999), REAL(-0.665375), REAL(-0.038981),
+	REAL(-0.106719), REAL(-0.665374), REAL(-0.186351),
+	REAL(-0.081749), REAL(-0.665372), REAL(-0.292554),
+	REAL(0.006943), REAL(-0.091505), REAL(-0.858354),
+	REAL(0.006117), REAL(-0.280985), REAL(-0.769967),
+	REAL(0.004495), REAL(-0.502360), REAL(-0.559799),
+	REAL(-0.198638), REAL(-0.302135), REAL(-0.845816),
+	REAL(-0.237395), REAL(-0.542544), REAL(-0.587188),
+	REAL(-0.270001), REAL(-0.279489), REAL(-0.669861),
+	REAL(-0.134547), REAL(-0.119852), REAL(-0.959004),
+	REAL(-0.052088), REAL(-0.122463), REAL(-0.944549),
+	REAL(-0.124463), REAL(-0.293508), REAL(-0.899566),
+	REAL(-0.047616), REAL(-0.289643), REAL(-0.879292),
+	REAL(-0.168595), REAL(-0.529132), REAL(-0.654931),
+	REAL(-0.099793), REAL(-0.515719), REAL(-0.645873),
+	REAL(-0.186168), REAL(-0.605282), REAL(-0.724690),
+	REAL(-0.112970), REAL(-0.583097), REAL(-0.707469),
+	REAL(-0.108152), REAL(-0.665375), REAL(-0.700408),
+	REAL(-0.183019), REAL(-0.665378), REAL(-0.717630),
+	REAL(-0.349529), REAL(-0.334459), REAL(-0.511985),
+	REAL(-0.141182), REAL(-0.437705), REAL(-0.798194),
+	REAL(-0.212670), REAL(-0.448725), REAL(-0.737447),
+	REAL(-0.261111), REAL(-0.414945), REAL(-0.613835),
+	REAL(-0.077364), REAL(-0.431480), REAL(-0.778113),
+	REAL(0.005174), REAL(-0.425277), REAL(-0.651592),
+	REAL(0.089236), REAL(-0.431732), REAL(-0.777093),
+	REAL(0.271006), REAL(-0.415749), REAL(-0.610577),
+	REAL(0.223981), REAL(-0.449384), REAL(-0.734774),
+	REAL(0.153275), REAL(-0.438150), REAL(-0.796391),
+	REAL(0.358414), REAL(-0.335529), REAL(-0.507649),
+	REAL(0.193434), REAL(-0.665946), REAL(-0.715325),
+	REAL(0.118363), REAL(-0.665717), REAL(-0.699021),
+	REAL(0.123515), REAL(-0.583454), REAL(-0.706020),
+	REAL(0.196851), REAL(-0.605860), REAL(-0.722345),
+	REAL(0.109788), REAL(-0.516035), REAL(-0.644590),
+	REAL(0.178656), REAL(-0.529656), REAL(-0.652804),
+	REAL(0.061157), REAL(-0.289807), REAL(-0.878626),
+	REAL(0.138234), REAL(-0.293905), REAL(-0.897958),
+	REAL(0.066933), REAL(-0.122643), REAL(-0.943820),
+	REAL(0.149571), REAL(-0.120281), REAL(-0.957264),
+	REAL(0.280989), REAL(-0.280321), REAL(-0.666487),
+	REAL(0.246581), REAL(-0.543275), REAL(-0.584224),
+	REAL(0.211720), REAL(-0.302754), REAL(-0.843303),
+	REAL(0.086966), REAL(-0.665627), REAL(-0.291520),
+	REAL(0.110634), REAL(-0.665702), REAL(-0.185021),
+	REAL(0.228099), REAL(-0.666061), REAL(-0.036201),
+	REAL(0.337743), REAL(-0.666396), REAL(-0.074503),
+	REAL(0.376722), REAL(-0.666513), REAL(-0.219833),
+	REAL(0.377265), REAL(-0.666513), REAL(-0.349036),
+	REAL(0.281411), REAL(-0.666217), REAL(-0.588670),
+	REAL(0.267564), REAL(-0.666174), REAL(-0.654834),
+	REAL(0.080745), REAL(-0.665602), REAL(-0.605452),
+	REAL(0.122016), REAL(-0.662963), REAL(-0.435280),
+	REAL(0.095767), REAL(-0.585141), REAL(-0.607228),
+	REAL(0.118944), REAL(0.012799), REAL(-0.880702),
+	REAL(0.061944), REAL(0.014564), REAL(-0.882086),
+	REAL(0.104725), REAL(0.108156), REAL(-0.949130),
+	REAL(0.048513), REAL(0.115159), REAL(-0.952753),
+	REAL(0.112696), REAL(0.236643), REAL(0.386937),
+	REAL(0.128177), REAL(0.269757), REAL(0.436071),
+	REAL(0.102643), REAL(0.315600), REAL(0.499370),
+	REAL(0.094535), REAL(0.373481), REAL(0.474824),
+	REAL(0.136270), REAL(0.443946), REAL(0.426895),
+	REAL(0.157071), REAL(0.535923), REAL(0.380222),
+	REAL(0.161350), REAL(0.591224), REAL(0.372630),
+	REAL(0.173035), REAL(0.662865), REAL(0.417531),
+	REAL(0.162808), REAL(0.660299), REAL(0.493077),
+	REAL(0.148250), REAL(0.611070), REAL(0.559555),
+	REAL(0.125719), REAL(0.576790), REAL(0.484702),
+	REAL(0.123489), REAL(0.534699), REAL(0.614440),
+	REAL(0.087621), REAL(0.506066), REAL(0.530188),
+	REAL(0.055321), REAL(0.442365), REAL(0.572915),
+	REAL(0.219936), REAL(0.568361), REAL(0.448571),
+	REAL(0.238099), REAL(0.441375), REAL(0.498528),
+	REAL(0.281711), REAL(0.414315), REAL(0.451121),
+	REAL(0.263833), REAL(0.528513), REAL(0.415794),
+	REAL(0.303284), REAL(0.533081), REAL(0.363998),
+	REAL(0.269687), REAL(0.623528), REAL(0.380528),
+	REAL(0.314255), REAL(0.670153), REAL(0.290524),
+	REAL(0.272023), REAL(0.682273), REAL(0.385343),
+	REAL(0.311480), REAL(0.775931), REAL(0.308527),
+	REAL(0.240239), REAL(0.652714), REAL(0.466159),
+	REAL(0.265619), REAL(0.756464), REAL(0.504187),
+	REAL(0.192562), REAL(0.467341), REAL(0.522972),
+	REAL(0.201605), REAL(0.524885), REAL(0.478417),
+	REAL(0.215743), REAL(0.564193), REAL(0.538084),
+	REAL(0.264969), REAL(0.641527), REAL(0.605317),
+	REAL(0.201031), REAL(0.477940), REAL(0.584002),
+	REAL(0.263086), REAL(0.512567), REAL(0.637832),
+	REAL(0.238615), REAL(0.526867), REAL(0.672237),
+	REAL(0.105309), REAL(0.455123), REAL(0.658482),
+	REAL(0.183993), REAL(0.102195), REAL(0.804872),
+	REAL(0.161563), REAL(0.060042), REAL(0.808692),
+	REAL(0.180748), REAL(0.077754), REAL(0.771600),
+	REAL(0.175168), REAL(0.128588), REAL(0.746368),
+	REAL(0.175075), REAL(0.148030), REAL(0.778264),
+	REAL(0.175658), REAL(0.139265), REAL(0.814333),
+	REAL(0.154191), REAL(0.067291), REAL(0.832578),
+	REAL(0.163818), REAL(0.109013), REAL(0.842830),
+	REAL(0.084760), REAL(0.396004), REAL(0.679695),
+	REAL(0.238888), REAL(0.310760), REAL(0.590775),
+	REAL(0.213380), REAL(0.308625), REAL(0.644905),
+	REAL(0.199666), REAL(0.409678), REAL(0.683003),
+	REAL(0.190143), REAL(0.128597), REAL(0.733463),
+	REAL(0.184833), REAL(0.063516), REAL(0.762902),
+	REAL(0.166070), REAL(0.035644), REAL(0.818261),
+	REAL(0.154361), REAL(0.056943), REAL(0.857042),
+	REAL(0.168542), REAL(0.109489), REAL(0.862725),
+	REAL(0.187387), REAL(0.166131), REAL(0.784599),
+	REAL(0.180428), REAL(0.160135), REAL(0.819438),
+	REAL(0.201823), REAL(0.163991), REAL(0.695756),
+	REAL(0.194206), REAL(0.206635), REAL(0.782275),
+	REAL(0.155438), REAL(0.291260), REAL(0.734412),
+	REAL(0.177696), REAL(0.196424), REAL(0.846693),
+	REAL(0.152305), REAL(0.125256), REAL(0.890786),
+	REAL(0.119546), REAL(0.249876), REAL(0.859104),
+	REAL(0.118369), REAL(0.139643), REAL(0.919173),
+	REAL(0.079410), REAL(0.132973), REAL(0.948652),
+	REAL(0.062419), REAL(0.036648), REAL(0.976547),
+	REAL(0.127847), REAL(-0.035919), REAL(0.947070),
+	REAL(0.143624), REAL(0.032206), REAL(0.885913),
+	REAL(0.074888), REAL(-0.085173), REAL(0.980577),
+	REAL(0.130184), REAL(-0.104656), REAL(0.947620),
+	REAL(0.156201), REAL(-0.094653), REAL(0.899074),
+	REAL(0.077366), REAL(-0.171194), REAL(0.926545),
+	REAL(0.127722), REAL(-0.164729), REAL(0.879810),
+	REAL(0.052670), REAL(-0.184618), REAL(0.842019),
+	REAL(0.023477), REAL(-0.184638), REAL(0.889811),
+	REAL(0.022626), REAL(-0.210587), REAL(0.827500),
+	REAL(0.223089), REAL(0.211976), REAL(0.620493),
+	REAL(0.251444), REAL(0.113067), REAL(0.666494),
+	REAL(0.251419), REAL(0.089540), REAL(0.673887),
+	REAL(0.214360), REAL(0.019258), REAL(0.771595),
+	REAL(0.158999), REAL(0.001490), REAL(0.835374),
+	REAL(0.176696), REAL(-0.059249), REAL(0.849218),
+	REAL(0.148696), REAL(-0.130091), REAL(0.793599),
+	REAL(0.108290), REAL(-0.166528), REAL(0.772088),
+	REAL(0.049820), REAL(-0.201382), REAL(0.764454),
+	REAL(0.071341), REAL(-0.215195), REAL(0.697209),
+	REAL(0.073148), REAL(-0.214475), REAL(0.623510),
+	REAL(0.140502), REAL(-0.169461), REAL(0.699354),
+	REAL(0.163374), REAL(-0.157073), REAL(0.611416),
+	REAL(0.189466), REAL(-0.138550), REAL(0.730366),
+	REAL(0.247593), REAL(-0.082554), REAL(0.759610),
+	REAL(0.227468), REAL(-0.121982), REAL(0.590197),
+	REAL(0.284702), REAL(-0.006586), REAL(0.535347),
+	REAL(0.275741), REAL(0.125287), REAL(0.446676),
+	REAL(0.266650), REAL(0.192594), REAL(0.506044),
+	REAL(0.300086), REAL(0.053287), REAL(0.629620),
+	REAL(0.055450), REAL(-0.663935), REAL(0.375065),
+	REAL(0.122854), REAL(-0.664138), REAL(0.482323),
+	REAL(0.046520), REAL(-0.531571), REAL(0.391918),
+	REAL(0.024824), REAL(-0.568450), REAL(0.275106),
+	REAL(0.053855), REAL(-0.663931), REAL(0.328224),
+	REAL(0.112829), REAL(-0.453549), REAL(0.305788),
+	REAL(0.131265), REAL(-0.510617), REAL(0.080746),
+	REAL(0.061174), REAL(-0.430716), REAL(-0.042710),
+	REAL(0.341019), REAL(-0.532887), REAL(-0.208150),
+	REAL(0.347705), REAL(-0.623533), REAL(-0.081139),
+	REAL(0.238040), REAL(-0.610732), REAL(-0.038037),
+	REAL(0.211764), REAL(-0.514274), REAL(-0.132078),
+	REAL(0.120605), REAL(-0.600219), REAL(-0.186856),
+	REAL(0.096985), REAL(-0.584476), REAL(-0.293357),
+	REAL(0.127621), REAL(-0.581941), REAL(-0.437170),
+	REAL(0.165902), REAL(-0.477425), REAL(-0.291453),
+	REAL(0.077720), REAL(-0.417975), REAL(-0.220519),
+	REAL(0.320892), REAL(-0.506363), REAL(-0.320874),
+	REAL(0.248214), REAL(-0.465684), REAL(-0.239842),
+	REAL(0.118764), REAL(-0.383338), REAL(-0.187114),
+	REAL(0.118816), REAL(-0.430106), REAL(-0.123307),
+	REAL(0.094131), REAL(-0.419464), REAL(-0.044777),
+	REAL(0.274526), REAL(-0.261706), REAL(0.005110),
+	REAL(0.259842), REAL(-0.283292), REAL(-0.003185),
+	REAL(0.222861), REAL(-0.340431), REAL(-0.038210),
+	REAL(0.204445), REAL(-0.664380), REAL(0.513353),
+	REAL(0.259286), REAL(-0.664547), REAL(0.471281),
+	REAL(0.185402), REAL(-0.476020), REAL(0.421718),
+	REAL(0.279163), REAL(-0.664604), REAL(0.417328),
+	REAL(0.277157), REAL(-0.528122), REAL(0.400208),
+	REAL(0.183069), REAL(-0.509812), REAL(0.329995),
+	REAL(0.282599), REAL(-0.429210), REAL(0.059242),
+	REAL(0.254816), REAL(-0.664541), REAL(0.290687),
+	REAL(0.271436), REAL(-0.567707), REAL(0.263966),
+	REAL(0.386561), REAL(-0.625221), REAL(-0.216870),
+	REAL(0.387086), REAL(-0.630883), REAL(-0.346073),
+	REAL(0.380021), REAL(-0.596021), REAL(-0.318679),
+	REAL(0.291269), REAL(-0.619007), REAL(-0.585707),
+	REAL(0.339280), REAL(-0.571198), REAL(-0.461946),
+	REAL(0.400045), REAL(-0.489778), REAL(-0.422640),
+	REAL(0.406817), REAL(-0.314349), REAL(-0.371230),
+	REAL(0.300588), REAL(-0.281718), REAL(-0.170549),
+	REAL(0.290866), REAL(-0.277304), REAL(-0.061905),
+	REAL(0.187735), REAL(-0.241545), REAL(0.509437),
+	REAL(0.188032), REAL(-0.287569), REAL(0.424234),
+	REAL(0.227520), REAL(-0.373262), REAL(0.293102),
+	REAL(0.266526), REAL(-0.273650), REAL(0.039597),
+	REAL(0.291592), REAL(-0.291676), REAL(0.111386),
+	REAL(0.291914), REAL(-0.122741), REAL(0.422683),
+	REAL(0.297574), REAL(-0.156119), REAL(0.373368),
+	REAL(0.286603), REAL(-0.232731), REAL(0.027162),
+	REAL(0.364663), REAL(-0.201399), REAL(0.206850),
+	REAL(0.353855), REAL(-0.132408), REAL(0.149228),
+	REAL(0.282208), REAL(-0.019715), REAL(0.314960),
+	REAL(0.331187), REAL(-0.099266), REAL(0.092701),
+	REAL(0.375463), REAL(-0.093120), REAL(-0.006467),
+	REAL(0.375917), REAL(-0.101236), REAL(-0.154882),
+	REAL(0.466635), REAL(-0.094416), REAL(-0.305669),
+	REAL(0.455805), REAL(-0.119881), REAL(-0.460632),
+	REAL(0.277465), REAL(-0.604242), REAL(-0.651871),
+	REAL(0.261022), REAL(-0.551176), REAL(-0.554667),
+	REAL(0.093627), REAL(0.258494), REAL(-0.920589),
+	REAL(0.114248), REAL(0.310608), REAL(-0.798070),
+	REAL(0.144232), REAL(0.211434), REAL(-0.835001),
+	REAL(0.119916), REAL(0.176940), REAL(-0.951159),
+	REAL(0.184061), REAL(0.101854), REAL(-0.918220),
+	REAL(0.092431), REAL(0.276521), REAL(-0.738231),
+	REAL(0.133504), REAL(0.218403), REAL(-0.758602),
+	REAL(0.194987), REAL(0.097655), REAL(-0.812476),
+	REAL(0.185542), REAL(0.011005), REAL(-0.879202),
+	REAL(0.230315), REAL(-0.127450), REAL(-0.884202),
+	REAL(0.260471), REAL(0.255056), REAL(-0.624378),
+	REAL(0.351567), REAL(-0.042194), REAL(-0.663976),
+	REAL(0.253742), REAL(0.323524), REAL(-0.433716),
+	REAL(0.411612), REAL(0.132299), REAL(-0.438264),
+	REAL(0.270513), REAL(0.356530), REAL(-0.289984),
+	REAL(0.422146), REAL(0.162819), REAL(-0.273130),
+	REAL(0.164724), REAL(0.237490), REAL(0.208912),
+	REAL(0.253806), REAL(0.092900), REAL(0.240640),
+	REAL(0.203608), REAL(0.284597), REAL(0.096223),
+	REAL(0.241006), REAL(0.343093), REAL(-0.171396),
+	REAL(0.356076), REAL(0.149288), REAL(-0.143443),
+	REAL(0.337656), REAL(0.131992), REAL(0.066374)
+};
+
+int Indices[IndexCount / 3][3] = {
+	{126,134,133},
+	{342,138,134},
+	{133,134,138},
+	{126,342,134},
+	{312,316,317},
+	{169,163,162},
+	{312,317,319},
+	{312,319,318},
+	{169,162,164},
+	{169,168,163},
+	{312,314,315},
+	{169,164,165},
+	{169,167,168},
+	{312,315,316},
+	{312,313,314},
+	{169,165,166},
+	{169,166,167},
+	{312,318,313},
+	{308,304,305},
+	{308,305,306},
+	{179,181,188},
+	{177,173,175},
+	{177,175,176},
+	{302,293,300},
+	{322,294,304},
+	{188,176,175},
+	{188,175,179},
+	{158,177,187},
+	{305,293,302},
+	{305,302,306},
+	{322,304,308},
+	{188,181,183},
+	{158,173,177},
+	{293,298,300},
+	{304,294,296},
+	{304,296,305},
+	{185,176,188},
+	{185,188,183},
+	{187,177,176},
+	{187,176,185},
+	{305,296,298},
+	{305,298,293},
+	{436,432, 28},
+	{436, 28, 23},
+	{434,278,431},
+	{ 30,208,209},
+	{ 30,209, 29},
+	{ 19, 20, 24},
+	{208,207,211},
+	{208,211,209},
+	{ 19,210,212},
+	{433,434,431},
+	{433,431,432},
+	{433,432,436},
+	{436,437,433},
+	{277,275,276},
+	{277,276,278},
+	{209,210, 25},
+	{ 21, 26, 24},
+	{ 21, 24, 20},
+	{ 25, 26, 27},
+	{ 25, 27, 29},
+	{435,439,277},
+	{439,275,277},
+	{432,431, 30},
+	{432, 30, 28},
+	{433,437,438},
+	{433,438,435},
+	{434,277,278},
+	{ 24, 25,210},
+	{ 24, 26, 25},
+	{ 29, 27, 28},
+	{ 29, 28, 30},
+	{ 19, 24,210},
+	{208, 30,431},
+	{208,431,278},
+	{435,434,433},
+	{435,277,434},
+	{ 25, 29,209},
+	{ 27, 22, 23},
+	{ 27, 23, 28},
+	{ 26, 22, 27},
+	{ 26, 21, 22},
+	{212,210,209},
+	{212,209,211},
+	{207,208,278},
+	{207,278,276},
+	{439,435,438},
+	{ 12,  9, 10},
+	{ 12, 10, 13},
+	{  2,  3,  5},
+	{  2,  5,  4},
+	{ 16, 13, 14},
+	{ 16, 14, 17},
+	{ 22, 21, 16},
+	{ 13, 10, 11},
+	{ 13, 11, 14},
+	{  1,  0,  3},
+	{  1,  3,  2},
+	{ 15, 12, 16},
+	{ 19, 18, 15},
+	{ 19, 15, 16},
+	{ 19, 16, 20},
+	{  9,  1,  2},
+	{  9,  2, 10},
+	{  3,  7,  8},
+	{  3,  8,  5},
+	{ 16, 17, 23},
+	{ 16, 23, 22},
+	{ 21, 20, 16},
+	{ 10,  2,  4},
+	{ 10,  4, 11},
+	{  0,  6,  7},
+	{  0,  7,  3},
+	{ 12, 13, 16},
+	{451,446,445},
+	{451,445,450},
+	{442,440,439},
+	{442,439,438},
+	{442,438,441},
+	{421,420,422},
+	{412,411,426},
+	{412,426,425},
+	{408,405,407},
+	{413, 67, 68},
+	{413, 68,414},
+	{391,390,412},
+	{ 80,384,386},
+	{404,406,378},
+	{390,391,377},
+	{390,377, 88},
+	{400,415,375},
+	{398,396,395},
+	{398,395,371},
+	{398,371,370},
+	{112,359,358},
+	{112,358,113},
+	{351,352,369},
+	{125,349,348},
+	{345,343,342},
+	{342,340,339},
+	{341,335,337},
+	{328,341,327},
+	{331,323,333},
+	{331,322,323},
+	{327,318,319},
+	{327,319,328},
+	{315,314,324},
+	{302,300,301},
+	{302,301,303},
+	{320,311,292},
+	{285,284,289},
+	{310,307,288},
+	{310,288,290},
+	{321,350,281},
+	{321,281,282},
+	{423,448,367},
+	{272,273,384},
+	{272,384,274},
+	{264,265,382},
+	{264,382,383},
+	{440,442,261},
+	{440,261,263},
+	{252,253,254},
+	{252,254,251},
+	{262,256,249},
+	{262,249,248},
+	{228,243,242},
+	{228, 31,243},
+	{213,215,238},
+	{213,238,237},
+	{ 19,212,230},
+	{224,225,233},
+	{224,233,231},
+	{217,218, 56},
+	{217, 56, 54},
+	{217,216,239},
+	{217,239,238},
+	{217,238,215},
+	{218,217,215},
+	{218,215,214},
+	{  6,102,206},
+	{186,199,200},
+	{197,182,180},
+	{170,171,157},
+	{201,200,189},
+	{170,190,191},
+	{170,191,192},
+	{175,174,178},
+	{175,178,179},
+	{168,167,155},
+	{122,149,158},
+	{122,158,159},
+	{135,153,154},
+	{135,154,118},
+	{143,140,141},
+	{143,141,144},
+	{132,133,136},
+	{130,126,133},
+	{124,125,127},
+	{122,101,100},
+	{122,100,121},
+	{110,108,107},
+	{110,107,109},
+	{ 98, 99, 97},
+	{ 98, 97, 64},
+	{ 98, 64, 66},
+	{ 87, 55, 57},
+	{ 83, 82, 79},
+	{ 83, 79, 84},
+	{ 78, 74, 50},
+	{ 49, 71, 41},
+	{ 49, 41, 37},
+	{ 49, 37, 36},
+	{ 58, 44, 60},
+	{ 60, 59, 58},
+	{ 51, 34, 33},
+	{ 39, 40, 42},
+	{ 39, 42, 38},
+	{243,240, 33},
+	{243, 33,229},
+	{ 39, 38,  6},
+	{ 44, 46, 40},
+	{ 55, 56, 57},
+	{ 64, 62, 65},
+	{ 64, 65, 66},
+	{ 41, 71, 45},
+	{ 75, 50, 51},
+	{ 81, 79, 82},
+	{ 77, 88, 73},
+	{ 93, 92, 94},
+	{ 68, 47, 46},
+	{ 96, 97, 99},
+	{ 96, 99, 95},
+	{110,109,111},
+	{111,112,110},
+	{114,113,123},
+	{114,123,124},
+	{132,131,129},
+	{133,137,136},
+	{135,142,145},
+	{145,152,135},
+	{149,147,157},
+	{157,158,149},
+	{164,150,151},
+	{153,163,168},
+	{153,168,154},
+	{185,183,182},
+	{185,182,184},
+	{161,189,190},
+	{200,199,191},
+	{200,191,190},
+	{180,178,195},
+	{180,195,196},
+	{102,101,204},
+	{102,204,206},
+	{ 43, 48,104},
+	{ 43,104,103},
+	{216,217, 54},
+	{216, 54, 32},
+	{207,224,231},
+	{230,212,211},
+	{230,211,231},
+	{227,232,241},
+	{227,241,242},
+	{235,234,241},
+	{235,241,244},
+	{430,248,247},
+	{272,274,253},
+	{272,253,252},
+	{439,260,275},
+	{225,224,259},
+	{225,259,257},
+	{269,270,407},
+	{269,407,405},
+	{270,269,273},
+	{270,273,272},
+	{273,269,268},
+	{273,268,267},
+	{273,267,266},
+	{273,266,265},
+	{273,265,264},
+	{448,279,367},
+	{281,350,368},
+	{285,286,301},
+	{290,323,310},
+	{290,311,323},
+	{282,281,189},
+	{292,311,290},
+	{292,290,291},
+	{307,306,302},
+	{307,302,303},
+	{316,315,324},
+	{316,324,329},
+	{331,351,350},
+	{330,334,335},
+	{330,335,328},
+	{341,337,338},
+	{344,355,354},
+	{346,345,348},
+	{346,348,347},
+	{364,369,352},
+	{364,352,353},
+	{365,363,361},
+	{365,361,362},
+	{376,401,402},
+	{373,372,397},
+	{373,397,400},
+	{376, 92,377},
+	{381,378,387},
+	{381,387,385},
+	{386, 77, 80},
+	{390,389,412},
+	{416,417,401},
+	{403,417,415},
+	{408,429,430},
+	{419,423,418},
+	{427,428,444},
+	{427,444,446},
+	{437,436,441},
+	{450,445, 11},
+	{450, 11,  4},
+	{447,449,  5},
+	{447,  5,  8},
+	{441,438,437},
+	{425,426,451},
+	{425,451,452},
+	{417,421,415},
+	{408,407,429},
+	{399,403,400},
+	{399,400,397},
+	{394,393,416},
+	{389,411,412},
+	{386,383,385},
+	{408,387,378},
+	{408,378,406},
+	{377,391,376},
+	{ 94,375,415},
+	{372,373,374},
+	{372,374,370},
+	{359,111,360},
+	{359,112,111},
+	{113,358,349},
+	{113,349,123},
+	{346,343,345},
+	{343,340,342},
+	{338,336,144},
+	{338,144,141},
+	{327,341,354},
+	{327,354,326},
+	{331,350,321},
+	{331,321,322},
+	{314,313,326},
+	{314,326,325},
+	{300,298,299},
+	{300,299,301},
+	{288,287,289},
+	{189,292,282},
+	{287,288,303},
+	{284,285,297},
+	{368,280,281},
+	{448,447,279},
+	{274,226,255},
+	{267,268,404},
+	{267,404,379},
+	{429,262,430},
+	{439,440,260},
+	{257,258,249},
+	{257,249,246},
+	{430,262,248},
+	{234,228,242},
+	{234,242,241},
+	{237,238,239},
+	{237,239,236},
+	{ 15, 18,227},
+	{ 15,227,229},
+	{222,223, 82},
+	{222, 82, 83},
+	{214,215,213},
+	{214,213, 81},
+	{ 38,102,  6},
+	{122,159,200},
+	{122,200,201},
+	{174,171,192},
+	{174,192,194},
+	{197,193,198},
+	{190,170,161},
+	{181,179,178},
+	{181,178,180},
+	{166,156,155},
+	{163,153,152},
+	{163,152,162},
+	{120,156,149},
+	{120,149,121},
+	{152,153,135},
+	{140,143,142},
+	{135,131,132},
+	{135,132,136},
+	{130,129,128},
+	{130,128,127},
+	{100,105,119},
+	{100,119,120},
+	{106,104,107},
+	{106,107,108},
+	{ 91, 95, 59},
+	{ 93, 94, 68},
+	{ 91, 89, 92},
+	{ 76, 53, 55},
+	{ 76, 55, 87},
+	{ 81, 78, 79},
+	{ 74, 73, 49},
+	{ 69, 60, 45},
+	{ 58, 62, 64},
+	{ 58, 64, 61},
+	{ 53, 31, 32},
+	{ 32, 54, 53},
+	{ 42, 43, 38},
+	{ 35, 36,  0},
+	{ 35,  0,  1},
+	{ 34, 35,  1},
+	{ 34,  1,  9},
+	{ 44, 40, 41},
+	{ 44, 41, 45},
+	{ 33,240, 51},
+	{ 63, 62, 58},
+	{ 63, 58, 59},
+	{ 45, 71, 70},
+	{ 76, 75, 51},
+	{ 76, 51, 52},
+	{ 86, 85, 84},
+	{ 86, 84, 87},
+	{ 89, 72, 73},
+	{ 89, 73, 88},
+	{ 91, 92, 96},
+	{ 91, 96, 95},
+	{ 72, 91, 60},
+	{ 72, 60, 69},
+	{104,106,105},
+	{119,105,117},
+	{119,117,118},
+	{124,127,128},
+	{117,116,129},
+	{117,129,131},
+	{118,117,131},
+	{135,140,142},
+	{146,150,152},
+	{146,152,145},
+	{149,122,121},
+	{166,165,151},
+	{166,151,156},
+	{158,172,173},
+	{161,160,189},
+	{199,198,193},
+	{199,193,191},
+	{204,201,202},
+	{178,174,194},
+	{200,159,186},
+	{109, 48, 67},
+	{ 48,107,104},
+	{216, 32,236},
+	{216,236,239},
+	{223,214, 81},
+	{223, 81, 82},
+	{ 33, 12, 15},
+	{ 32,228,234},
+	{ 32,234,236},
+	{240, 31, 52},
+	{256,255,246},
+	{256,246,249},
+	{258,263,248},
+	{258,248,249},
+	{275,260,259},
+	{275,259,276},
+	{207,276,259},
+	{270,271,429},
+	{270,429,407},
+	{413,418,366},
+	{413,366,365},
+	{368,367,279},
+	{368,279,280},
+	{303,301,286},
+	{303,286,287},
+	{283,282,292},
+	{283,292,291},
+	{320,292,189},
+	{298,296,297},
+	{298,297,299},
+	{318,327,326},
+	{318,326,313},
+	{329,330,317},
+	{336,333,320},
+	{326,354,353},
+	{334,332,333},
+	{334,333,336},
+	{342,339,139},
+	{342,139,138},
+	{345,342,126},
+	{347,357,356},
+	{369,368,351},
+	{363,356,357},
+	{363,357,361},
+	{366,367,368},
+	{366,368,369},
+	{375,373,400},
+	{ 92, 90,377},
+	{409,387,408},
+	{386,385,387},
+	{386,387,388},
+	{412,394,391},
+	{396,398,399},
+	{408,406,405},
+	{415,421,419},
+	{415,419,414},
+	{425,452,448},
+	{425,448,424},
+	{444,441,443},
+	{448,452,449},
+	{448,449,447},
+	{446,444,443},
+	{446,443,445},
+	{250,247,261},
+	{250,261,428},
+	{421,422,423},
+	{421,423,419},
+	{427,410,250},
+	{417,403,401},
+	{403,402,401},
+	{420,392,412},
+	{420,412,425},
+	{420,425,424},
+	{386,411,389},
+	{383,382,381},
+	{383,381,385},
+	{378,379,404},
+	{372,371,395},
+	{372,395,397},
+	{371,372,370},
+	{361,359,360},
+	{361,360,362},
+	{368,350,351},
+	{349,347,348},
+	{356,355,344},
+	{356,344,346},
+	{344,341,340},
+	{344,340,343},
+	{338,337,336},
+	{328,335,341},
+	{324,352,351},
+	{324,351,331},
+	{320,144,336},
+	{314,325,324},
+	{322,308,309},
+	{310,309,307},
+	{287,286,289},
+	{203,280,279},
+	{203,279,205},
+	{297,295,283},
+	{297,283,284},
+	{447,205,279},
+	{274,384, 80},
+	{274, 80,226},
+	{266,267,379},
+	{266,379,380},
+	{225,257,246},
+	{225,246,245},
+	{256,254,253},
+	{256,253,255},
+	{430,247,250},
+	{226,235,244},
+	{226,244,245},
+	{232,233,244},
+	{232,244,241},
+	{230, 18, 19},
+	{ 32, 31,228},
+	{219,220, 86},
+	{219, 86, 57},
+	{226,213,235},
+	{206,  7,  6},
+	{122,201,101},
+	{201,204,101},
+	{180,196,197},
+	{170,192,171},
+	{200,190,189},
+	{194,193,195},
+	{183,181,180},
+	{183,180,182},
+	{155,154,168},
+	{149,156,151},
+	{149,151,148},
+	{155,156,120},
+	{145,142,143},
+	{145,143,146},
+	{136,137,140},
+	{133,132,130},
+	{128,129,116},
+	{100,120,121},
+	{110,112,113},
+	{110,113,114},
+	{ 66, 65, 63},
+	{ 66, 63, 99},
+	{ 66, 99, 98},
+	{ 96, 46, 61},
+	{ 89, 88, 90},
+	{ 86, 87, 57},
+	{ 80, 78, 81},
+	{ 72, 69, 49},
+	{ 67, 48, 47},
+	{ 67, 47, 68},
+	{ 56, 55, 53},
+	{ 50, 49, 36},
+	{ 50, 36, 35},
+	{ 40, 39, 41},
+	{242,243,229},
+	{242,229,227},
+	{  6, 37, 39},
+	{ 42, 47, 48},
+	{ 42, 48, 43},
+	{ 61, 46, 44},
+	{ 45, 70, 69},
+	{ 69, 70, 71},
+	{ 69, 71, 49},
+	{ 74, 78, 77},
+	{ 83, 84, 85},
+	{ 73, 74, 77},
+	{ 93, 96, 92},
+	{ 68, 46, 93},
+	{ 95, 99, 63},
+	{ 95, 63, 59},
+	{115,108,110},
+	{115,110,114},
+	{125,126,127},
+	{129,130,132},
+	{137,133,138},
+	{137,138,139},
+	{148,146,143},
+	{148,143,147},
+	{119,118,154},
+	{161,147,143},
+	{165,164,151},
+	{158,157,171},
+	{158,171,172},
+	{159,158,187},
+	{159,187,186},
+	{194,192,191},
+	{194,191,193},
+	{189,202,201},
+	{182,197,184},
+	{205,  8,  7},
+	{ 48,109,107},
+	{218,219, 57},
+	{218, 57, 56},
+	{207,231,211},
+	{232,230,231},
+	{232,231,233},
+	{ 53, 52, 31},
+	{388,411,386},
+	{409,430,250},
+	{262,429,254},
+	{262,254,256},
+	{442,444,428},
+	{273,264,383},
+	{273,383,384},
+	{429,271,251},
+	{429,251,254},
+	{413,365,362},
+	{ 67,413,360},
+	{282,283,295},
+	{285,301,299},
+	{202,281,280},
+	{284,283,291},
+	{284,291,289},
+	{320,189,160},
+	{308,306,307},
+	{307,309,308},
+	{319,317,330},
+	{319,330,328},
+	{353,352,324},
+	{332,331,333},
+	{340,341,338},
+	{354,341,344},
+	{349,358,357},
+	{349,357,347},
+	{364,355,356},
+	{364,356,363},
+	{364,365,366},
+	{364,366,369},
+	{374,376,402},
+	{375, 92,373},
+	{ 77,389,390},
+	{382,380,381},
+	{389, 77,386},
+	{393,394,412},
+	{393,412,392},
+	{401,394,416},
+	{415,400,403},
+	{411,410,427},
+	{411,427,426},
+	{422,420,424},
+	{247,248,263},
+	{247,263,261},
+	{445,443, 14},
+	{445, 14, 11},
+	{449,450,  4},
+	{449,  4,  5},
+	{443,441, 17},
+	{443, 17, 14},
+	{436, 23, 17},
+	{436, 17,441},
+	{424,448,422},
+	{448,423,422},
+	{414,419,418},
+	{414,418,413},
+	{406,404,405},
+	{399,397,395},
+	{399,395,396},
+	{420,416,392},
+	{388,410,411},
+	{386,384,383},
+	{390, 88, 77},
+	{375, 94, 92},
+	{415,414, 68},
+	{415, 68, 94},
+	{370,374,402},
+	{370,402,398},
+	{361,357,358},
+	{361,358,359},
+	{125,348,126},
+	{346,344,343},
+	{340,338,339},
+	{337,335,334},
+	{337,334,336},
+	{325,353,324},
+	{324,331,332},
+	{324,332,329},
+	{323,322,309},
+	{323,309,310},
+	{294,295,297},
+	{294,297,296},
+	{289,286,285},
+	{202,280,203},
+	{288,307,303},
+	{282,295,321},
+	{ 67,360,111},
+	{418,423,367},
+	{418,367,366},
+	{272,252,251},
+	{272,251,271},
+	{272,271,270},
+	{255,253,274},
+	{265,266,380},
+	{265,380,382},
+	{442,428,261},
+	{440,263,258},
+	{440,258,260},
+	{409,250,410},
+	{255,226,245},
+	{255,245,246},
+	{ 31,240,243},
+	{236,234,235},
+	{236,235,237},
+	{233,225,245},
+	{233,245,244},
+	{220,221, 85},
+	{220, 85, 86},
+	{ 81,213,226},
+	{ 81,226, 80},
+	{  7,206,205},
+	{186,184,198},
+	{186,198,199},
+	{204,203,205},
+	{204,205,206},
+	{195,193,196},
+	{171,174,172},
+	{173,174,175},
+	{173,172,174},
+	{155,167,166},
+	{160,161,143},
+	{160,143,144},
+	{119,154,155},
+	{148,151,150},
+	{148,150,146},
+	{140,137,139},
+	{140,139,141},
+	{127,126,130},
+	{114,124,128},
+	{114,128,115},
+	{117,105,106},
+	{117,106,116},
+	{104,105,100},
+	{104,100,103},
+	{ 59, 60, 91},
+	{ 97, 96, 61},
+	{ 97, 61, 64},
+	{ 91, 72, 89},
+	{ 87, 84, 79},
+	{ 87, 79, 76},
+	{ 78, 80, 77},
+	{ 49, 50, 74},
+	{ 60, 44, 45},
+	{ 61, 44, 58},
+	{ 51, 50, 35},
+	{ 51, 35, 34},
+	{ 39, 37, 41},
+	{ 33, 34,  9},
+	{ 33,  9, 12},
+	{  0, 36, 37},
+	{  0, 37,  6},
+	{ 40, 46, 47},
+	{ 40, 47, 42},
+	{ 53, 54, 56},
+	{ 65, 62, 63},
+	{ 72, 49, 73},
+	{ 79, 78, 75},
+	{ 79, 75, 76},
+	{ 52, 53, 76},
+	{ 92, 89, 90},
+	{ 96, 93, 46},
+	{102,103,100},
+	{102,100,101},
+	{116,106,108},
+	{116,108,115},
+	{123,125,124},
+	{116,115,128},
+	{118,131,135},
+	{140,135,136},
+	{148,147,149},
+	{120,119,155},
+	{164,162,152},
+	{164,152,150},
+	{157,147,161},
+	{157,161,170},
+	{186,187,185},
+	{186,185,184},
+	{193,197,196},
+	{202,203,204},
+	{194,195,178},
+	{198,184,197},
+	{ 67,111,109},
+	{ 38, 43,103},
+	{ 38,103,102},
+	{214,223,222},
+	{214,222,221},
+	{214,221,220},
+	{214,220,219},
+	{214,219,218},
+	{213,237,235},
+	{221,222, 83},
+	{221, 83, 85},
+	{ 15,229, 33},
+	{227, 18,230},
+	{227,230,232},
+	{ 52, 51,240},
+	{ 75, 78, 50},
+	{408,430,409},
+	{260,258,257},
+	{260,257,259},
+	{224,207,259},
+	{268,269,405},
+	{268,405,404},
+	{413,362,360},
+	{447,  8,205},
+	{299,297,285},
+	{189,281,202},
+	{290,288,289},
+	{290,289,291},
+	{322,321,295},
+	{322,295,294},
+	{333,323,311},
+	{333,311,320},
+	{317,316,329},
+	{320,160,144},
+	{353,325,326},
+	{329,332,334},
+	{329,334,330},
+	{339,338,141},
+	{339,141,139},
+	{348,345,126},
+	{347,356,346},
+	{123,349,125},
+	{364,353,354},
+	{364,354,355},
+	{365,364,363},
+	{376,391,394},
+	{376,394,401},
+	{ 92,376,374},
+	{ 92,374,373},
+	{377, 90, 88},
+	{380,379,378},
+	{380,378,381},
+	{388,387,409},
+	{388,409,410},
+	{416,393,392},
+	{399,398,402},
+	{399,402,403},
+	{250,428,427},
+	{421,417,416},
+	{421,416,420},
+	{426,427,446},
+	{426,446,451},
+	{444,442,441},
+	{452,451,450},
+	{452,450,449}
+};
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+  // if (o1->body && o2->body) return;
+
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+
+  dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
+  for (i=0; i<MAX_CONTACTS; i++) {
+    contact[i].surface.mode = dContactBounce | dContactSoftCFM;
+    contact[i].surface.mu = dInfinity;
+    contact[i].surface.mu2 = 0;
+    contact[i].surface.bounce = 0.1;
+    contact[i].surface.bounce_vel = 0.1;
+    contact[i].surface.soft_cfm = 0.01;
+  }
+  if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
+			   sizeof(dContact))) {
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    const dReal ss[3] = {0.02,0.02,0.02};
+    for (i=0; i<numc; i++) {
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+      if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("To drop another object, press:\n");
+  printf ("   b for box.\n");
+  printf ("   s for sphere.\n");
+  printf ("   y for cylinder.\n");
+  printf ("   c for capsule.\n");
+  printf ("   x for a composite object.\n");
+  printf ("   m for a trimesh.\n");
+  printf ("To select an object, press space.\n");
+  printf ("To disable the selected object, press d.\n");
+  printf ("To enable the selected object, press e.\n");
+  printf ("To toggle showing the geom AABBs, press a.\n");
+  printf ("To toggle showing the contact points, press t.\n");
+  printf ("To toggle dropping from random position/orientation, press r.\n");
+}
+
+
+char locase (char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+  else return c;
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  int i,j,k;
+  dReal sides[3];
+  dMass m;
+
+  cmd = locase (cmd);
+  if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'm' || cmd == 'y' ) {
+    if (num < NUM) {
+      i = num;
+      num++;
+    }
+    else {
+      i = nextobj;
+      nextobj++;
+      if (nextobj >= num) nextobj = 0;
+
+      // destroy the body and geoms for slot i
+      dBodyDestroy (obj[i].body);
+      for (k=0; k < GPB; k++) {
+	if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+      }
+      memset (&obj[i],0,sizeof(obj[i]));
+    }
+
+    obj[i].body = dBodyCreate (world);
+    for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+    dMatrix3 R;
+    if (random_pos) {
+      dBodySetPosition (obj[i].body,
+			dRandReal()*2-1,dRandReal()*2-1,dRandReal()+3);
+      dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			  dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+    }
+    else {
+      dReal maxheight = 0;
+      for (k=0; k<num; k++) {
+	const dReal *pos = dBodyGetPosition (obj[k].body);
+	if (pos[2] > maxheight) maxheight = pos[2];
+      }
+      dBodySetPosition (obj[i].body, 0,0,maxheight+1);
+      dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
+    }
+    dBodySetRotation (obj[i].body,R);
+    dBodySetData (obj[i].body,(void*)(size_t)i);
+
+    if (cmd == 'b') {
+      dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+      obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+    }
+    else if (cmd == 'c') {
+      sides[0] *= 0.5;
+      dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
+    }
+    else if (cmd == 'y') {
+      sides[1] *= 0.5;
+      dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
+    }
+	else if (cmd == 's') {
+      sides[0] *= 0.5;
+      dMassSetSphere (&m,DENSITY,sides[0]);
+      obj[i].geom[0] = dCreateSphere (space,sides[0]);
+    }
+    else if (cmd == 'm') {
+      dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate();
+      dGeomTriMeshDataBuildSingle(new_tmdata, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
+
+      obj[i].geom[0] = dCreateTriMesh(space, new_tmdata, 0, 0, 0);
+
+      // remember the mesh's dTriMeshDataID on its userdata for convenience.
+      dGeomSetData(obj[i].geom[0], new_tmdata);
+
+      dMassSetTrimesh( &m, DENSITY, obj[i].geom[0] );
+      printf("mass at %f %f %f\n", m.c[0], m.c[1], m.c[2]);
+      dGeomSetPosition(obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2]);
+      dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);
+    }
+    else if (cmd == 'x') {
+      dGeomID g2[GPB];		// encapsulated geometries
+      dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+      // start accumulating masses for the encapsulated geometries
+      dMass m2;
+      dMassSetZero (&m);
+
+      // set random delta positions
+      for (j=0; j<GPB; j++) {
+	for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+      }
+
+      for (k=0; k<GPB; k++) {
+	obj[i].geom[k] = dCreateGeomTransform (space);
+	dGeomTransformSetCleanup (obj[i].geom[k],1);
+	if (k==0) {
+	  dReal radius = dRandReal()*0.25+0.05;
+	  g2[k] = dCreateSphere (0,radius);
+	  dMassSetSphere (&m2,DENSITY,radius);
+	}
+	else if (k==1) {
+	  g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+	  dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+	}
+	else {
+	  dReal radius = dRandReal()*0.1+0.05;
+	  dReal length = dRandReal()*1.0+0.1;
+	  g2[k] = dCreateCapsule (0,radius,length);
+	  dMassSetCapsule (&m2,DENSITY,3,radius,length);
+	}
+	dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+	// set the transformation (adjust the mass too)
+	dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMatrix3 Rtx;
+	dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+	dGeomSetRotation (g2[k],Rtx);
+	dMassRotate (&m2,Rtx);
+
+	// add to the total mass
+	dMassAdd (&m,&m2);
+      }
+
+      // move all encapsulated objects so that the center of mass is (0,0,0)
+      for (k=0; k<2; k++) {
+	dGeomSetPosition (g2[k],
+			  dpos[k][0]-m.c[0],
+			  dpos[k][1]-m.c[1],
+			  dpos[k][2]-m.c[2]);
+      }
+      dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+    }
+
+    for (k=0; k < GPB; k++) {
+      if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+    }
+
+    dBodySetMass (obj[i].body,&m);
+  }
+
+  if (cmd == ' ') {
+    selected++;
+    if (selected >= num) selected = 0;
+    if (selected < 0) selected = 0;
+  }
+  else if (cmd == 'd' && selected >= 0 && selected < num) {
+    dBodyDisable (obj[selected].body);
+  }
+  else if (cmd == 'e' && selected >= 0 && selected < num) {
+    dBodyEnable (obj[selected].body);
+  }
+  else if (cmd == 'a') {
+    show_aabb ^= 1;
+  }
+  else if (cmd == 't') {
+    show_contacts ^= 1;
+  }
+  else if (cmd == 'r') {
+    random_pos ^= 1;
+  }
+}
+
+
+// draw a geom
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
+{
+  if (!g) return;
+  if (!pos) pos = dGeomGetPosition (g);
+  if (!R) R = dGeomGetRotation (g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass) {
+    dVector3 sides;
+    dGeomBoxGetLengths (g,sides);
+    dsDrawBox (pos,R,sides);
+  }
+  else if (type == dSphereClass) {
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+  }
+  else if (type == dCapsuleClass) {
+    dReal radius,length;
+    dGeomCapsuleGetParams (g,&radius,&length);
+    dsDrawCapsule (pos,R,length,radius);
+  }
+  else if (type == dCylinderClass) {
+    dReal radius,length;
+    dGeomCylinderGetParams (g,&radius,&length);
+    dsDrawCylinder (pos,R,length,radius);
+  }
+
+  else if (type == dGeomTransformClass) {
+    dGeomID g2 = dGeomTransformGetGeom (g);
+    const dReal *pos2 = dGeomGetPosition (g2);
+    const dReal *R2 = dGeomGetRotation (g2);
+    dVector3 actual_pos;
+    dMatrix3 actual_R;
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+    actual_pos[0] += pos[0];
+    actual_pos[1] += pos[1];
+    actual_pos[2] += pos[2];
+    dMULTIPLY0_333 (actual_R,R,R2);
+    drawGeom (g2,actual_pos,actual_R,0);
+  }
+
+  if (show_aabb) {
+    // draw the bounding box for this geom
+    dReal aabb[6];
+    dGeomGetAABB (g,aabb);
+    dVector3 bbpos;
+    for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+    dVector3 bbsides;
+    for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    dsSetColorAlpha (1,0,0,0.5);
+    dsDrawBox (bbpos,RI,bbsides);
+  }
+}
+
+
+// set previous transformation matrix for trimesh
+void setCurrentTransform(dGeomID geom)
+{
+ const dReal* Pos = dGeomGetPosition(geom);
+ const dReal* Rot = dGeomGetRotation(geom);
+
+ const dReal Transform[16] = 
+ {
+   Rot[0], Rot[4], Rot[8],  0,
+   Rot[1], Rot[5], Rot[9],  0,
+   Rot[2], Rot[6], Rot[10], 0,
+   Pos[0], Pos[1], Pos[2],  1
+ };
+
+ dGeomTriMeshSetLastTransform( geom, *(dMatrix4*)(&Transform) );
+
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  dsSetColor (0,0,2);
+  dSpaceCollide (space,0,&nearCallback);
+
+
+#if 0
+  // What is this for??? - Bram
+  if (!pause) 
+  {
+    for (int i=0; i<num; i++)
+      for (int j=0; j < GPB; j++)
+        if (obj[i].geom[j])
+          if (dGeomGetClass(obj[i].geom[j]) == dTriMeshClass)
+            setCurrentTransform(obj[i].geom[j]);
+ 
+    setCurrentTransform(TriMesh1);
+    setCurrentTransform(TriMesh2);
+  }
+#endif
+
+  //if (!pause) dWorldStep (world,0.05);
+  if (!pause) dWorldStepFast1 (world,0.05, 5);
+
+  for (int j = 0; j < dSpaceGetNumGeoms(space); j++){
+	  dSpaceGetGeom(space, j);
+  }
+
+  // remove all contact joints
+  dJointGroupEmpty (contactgroup);
+
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+  for (int i=0; i<num; i++) {
+    for (int j=0; j < GPB; j++) {
+      if (obj[i].geom[j]) {
+        if (i==selected) {
+          dsSetColor (0,0.7,1);
+        }
+        else if (! dBodyIsEnabled (obj[i].body)) {
+          dsSetColor (1,0,0);
+        }
+        else {
+          dsSetColor (1,1,0);
+        }
+      
+        if (dGeomGetClass(obj[i].geom[j]) == dTriMeshClass) {
+          int* Indices = (int*)::Indices;
+
+          // assume all trimeshes are drawn as bunnies
+          const dReal* Pos = dGeomGetPosition(obj[i].geom[j]);
+          const dReal* Rot = dGeomGetRotation(obj[i].geom[j]);
+        
+          for (int ii = 0; ii < IndexCount / 3; ii++) {
+            const dReal v[9] = { // explicit conversion from float to dReal
+              Vertices[Indices[ii * 3 + 0] * 3 + 0],
+              Vertices[Indices[ii * 3 + 0] * 3 + 1],
+              Vertices[Indices[ii * 3 + 0] * 3 + 2],
+              Vertices[Indices[ii * 3 + 1] * 3 + 0],
+              Vertices[Indices[ii * 3 + 1] * 3 + 1],
+              Vertices[Indices[ii * 3 + 1] * 3 + 2],
+              Vertices[Indices[ii * 3 + 2] * 3 + 0],
+              Vertices[Indices[ii * 3 + 2] * 3 + 1],
+              Vertices[Indices[ii * 3 + 2] * 3 + 2]
+            };
+            dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 1);
+          }
+
+          // tell the tri-tri collider the current transform of the trimesh --
+          // this is fairly important for good results.
+          
+		  // Fill in the (4x4) matrix.
+		  dReal* p_matrix = obj[i].matrix_dblbuff + ( obj[i].last_matrix_index * 16 );
+
+		  p_matrix[ 0 ] = Rot[ 0 ];	p_matrix[ 1 ] = Rot[ 1 ];	p_matrix[ 2 ] = Rot[ 2 ];	p_matrix[ 3 ] = 0;
+		  p_matrix[ 4 ] = Rot[ 4 ];	p_matrix[ 5 ] = Rot[ 5 ];	p_matrix[ 6 ] = Rot[ 6 ];	p_matrix[ 7 ] = 0;
+		  p_matrix[ 8 ] = Rot[ 8 ];	p_matrix[ 9 ] = Rot[ 9 ];	p_matrix[10 ] = Rot[10 ];	p_matrix[11 ] = 0;
+		  p_matrix[12 ] = Pos[ 0 ];	p_matrix[13 ] = Pos[ 1 ];	p_matrix[14 ] = Pos[ 2 ];	p_matrix[15 ] = 1;
+
+		  // Flip to other matrix.
+		  obj[i].last_matrix_index = !obj[i].last_matrix_index;
+
+		  dGeomTriMeshSetLastTransform( obj[i].geom[j], 
+			  *(dMatrix4*)( obj[i].matrix_dblbuff + obj[i].last_matrix_index * 16 ) );
+  
+        } else {
+          drawGeom (obj[i].geom[j],0,0,show_aabb);
+        }
+      }
+    }
+  }
+
+  int* Indices = (int*)::Indices;
+
+  {const dReal* Pos = dGeomGetPosition(TriMesh1);
+  const dReal* Rot = dGeomGetRotation(TriMesh1);
+
+  {for (int i = 0; i < IndexCount / 3; i++){
+    const dReal v[9] = { // explicit conversion from float to dReal
+      Vertices[Indices[i * 3 + 0] * 3 + 0],
+      Vertices[Indices[i * 3 + 0] * 3 + 1],
+      Vertices[Indices[i * 3 + 0] * 3 + 2],
+      Vertices[Indices[i * 3 + 1] * 3 + 0],
+      Vertices[Indices[i * 3 + 1] * 3 + 1],
+      Vertices[Indices[i * 3 + 1] * 3 + 2],
+      Vertices[Indices[i * 3 + 2] * 3 + 0],
+      Vertices[Indices[i * 3 + 2] * 3 + 1],
+      Vertices[Indices[i * 3 + 2] * 3 + 2]
+    };
+    dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 0);
+  }}}
+
+  {const dReal* Pos = dGeomGetPosition(TriMesh2);
+  const dReal* Rot = dGeomGetRotation(TriMesh2);
+
+  {for (int i = 0; i < IndexCount / 3; i++){
+    const dReal v[9] = { // explicit conversion from float to dReal
+      Vertices[Indices[i * 3 + 0] * 3 + 0],
+      Vertices[Indices[i * 3 + 0] * 3 + 1],
+      Vertices[Indices[i * 3 + 0] * 3 + 2],
+      Vertices[Indices[i * 3 + 1] * 3 + 0],
+      Vertices[Indices[i * 3 + 1] * 3 + 1],
+      Vertices[Indices[i * 3 + 1] * 3 + 2],
+      Vertices[Indices[i * 3 + 2] * 3 + 0],
+      Vertices[Indices[i * 3 + 2] * 3 + 1],
+      Vertices[Indices[i * 3 + 2] * 3 + 2]
+    };
+    dsDrawTriangle(Pos, Rot, &v[0], &v[3], &v[6], 1);
+  }}}
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+ 
+  space = dSimpleSpaceCreate(0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  dWorldSetCFM (world,1e-5);
+  dCreatePlane (space,0,0,1,0);
+  memset (obj,0,sizeof(obj));
+
+  // note: can't share tridata if intending to trimesh-trimesh collide
+  TriData1 = dGeomTriMeshDataCreate();
+  dGeomTriMeshDataBuildSingle(TriData1, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
+  TriData2 = dGeomTriMeshDataCreate();
+  dGeomTriMeshDataBuildSingle(TriData2, &Vertices[0], 3 * sizeof(float), VertexCount, (int*)&Indices[0], IndexCount, 3 * sizeof(int));
+  
+  TriMesh1 = dCreateTriMesh(space, TriData1, 0, 0, 0);
+  TriMesh2 = dCreateTriMesh(space, TriData2, 0, 0, 0);
+  dGeomSetData(TriMesh1, TriData1);
+  dGeomSetData(TriMesh2, TriData2);
+  
+  {dGeomSetPosition(TriMesh1, 0, 0, 0.9);
+  dMatrix3 Rotation;
+  dRFromAxisAndAngle(Rotation, 1, 0, 0, M_PI / 2);
+  dGeomSetRotation(TriMesh1, Rotation);}
+
+  {dGeomSetPosition(TriMesh2, 1, 0, 0.9);
+  dMatrix3 Rotation;
+  dRFromAxisAndAngle(Rotation, 1, 0, 0, M_PI / 2);
+  dGeomSetRotation(TriMesh2, Rotation);}
+  
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_ode.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_ode.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_ode.cpp	(revision 216)
@@ -0,0 +1,1128 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <setjmp.h>
+#include <ode/ode.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+//****************************************************************************
+// matrix accessors
+
+#define _A(i,j) A[(i)*4+(j)]
+#define _I(i,j) I[(i)*4+(j)]
+#define _R(i,j) R[(i)*4+(j)]
+
+//****************************************************************************
+// tolerances
+
+#ifdef dDOUBLE
+const double tol = 1e-10;
+#endif
+
+#ifdef dSINGLE
+const double tol = 1e-5;
+#endif
+
+//****************************************************************************
+// misc messages and error handling
+
+#ifdef __GNUC__
+#define HEADER printf ("%s()\n", __FUNCTION__);
+#else
+#define HEADER printf ("%s:%d\n",__FILE__,__LINE__);
+#endif
+
+static jmp_buf jump_buffer;
+
+
+void myMessageFunction (int num, const char *msg, va_list ap)
+{
+  printf ("(Message %d: ",num);
+  vprintf (msg,ap);
+  printf (")");
+  dSetMessageHandler (0);
+  longjmp (jump_buffer,1);
+}
+
+
+#define TRAP_MESSAGE(do,ifnomsg,ifmsg) \
+  dSetMessageHandler (&myMessageFunction); \
+  if (setjmp (jump_buffer)) { \
+    dSetMessageHandler (0); \
+    ifmsg ; \
+  } \
+  else { \
+    dSetMessageHandler (&myMessageFunction); \
+    do ; \
+    ifnomsg ; \
+  } \
+  dSetMessageHandler (0);
+
+//****************************************************************************
+// utility stuff
+
+// compare two numbers, within a threshhold, return 1 if approx equal
+
+int cmp (dReal a, dReal b)
+{
+  return (fabs(a-b) < tol);
+}
+
+//****************************************************************************
+// matrix utility stuff
+
+// compare a 3x3 matrix with the identity
+
+int cmpIdentityMat3 (dMatrix3 A)
+{
+  return
+    (cmp(_A(0,0),1.0) && cmp(_A(0,1),0.0) && cmp(_A(0,2),0.0) &&
+     cmp(_A(1,0),0.0) && cmp(_A(1,1),1.0) && cmp(_A(1,2),0.0) &&
+     cmp(_A(2,0),0.0) && cmp(_A(2,1),0.0) && cmp(_A(2,2),1.0));
+}
+
+
+// transpose a 3x3 matrix in-line
+
+void transpose3x3 (dMatrix3 A)
+{
+  dReal tmp;
+  tmp=A[4]; A[4]=A[1]; A[1]=tmp;
+  tmp=A[8]; A[8]=A[2]; A[2]=tmp;
+  tmp=A[9]; A[9]=A[6]; A[6]=tmp;
+}
+
+//****************************************************************************
+// test miscellaneous math functions
+
+void testRandomNumberGenerator()
+{
+  HEADER;
+  if (dTestRand()) printf ("\tpassed\n");
+  else printf ("\tFAILED\n");
+}
+
+
+void testInfinity()
+{
+  HEADER;
+  if (1e10 < dInfinity && -1e10 > -dInfinity && -dInfinity < dInfinity)
+    printf ("\tpassed\n");
+  else printf ("\tFAILED\n");
+}
+
+
+void testPad()
+{
+  HEADER;
+  char s[100];
+  s[0]=0;
+  for (int i=0; i<=16; i++) sprintf (s+strlen(s),"%d ",dPAD(i));
+  printf ("\t%s\n", strcmp(s,"0 1 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16 ") ?
+	  "FAILED" : "passed");
+}
+
+
+void testCrossProduct()
+{
+  HEADER;
+
+  dVector3 a1,a2,b,c;
+  dMatrix3 B;
+  dMakeRandomVector (b,3,1.0);
+  dMakeRandomVector (c,3,1.0);
+
+  dCROSS (a1,=,b,c);
+
+  dSetZero (B,12);
+  dCROSSMAT (B,b,4,+,-);
+  dMultiply0 (a2,B,c,3,3,1);
+
+  dReal diff = dMaxDifference(a1,a2,3,1);
+  printf ("\t%s\n", diff > tol ? "FAILED" : "passed");
+}
+
+
+void testSetZero()
+{
+  HEADER;
+  dReal a[100];
+  dMakeRandomVector (a,100,1.0);
+  dSetZero (a,100);
+  for (int i=0; i<100; i++) if (a[i] != 0.0) {
+    printf ("\tFAILED\n");
+    return;
+  }
+  printf ("\tpassed\n");
+}
+
+
+void testNormalize3()
+{
+  HEADER;
+  int i,j,bad=0;
+  dVector3 n1,n2;
+  for (i=0; i<1000; i++) {
+    dMakeRandomVector (n1,3,1.0);
+    for (j=0; j<3; j++) n2[j]=n1[j];
+    dNormalize3 (n2);
+    if (dFabs(dDOT(n2,n2) - 1.0) > tol) bad |= 1;
+    if (dFabs(n2[0]/n1[0] - n2[1]/n1[1]) > tol) bad |= 2;
+    if (dFabs(n2[0]/n1[0] - n2[2]/n1[2]) > tol) bad |= 4;
+    if (dFabs(n2[1]/n1[1] - n2[2]/n1[2]) > tol) bad |= 8;
+    if (dFabs(dDOT(n2,n1) - dSqrt(dDOT(n1,n1))) > tol) bad |= 16;
+    if (bad) {
+      printf ("\tFAILED (code=%x)\n",bad);
+      return;
+    }
+  }
+  printf ("\tpassed\n");
+}
+
+
+/*
+void testReorthonormalize()
+{
+  HEADER;
+  dMatrix3 R,I;
+  dMakeRandomMatrix (R,3,3,1.0);
+  for (int i=0; i<30; i++) dReorthonormalize (R);
+  dMultiply2 (I,R,R,3,3,3);
+  printf ("\t%s\n",cmpIdentityMat3 (I) ? "passed" : "FAILED");
+}
+*/
+
+
+void testPlaneSpace()
+{
+  HEADER;
+  dVector3 n,p,q;
+  int bad = 0;
+  for (int i=0; i<1000; i++) {
+    dMakeRandomVector (n,3,1.0);
+    dNormalize3 (n);
+    dPlaneSpace (n,p,q);
+    if (fabs(dDOT(n,p)) > tol) bad = 1;
+    if (fabs(dDOT(n,q)) > tol) bad = 1;
+    if (fabs(dDOT(p,q)) > tol) bad = 1;
+    if (fabs(dDOT(p,p)-1) > tol) bad = 1;
+    if (fabs(dDOT(q,q)-1) > tol) bad = 1;
+  }
+  printf ("\t%s\n", bad ? "FAILED" : "passed");
+}
+
+//****************************************************************************
+// test matrix functions
+
+#define MSIZE 21
+#define MSIZE4 24	// MSIZE rounded up to 4
+
+
+void testMatrixMultiply()
+{
+  // A is 2x3, B is 3x4, B2 is B except stored columnwise, C is 2x4
+  dReal A[8],B[12],A2[12],B2[16],C[8];
+  int i;
+
+  HEADER;
+  dSetZero (A,8);
+  for (i=0; i<3; i++) A[i] = i+2;
+  for (i=0; i<3; i++) A[i+4] = i+3+2;
+  for (i=0; i<12; i++) B[i] = i+8;
+  dSetZero (A2,12);
+  for (i=0; i<6; i++) A2[i+2*(i/2)] = A[i+i/3];
+  dSetZero (B2,16);
+  for (i=0; i<12; i++) B2[i+i/3] = B[i];
+
+  dMultiply0 (C,A,B,2,3,4);
+  if (C[0] != 116 || C[1] != 125 || C[2] != 134 || C[3] != 143 ||
+      C[4] != 224 || C[5] != 242 || C[6] != 260 || C[7] != 278)
+    printf ("\tFAILED (1)\n"); else printf ("\tpassed (1)\n");
+
+  dMultiply1 (C,A2,B,2,3,4);
+  if (C[0] != 160 || C[1] != 172 || C[2] != 184 || C[3] != 196 ||
+      C[4] != 196 || C[5] != 211 || C[6] != 226 || C[7] != 241)
+    printf ("\tFAILED (2)\n"); else printf ("\tpassed (2)\n");
+
+  dMultiply2 (C,A,B2,2,3,4);
+  if (C[0] != 83 || C[1] != 110 || C[2] != 137 || C[3] != 164 ||
+      C[4] != 164 || C[5] != 218 || C[6] != 272 || C[7] != 326)
+    printf ("\tFAILED (3)\n"); else printf ("\tpassed (3)\n");
+}
+
+
+void testSmallMatrixMultiply()
+{
+  dMatrix3 A,B,C,A2;
+  dVector3 a,a2,x;
+
+  HEADER;
+  dMakeRandomMatrix (A,3,3,1.0);
+  dMakeRandomMatrix (B,3,3,1.0);
+  dMakeRandomMatrix (C,3,3,1.0);
+  dMakeRandomMatrix (x,3,1,1.0);
+
+  // dMULTIPLY0_331()
+  dMULTIPLY0_331 (a,B,x);
+  dMultiply0 (a2,B,x,3,3,1);
+  printf ("\t%s (1)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" :
+	  "passed");
+
+  // dMULTIPLY1_331()
+  dMULTIPLY1_331 (a,B,x);
+  dMultiply1 (a2,B,x,3,3,1);
+  printf ("\t%s (2)\n",(dMaxDifference (a,a2,3,1) > tol) ? "FAILED" :
+	  "passed");
+
+  // dMULTIPLY0_133
+  dMULTIPLY0_133 (a,x,B);
+  dMultiply0 (a2,x,B,1,3,3);
+  printf ("\t%s (3)\n",(dMaxDifference (a,a2,1,3) > tol) ? "FAILED" :
+	  "passed");
+
+  // dMULTIPLY0_333()
+  dMULTIPLY0_333 (A,B,C);
+  dMultiply0 (A2,B,C,3,3,3);
+  printf ("\t%s (4)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
+	  "passed");
+
+  // dMULTIPLY1_333()
+  dMULTIPLY1_333 (A,B,C);
+  dMultiply1 (A2,B,C,3,3,3);
+  printf ("\t%s (5)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
+	  "passed");
+
+  // dMULTIPLY2_333()
+  dMULTIPLY2_333 (A,B,C);
+  dMultiply2 (A2,B,C,3,3,3);
+  printf ("\t%s (6)\n",(dMaxDifference (A,A2,3,3) > tol) ? "FAILED" :
+	  "passed");
+}
+
+
+void testCholeskyFactorization()
+{
+  dReal A[MSIZE4*MSIZE], B[MSIZE4*MSIZE], C[MSIZE4*MSIZE], diff;
+  HEADER;
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,B,MSIZE4*MSIZE*sizeof(dReal));
+  if (dFactorCholesky (B,MSIZE)) printf ("\tpassed (1)\n");
+  else printf ("\tFAILED (1)\n");
+  dClearUpperTriangle (B,MSIZE);
+  dMultiply2 (C,B,B,MSIZE,MSIZE,MSIZE);
+  diff = dMaxDifference(A,C,MSIZE,MSIZE);
+  printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
+	  diff > tol ? "FAILED" : "passed");
+}
+
+
+void testCholeskySolve()
+{
+  dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], b[MSIZE],x[MSIZE],btest[MSIZE],diff;
+  HEADER;
+
+  // get A,L = PD matrix
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
+
+  // get b,x = right hand side
+  dMakeRandomMatrix (b,MSIZE,1,1.0);
+  memcpy (x,b,MSIZE*sizeof(dReal));
+
+  // factor L
+  if (dFactorCholesky (L,MSIZE)) printf ("\tpassed (1)\n");
+  else printf ("\tFAILED (1)\n");
+  dClearUpperTriangle (L,MSIZE);
+
+  // solve A*x = b
+  dSolveCholesky (L,x,MSIZE);
+
+  // compute A*x and compare it with b
+  dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
+  diff = dMaxDifference(b,btest,MSIZE,1);
+  printf ("\tmaximum difference = %.6e - %s (2)\n",diff,
+	  diff > tol ? "FAILED" : "passed");
+}
+
+
+void testInvertPDMatrix()
+{
+  int i,j,ok;
+  dReal A[MSIZE4*MSIZE], Ainv[MSIZE4*MSIZE], I[MSIZE4*MSIZE];
+  HEADER;
+
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (Ainv,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,Ainv,MSIZE4*MSIZE*sizeof(dReal));
+  dSetZero (Ainv,MSIZE4*MSIZE);
+
+  if (dInvertPDMatrix (A,Ainv,MSIZE))
+    printf ("\tpassed (1)\n"); else printf ("\tFAILED (1)\n");
+  dMultiply0 (I,A,Ainv,MSIZE,MSIZE,MSIZE);
+
+  // compare with identity
+  ok = 1;
+  for (i=0; i<MSIZE; i++) {
+    for (j=0; j<MSIZE; j++) {
+      if (i != j) if (cmp (I[i*MSIZE4+j],0.0)==0) ok = 0;
+    }
+  }
+  for (i=0; i<MSIZE; i++) {
+    if (cmp (I[i*MSIZE4+i],1.0)==0) ok = 0;
+  }
+  if (ok) printf ("\tpassed (2)\n"); else printf ("\tFAILED (2)\n");
+}
+
+
+void testIsPositiveDefinite()
+{
+  dReal A[MSIZE4*MSIZE], B[MSIZE4*MSIZE];
+  HEADER;
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (B,A,A,MSIZE,MSIZE,MSIZE);
+  printf ("\t%s\n",dIsPositiveDefinite(A,MSIZE) ? "FAILED (1)":"passed (1)");
+  printf ("\t%s\n",dIsPositiveDefinite(B,MSIZE) ? "passed (2)":"FAILED (2)");
+}
+
+
+void testFastLDLTFactorization()
+{
+  int i,j;
+  dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], DL[MSIZE4*MSIZE],
+    ATEST[MSIZE4*MSIZE], d[MSIZE], diff;
+  HEADER;
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
+
+  dFactorLDLT (L,d,MSIZE,MSIZE4);
+  dClearUpperTriangle (L,MSIZE);
+  for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
+
+  dSetZero (DL,MSIZE4*MSIZE);
+  for (i=0; i<MSIZE; i++) {
+    for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
+  }
+
+  dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
+  diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
+  printf ("\tmaximum difference = %.6e - %s\n",diff,
+	  diff > tol ? "FAILED" : "passed");
+}
+
+
+void testSolveLDLT()
+{
+  dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE], x[MSIZE],
+    b[MSIZE], btest[MSIZE], diff;
+  HEADER;
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
+
+  dMakeRandomMatrix (b,MSIZE,1,1.0);
+  memcpy (x,b,MSIZE*sizeof(dReal));
+
+  dFactorLDLT (L,d,MSIZE,MSIZE4);
+  dSolveLDLT (L,d,x,MSIZE,MSIZE4);
+
+  dMultiply2 (btest,A,x,MSIZE,MSIZE,1);
+  diff = dMaxDifference(b,btest,MSIZE,1);
+  printf ("\tmaximum difference = %.6e - %s\n",diff,
+	  diff > tol ? "FAILED" : "passed");
+}
+
+
+void testLDLTAddTL()
+{
+  int i,j;
+  dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE], a[MSIZE],
+    DL[MSIZE4*MSIZE], ATEST[MSIZE4*MSIZE], diff;
+  HEADER;
+
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
+  dFactorLDLT (L,d,MSIZE,MSIZE4);
+
+  // delete first row and column of factorization
+  for (i=0; i<MSIZE; i++) a[i] = -A[i*MSIZE4];
+  a[0] += 1;
+  dLDLTAddTL (L,d,a,MSIZE,MSIZE4);
+  for (i=1; i<MSIZE; i++) L[i*MSIZE4] = 0;
+  d[0] = 1;
+
+  // get modified L*D*L'
+  dClearUpperTriangle (L,MSIZE);
+  for (i=0; i<MSIZE; i++) L[i*MSIZE4+i] = 1.0;
+  dSetZero (DL,MSIZE4*MSIZE);
+  for (i=0; i<MSIZE; i++) {
+    for (j=0; j<MSIZE; j++) DL[i*MSIZE4+j] = L[i*MSIZE4+j] / d[j];
+  }
+  dMultiply2 (ATEST,L,DL,MSIZE,MSIZE,MSIZE);
+
+  // compare it to A with its first row/column removed
+  for (i=1; i<MSIZE; i++) A[i*MSIZE4] = A[i] = 0;
+  A[0] = 1;
+  diff = dMaxDifference(A,ATEST,MSIZE,MSIZE);
+  printf ("\tmaximum difference = %.6e - %s\n",diff,
+	  diff > tol ? "FAILED" : "passed");
+}
+
+
+void testLDLTRemove()
+{
+  int i,j,r,p[MSIZE];
+  dReal A[MSIZE4*MSIZE], L[MSIZE4*MSIZE], d[MSIZE],
+    L2[MSIZE4*MSIZE], d2[MSIZE], DL2[MSIZE4*MSIZE],
+    Atest1[MSIZE4*MSIZE], Atest2[MSIZE4*MSIZE], diff, maxdiff;
+  HEADER;
+
+  // make array of A row pointers
+  dReal *Arows[MSIZE];
+  for (i=0; i<MSIZE; i++) Arows[i] = A+i*MSIZE4;
+
+  // fill permutation vector
+  for (i=0; i<MSIZE; i++) p[i]=i;
+
+  dMakeRandomMatrix (A,MSIZE,MSIZE,1.0);
+  dMultiply2 (L,A,A,MSIZE,MSIZE,MSIZE);
+  memcpy (A,L,MSIZE4*MSIZE*sizeof(dReal));
+  dFactorLDLT (L,d,MSIZE,MSIZE4);
+
+  maxdiff = 1e10;
+  for (r=0; r<MSIZE; r++) {
+    // get Atest1 = A with row/column r removed
+    memcpy (Atest1,A,MSIZE4*MSIZE*sizeof(dReal));
+    dRemoveRowCol (Atest1,MSIZE,MSIZE4,r);
+
+    // test that the row/column removal worked
+    int bad = 0;
+    for (i=0; i<MSIZE; i++) {
+      for (j=0; j<MSIZE; j++) {
+	if (i != r && j != r) {
+	  int ii = i;
+	  int jj = j;
+	  if (ii >= r) ii--;
+	  if (jj >= r) jj--;
+	  if (A[i*MSIZE4+j] != Atest1[ii*MSIZE4+jj]) bad = 1;
+	}
+      }
+    }
+    if (bad) printf ("\trow/col removal FAILED for row %d\n",r);
+
+    // zero out last row/column of Atest1
+    for (i=0; i<MSIZE; i++) {
+      Atest1[(MSIZE-1)*MSIZE4+i] = 0;
+      Atest1[i*MSIZE4+MSIZE-1] = 0;
+    }    
+
+    // get L2*D2*L2' = adjusted factorization to remove that row
+    memcpy (L2,L,MSIZE4*MSIZE*sizeof(dReal));
+    memcpy (d2,d,MSIZE*sizeof(dReal));
+    dLDLTRemove (/*A*/ Arows,p,L2,d2,MSIZE,MSIZE,r,MSIZE4);
+
+    // get Atest2 = L2*D2*L2'
+    dClearUpperTriangle (L2,MSIZE);
+    for (i=0; i<(MSIZE-1); i++) L2[i*MSIZE4+i] = 1.0;
+    for (i=0; i<MSIZE; i++) L2[(MSIZE-1)*MSIZE4+i] = 0;
+    d2[MSIZE-1] = 1;
+    dSetZero (DL2,MSIZE4*MSIZE);
+    for (i=0; i<(MSIZE-1); i++) {
+      for (j=0; j<MSIZE-1; j++) DL2[i*MSIZE4+j] = L2[i*MSIZE4+j] / d2[j];
+    }
+
+    dMultiply2 (Atest2,L2,DL2,MSIZE,MSIZE,MSIZE);
+
+    diff = dMaxDifference(Atest1,Atest2,MSIZE,MSIZE);
+    if (diff < maxdiff) maxdiff = diff;
+
+    /*
+    dPrintMatrix (Atest1,MSIZE,MSIZE);
+    printf ("\n");
+    dPrintMatrix (Atest2,MSIZE,MSIZE);
+    printf ("\n");
+    */
+  }
+  printf ("\tmaximum difference = %.6e - %s\n",maxdiff,
+	  maxdiff > tol ? "FAILED" : "passed");
+}
+
+//****************************************************************************
+// test mass stuff
+
+#define NUMP 10		// number of particles
+
+
+void printMassParams (dMass *m)
+{
+  printf ("mass = %.4f\n",m->mass);
+  printf ("com  = (%.4f,%.4f,%.4f)\n",m->c[0],m->c[1],m->c[2]);
+  printf ("I    = [ %10.4f %10.4f %10.4f ]\n"
+	  "       [ %10.4f %10.4f %10.4f ]\n"
+	  "       [ %10.4f %10.4f %10.4f ]\n",
+	  m->_I(0,0),m->_I(0,1),m->_I(0,2),
+	  m->_I(1,0),m->_I(1,1),m->_I(1,2),
+	  m->_I(2,0),m->_I(2,1),m->_I(2,2));
+}
+
+
+void compareMassParams (dMass *m1, dMass *m2, char *msg)
+{
+  int i,j,ok = 1;
+  if (!(cmp(m1->mass,m2->mass) && cmp(m1->c[0],m2->c[0]) &&
+	cmp(m1->c[1],m2->c[1]) && cmp(m1->c[2],m2->c[2])))
+    ok = 0;
+  for (i=0; i<3; i++) for (j=0; j<3; j++)
+    if (cmp (m1->_I(i,j),m2->_I(i,j))==0) ok = 0;
+  if (ok) printf ("\tpassed (%s)\n",msg); else printf ("\tFAILED (%s)\n",msg);
+}
+
+
+// compute the mass parameters of a particle set
+
+void computeMassParams (dMass *m, dReal q[NUMP][3], dReal pm[NUMP])
+{
+  int i,j;
+  dMassSetZero (m);
+  for (i=0; i<NUMP; i++) {
+    m->mass += pm[i];
+    for (j=0; j<3; j++) m->c[j] += pm[i]*q[i][j];
+    m->_I(0,0) += pm[i]*(q[i][1]*q[i][1] + q[i][2]*q[i][2]);
+    m->_I(1,1) += pm[i]*(q[i][0]*q[i][0] + q[i][2]*q[i][2]);
+    m->_I(2,2) += pm[i]*(q[i][0]*q[i][0] + q[i][1]*q[i][1]);
+    m->_I(0,1) -= pm[i]*(q[i][0]*q[i][1]);
+    m->_I(0,2) -= pm[i]*(q[i][0]*q[i][2]);
+    m->_I(1,2) -= pm[i]*(q[i][1]*q[i][2]);
+  }
+  for (j=0; j<3; j++) m->c[j] /= m->mass;
+  m->_I(1,0) = m->_I(0,1);
+  m->_I(2,0) = m->_I(0,2);
+  m->_I(2,1) = m->_I(1,2);
+}
+
+
+void testMassFunctions()
+{
+  dMass m;
+  int i,j;
+  dReal q[NUMP][3];		// particle positions
+  dReal pm[NUMP];		// particle masses
+  dMass m1,m2;
+  dMatrix3 R;
+
+  HEADER;
+
+  printf ("\t");
+  dMassSetZero (&m);
+  TRAP_MESSAGE (dMassSetParameters (&m,10, 0,0,0, 1,2,3, 4,5,6),
+		printf (" FAILED (1)\n"), printf (" passed (1)\n"));
+
+  printf ("\t");
+  dMassSetZero (&m);
+  TRAP_MESSAGE (dMassSetParameters (&m,10, 0.1,0.2,0.15, 3,5,14, 3.1,3.2,4),
+		printf (" passed (2)\n") , printf (" FAILED (2)\n"));
+  if (m.mass==10 && m.c[0]==REAL(0.1) && m.c[1]==REAL(0.2) &&
+      m.c[2]==REAL(0.15) && m._I(0,0)==3 && m._I(1,1)==5 && m._I(2,2)==14 &&
+      m._I(0,1)==REAL(3.1) && m._I(0,2)==REAL(3.2) && m._I(1,2)==4 &&
+      m._I(1,0)==REAL(3.1) && m._I(2,0)==REAL(3.2) && m._I(2,1)==4)
+    printf ("\tpassed (3)\n"); else printf ("\tFAILED (3)\n");
+
+  dMassSetZero (&m);
+  dMassSetSphere (&m,1.4, 0.86);
+  if (cmp(m.mass,3.73002719949386) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
+      cmp(m._I(0,0),1.10349124669826) &&
+      cmp(m._I(1,1),1.10349124669826) &&
+      cmp(m._I(2,2),1.10349124669826) &&
+      m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
+      m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
+    printf ("\tpassed (4)\n"); else printf ("\tFAILED (4)\n");
+
+  dMassSetZero (&m);
+  dMassSetCapsule (&m,1.3,1,0.76,1.53);
+  if (cmp(m.mass,5.99961928996029) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
+      cmp(m._I(0,0),1.59461986077384) &&
+      cmp(m._I(1,1),4.57537403079093) &&
+      cmp(m._I(2,2),4.57537403079093) &&
+      m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
+      m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
+    printf ("\tpassed (5)\n"); else printf ("\tFAILED (5)\n");
+
+  dMassSetZero (&m);
+  dMassSetBox (&m,0.27,3,4,5);
+  if (cmp(m.mass,16.2) && m.c[0]==0 && m.c[1]==0 && m.c[2]==0 &&
+      cmp(m._I(0,0),55.35) && cmp(m._I(1,1),45.9) && cmp(m._I(2,2),33.75) &&
+      m._I(0,1)==0 && m._I(0,2)==0 && m._I(1,2)==0 &&
+      m._I(1,0)==0 && m._I(2,0)==0 && m._I(2,1)==0)
+    printf ("\tpassed (6)\n"); else printf ("\tFAILED (6)\n");
+
+  // test dMassAdjust?
+
+  // make random particles and compute the mass, COM and inertia, then
+  // translate and repeat.
+  for (i=0; i<NUMP; i++) {
+    pm[i] = dRandReal()+0.5;
+    for (j=0; j<3; j++) {
+      q[i][j] = 2.0*(dRandReal()-0.5);
+    }
+  }
+  computeMassParams (&m1,q,pm);
+  memcpy (&m2,&m1,sizeof(dMass));
+  dMassTranslate (&m2,1,2,-3);
+  for (i=0; i<NUMP; i++) {
+    q[i][0] += 1;
+    q[i][1] += 2;
+    q[i][2] -= 3;
+  }
+  computeMassParams (&m1,q,pm);
+  compareMassParams (&m1,&m2,"7");
+
+  // rotate the masses
+  _R(0,0) = -0.87919618797635;
+  _R(0,1) = 0.15278881840384;
+  _R(0,2) = -0.45129772879842;
+  _R(1,0) = -0.47307856232664;
+  _R(1,1) = -0.39258064912909;
+  _R(1,2) = 0.78871864932708;
+  _R(2,0) = -0.05666336483842;
+  _R(2,1) = 0.90693771059546;
+  _R(2,2) = 0.41743652473765;
+  dMassRotate (&m2,R);
+  for (i=0; i<NUMP; i++) {
+    dReal a[3];
+    dMultiply0 (a,&_R(0,0),&q[i][0],3,3,1);
+    q[i][0] = a[0];
+    q[i][1] = a[1];
+    q[i][2] = a[2];
+  }
+  computeMassParams (&m1,q,pm);
+  compareMassParams (&m1,&m2,"8");
+}
+
+//****************************************************************************
+// test rotation stuff
+
+void makeRandomRotation (dMatrix3 R)
+{
+  dReal *u1 = R, *u2=R+4, *u3=R+8;
+  dMakeRandomVector (u1,3,1.0);
+  dNormalize3 (u1);
+  dMakeRandomVector (u2,3,1.0);
+  dReal d = dDOT(u1,u2);
+  u2[0] -= d*u1[0];
+  u2[1] -= d*u1[1];
+  u2[2] -= d*u1[2];
+  dNormalize3 (u2);
+  dCROSS (u3,=,u1,u2);
+}
+
+
+void testRtoQandQtoR()
+{
+  HEADER;
+  dMatrix3 R,I,R2;
+  dQuaternion q;
+  int i;
+
+  // test makeRandomRotation()
+  makeRandomRotation (R);
+  dMultiply2 (I,R,R,3,3,3);
+  printf ("\tmakeRandomRotation() - %s (1)\n",
+	  cmpIdentityMat3(I) ? "passed" : "FAILED");
+
+  // test QtoR() on random normalized quaternions
+  int ok = 1;
+  for (i=0; i<100; i++) {
+    dMakeRandomVector (q,4,1.0);
+    dNormalize4 (q);
+    dQtoR (q,R);
+    dMultiply2 (I,R,R,3,3,3);
+    if (cmpIdentityMat3(I)==0) ok = 0;
+  }
+  printf ("\tQtoR() orthonormality %s (2)\n", ok ? "passed" : "FAILED");
+
+  // test R -> Q -> R works
+  dReal maxdiff=0;
+  for (i=0; i<100; i++) {
+    makeRandomRotation (R);
+    dRtoQ (R,q);
+    dQtoR (q,R2);
+    dReal diff = dMaxDifference (R,R2,3,3);
+    if (diff > maxdiff) maxdiff = diff;
+  }
+  printf ("\tmaximum difference = %e - %s (3)\n",maxdiff,
+	  (maxdiff > tol) ? "FAILED" : "passed");
+}
+
+
+void testQuaternionMultiply()
+{
+  HEADER;
+  dMatrix3 RA,RB,RC,Rtest;
+  dQuaternion qa,qb,qc;
+  dReal diff,maxdiff=0;
+
+  for (int i=0; i<100; i++) {
+    makeRandomRotation (RB);
+    makeRandomRotation (RC);
+    dRtoQ (RB,qb);
+    dRtoQ (RC,qc);
+
+    dMultiply0 (RA,RB,RC,3,3,3);
+    dQMultiply0 (qa,qb,qc);
+    dQtoR (qa,Rtest);
+    diff = dMaxDifference (Rtest,RA,3,3);
+    if (diff > maxdiff) maxdiff = diff;
+
+    dMultiply1 (RA,RB,RC,3,3,3);
+    dQMultiply1 (qa,qb,qc);
+    dQtoR (qa,Rtest);
+    diff = dMaxDifference (Rtest,RA,3,3);
+    if (diff > maxdiff) maxdiff = diff;
+
+    dMultiply2 (RA,RB,RC,3,3,3);
+    dQMultiply2 (qa,qb,qc);
+    dQtoR (qa,Rtest);
+    diff = dMaxDifference (Rtest,RA,3,3);
+    if (diff > maxdiff) maxdiff = diff;
+
+    dMultiply0 (RA,RC,RB,3,3,3);
+    transpose3x3 (RA);
+    dQMultiply3 (qa,qb,qc);
+    dQtoR (qa,Rtest);
+    diff = dMaxDifference (Rtest,RA,3,3);
+    if (diff > maxdiff) maxdiff = diff;
+  }
+  printf ("\tmaximum difference = %e - %s\n",maxdiff,
+	  (maxdiff > tol) ? "FAILED" : "passed");
+}
+
+
+void testRotationFunctions()
+{
+  dMatrix3 R1;
+  HEADER;
+
+  printf ("\tdRSetIdentity - ");
+  dMakeRandomMatrix (R1,3,3,1.0);
+  dRSetIdentity (R1);
+  if (cmpIdentityMat3(R1)) printf ("passed\n"); else printf ("FAILED\n");
+
+  printf ("\tdRFromAxisAndAngle - ");
+
+  printf ("\n");
+  printf ("\tdRFromEulerAngles - ");
+
+  printf ("\n");
+  printf ("\tdRFrom2Axes - ");
+
+  printf ("\n");
+}
+
+//****************************************************************************
+
+#include "../src/array.h"
+#include "../src/array.cpp"
+
+// matrix header on the stack
+
+class dMatrixComparison {
+  struct dMatInfo;
+  dArray<dMatInfo*> mat;
+  int afterfirst,index;
+
+public:
+  dMatrixComparison();
+  ~dMatrixComparison();
+
+  dReal nextMatrix (dReal *A, int n, int m, int lower_tri, char *name, ...);
+  // add a new n*m matrix A to the sequence. the name of the matrix is given
+  // by the printf-style arguments (name,...). if this is the first sequence
+  // then this object will simply record the matrices and return 0.
+  // if this the second or subsequent sequence then this object will compare
+  // the matrices with the first sequence, and report any differences.
+  // the matrix error will be returned. if `lower_tri' is 1 then only the
+  // lower triangle of the matrix (including the diagonal) will be compared
+  // (the matrix must be square).
+
+  void end();
+  // end a sequence.
+
+  void reset();
+  // restarts the object, so the next sequence will be the first sequence.
+
+  void dump();
+  // print out info about all the matrices in the sequence
+};
+
+struct dMatrixComparison::dMatInfo {
+  int n,m;		// size of matrix
+  char name[128];	// name of the matrix
+  dReal *data;		// matrix data
+  int size;		// size of `data'
+};
+
+
+
+dMatrixComparison::dMatrixComparison()
+{
+  afterfirst = 0;
+  index = 0;
+}
+
+
+dMatrixComparison::~dMatrixComparison()
+{
+  reset();
+}
+
+
+dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri,
+				     char *name, ...)
+{
+  if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix");
+  int num = n*dPAD(m);
+
+  if (afterfirst==0) {
+    dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo));
+    mi->n = n;
+    mi->m = m;
+    mi->size = num * sizeof(dReal);
+    mi->data = (dReal*) dAlloc (mi->size);
+    memcpy (mi->data,A,mi->size);
+
+    va_list ap;
+    va_start (ap,name);
+    vsprintf (mi->name,name,ap);
+    if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long");
+
+    mat.push (mi);
+    return 0;
+  }
+  else {
+    if (lower_tri && n != m)
+      dDebug (0,"dMatrixComparison, lower triangular matrix must be square");
+    if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices");
+    dMatInfo *mp = mat[index];
+    index++;
+
+    dMatInfo mi;
+    va_list ap;
+    va_start (ap,name);
+    vsprintf (mi.name,name,ap);
+    if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long");
+
+    if (strcmp(mp->name,mi.name) != 0)
+      dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")",
+	      mp->name,mi.name);
+    if (mp->n != n || mp->m != m)
+      dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)",
+	      mp->n,mp->m,n,m);
+
+    dReal maxdiff;
+    if (lower_tri) {
+      maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n);
+    }
+    else {
+      maxdiff = dMaxDifference (A,mp->data,n,m);
+    }
+    if (maxdiff > tol)
+      dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", "
+	      "error=%.4e)",n,m,mi.name,maxdiff);
+    return maxdiff;
+  }
+}
+
+
+void dMatrixComparison::end()
+{
+  if (mat.size() <= 0) dDebug (0,"no matrices in sequence");
+  afterfirst = 1;
+  index = 0;
+}
+
+
+void dMatrixComparison::reset()
+{
+  for (int i=0; i<mat.size(); i++) {
+    dFree (mat[i]->data,mat[i]->size);
+    dFree (mat[i],sizeof(dMatInfo));
+  }
+  mat.setSize (0);
+  afterfirst = 0;
+  index = 0;
+}
+
+
+void dMatrixComparison::dump()
+{
+  for (int i=0; i<mat.size(); i++)
+    printf ("%d: %s (%dx%d)\n",i,mat[i]->name,mat[i]->n,mat[i]->m);
+}
+
+//****************************************************************************
+// unit test
+
+#include <setjmp.h>
+
+// static jmp_buf jump_buffer;
+
+static void myDebug (int num, const char *msg, va_list ap)
+{
+  // printf ("(Error %d: ",num);
+  // vprintf (msg,ap);
+  // printf (")\n");
+  longjmp (jump_buffer,1);
+}
+
+
+extern "C" void dTestMatrixComparison()
+{
+  volatile int i;
+  printf ("dTestMatrixComparison()\n");
+  dMessageFunction *orig_debug = dGetDebugHandler();
+
+  dMatrixComparison mc;
+  dReal A[50*50];
+
+  // make first sequence
+  unsigned long seed = dRandGetSeed();
+  for (i=1; i<49; i++) {
+    dMakeRandomMatrix (A,i,i+1,1.0);
+    mc.nextMatrix (A,i,i+1,0,"A%d",i);
+  }
+  mc.end();
+
+  //mc.dump();
+
+  // test identical sequence
+  dSetDebugHandler (&myDebug);
+  dRandSetSeed (seed);
+  if (setjmp (jump_buffer)) {
+    printf ("\tFAILED (1)\n");
+  }
+  else {
+    for (i=1; i<49; i++) {
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      mc.nextMatrix (A,i,i+1,0,"A%d",i);
+    }
+    mc.end();
+    printf ("\tpassed (1)\n");
+  }
+  dSetDebugHandler (orig_debug);
+
+  // test broken sequences (with matrix error)
+  dRandSetSeed (seed);
+  volatile int passcount = 0;
+  for (i=1; i<49; i++) {
+    if (setjmp (jump_buffer)) {
+      passcount++;
+    }
+    else {
+      dSetDebugHandler (&myDebug);
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      A[(i-1)*dPAD(i+1)+i] += REAL(0.01);
+      mc.nextMatrix (A,i,i+1,0,"A%d",i);
+      dSetDebugHandler (orig_debug);
+    }
+  }
+  mc.end();
+  printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED");
+
+  // test broken sequences (with name error)
+  dRandSetSeed (seed);
+  passcount = 0;
+  for (i=1; i<49; i++) {
+    if (setjmp (jump_buffer)) {
+      passcount++;
+    }
+    else {
+      dSetDebugHandler (&myDebug);
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      mc.nextMatrix (A,i,i+1,0,"B%d",i);
+      dSetDebugHandler (orig_debug);
+    }
+  }
+  mc.end();
+  printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED");
+
+  // test identical sequence again
+  dSetDebugHandler (&myDebug);
+  dRandSetSeed (seed);
+  if (setjmp (jump_buffer)) {
+    printf ("\tFAILED (4)\n");
+  }
+  else {
+    for (i=1; i<49; i++) {
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      mc.nextMatrix (A,i,i+1,0,"A%d",i);
+    }
+    mc.end();
+    printf ("\tpassed (4)\n");
+  }
+  dSetDebugHandler (orig_debug);
+}
+
+//****************************************************************************
+
+// internal unit tests
+extern "C" void dTestDataStructures();
+extern "C" void dTestMatrixComparison();
+extern "C" void dTestSolveLCP();
+
+
+int main()
+{
+  dInitODE();
+  testRandomNumberGenerator();
+  testInfinity();
+  testPad();
+  testCrossProduct();
+  testSetZero();
+  testNormalize3();
+  //testReorthonormalize();     ... not any more
+  testPlaneSpace();
+  testMatrixMultiply();
+  testSmallMatrixMultiply();
+  testCholeskyFactorization();
+  testCholeskySolve();
+  testInvertPDMatrix();
+  testIsPositiveDefinite();
+  testFastLDLTFactorization();
+  testSolveLDLT();
+  testLDLTAddTL();
+  testLDLTRemove();
+  testMassFunctions();
+  testRtoQandQtoR();
+  testQuaternionMultiply();
+  testRotationFunctions();
+  dTestMatrixComparison();
+  dTestSolveLCP();
+  // dTestDataStructures();
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_plane2d.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_plane2d.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_plane2d.cpp	(revision 216)
@@ -0,0 +1,268 @@
+// Test my Plane2D constraint.
+// Uses ode-0.35 collision API.
+
+# include       <stdio.h>
+# include       <stdlib.h>
+# include       <math.h>
+# include       <ode/ode.h>
+# include       <drawstuff/drawstuff.h>
+
+#   define drand48()  ((double) (((double) rand()) / ((double) RAND_MAX)))
+
+# define        N_BODIES        40
+# define        STAGE_SIZE      8.0  // in m
+
+# define        TIME_STEP       0.01
+# define        K_SPRING        10.0
+# define        K_DAMP          10.0
+
+
+static dWorld   dyn_world;
+static dBody    dyn_bodies[N_BODIES];
+static dReal    bodies_sides[N_BODIES][3];
+
+static dSpaceID coll_space_id;
+static dJointID plane2d_joint_ids[N_BODIES];
+static dJointGroup
+                coll_contacts;
+
+
+
+static void     cb_start ()
+/*************************/
+{
+    static float    xyz[3] = { 0.5f*STAGE_SIZE, 0.5f*STAGE_SIZE, 0.65f*STAGE_SIZE};
+    static float    hpr[3] = { 90.0f, -90.0f, 0 };
+
+    dsSetViewpoint (xyz, hpr);
+}
+
+
+
+static void     cb_near_collision (void *data, dGeomID o1, dGeomID o2)
+/********************************************************************/
+{
+    dBodyID     b1 = dGeomGetBody (o1);
+    dBodyID     b2 = dGeomGetBody (o2);
+    dContact    contact;
+
+
+    // exit without doing anything if the two bodies are static
+    if (b1 == 0 && b2 == 0)
+        return;
+
+    // exit without doing anything if the two bodies are connected by a joint
+    if (b1 && b2 && dAreConnected (b1, b2))
+    {
+        /* MTRAP; */
+        return;
+    }
+
+    contact.surface.mode = 0;
+    contact.surface.mu = 0; // frictionless
+
+    if (dCollide (o1, o2, 1, &contact.geom, sizeof (dContactGeom)))
+    {
+        dJointID c = dJointCreateContact (dyn_world.id(),
+                        coll_contacts.id (), &contact);
+        dJointAttach (c, b1, b2);
+    }
+}
+
+
+static void     track_to_pos (dBody &body, dJointID joint_id,
+                              dReal target_x, dReal target_y)
+/************************************************************************/
+{
+    dReal  curr_x = body.getPosition()[0];
+    dReal  curr_y = body.getPosition()[1];
+
+    dJointSetPlane2DXParam (joint_id, dParamVel, 1 * (target_x - curr_x));
+    dJointSetPlane2DYParam (joint_id, dParamVel, 1 * (target_y - curr_y));
+}
+
+
+
+static void     cb_sim_step (int pause)
+/*************************************/
+{
+    if (! pause)
+    {
+        static dReal angle = 0;
+
+        angle += REAL( 0.01 );
+
+        track_to_pos (dyn_bodies[0], plane2d_joint_ids[0],
+            dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * cos (angle) ),
+            dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * sin (angle) ));
+
+        /* double   f0 = 0.001; */
+        /* for (int b = 0; b < N_BODIES; b ++) */
+        /* { */
+            /* double   p = 1 + b / (double) N_BODIES; */
+            /* double   q = 2 - b / (double) N_BODIES; */
+            /* dyn_bodies[b].addForce (f0 * cos (p*angle), f0 * sin (q*angle), 0); */
+        /* } */
+        /* dyn_bodies[0].addTorque (0, 0, 0.1); */
+
+        const int n = 10;
+        for (int i = 0; i < n; i ++)
+        {
+            dSpaceCollide (coll_space_id, 0, &cb_near_collision);
+            dyn_world.step (dReal(TIME_STEP/n));
+            coll_contacts.empty ();
+        }
+    }
+
+# if 1  /* [ */
+    {
+        // @@@ hack Plane2D constraint error reduction here:
+        for (int b = 0; b < N_BODIES; b ++)
+        {
+            const dReal     *rot = dBodyGetAngularVel (dyn_bodies[b].id());
+            const dReal     *quat_ptr;
+            dReal           quat[4],
+                            quat_len;
+
+
+            quat_ptr = dBodyGetQuaternion (dyn_bodies[b].id());
+            quat[0] = quat_ptr[0];
+            quat[1] = 0;
+            quat[2] = 0;
+            quat[3] = quat_ptr[3];
+            quat_len = sqrt (quat[0] * quat[0] + quat[3] * quat[3]);
+            quat[0] /= quat_len;
+            quat[3] /= quat_len;
+            dBodySetQuaternion (dyn_bodies[b].id(), quat);
+            dBodySetAngularVel (dyn_bodies[b].id(), 0, 0, rot[2]);
+        }
+    }
+# endif  /* ] */
+
+
+# if 0  /* [ */
+    {
+        // @@@ friction
+        for (int b = 0; b < N_BODIES; b ++)
+        {
+            const dReal *vel = dBodyGetLinearVel (dyn_bodies[b].id()),
+                        *rot = dBodyGetAngularVel (dyn_bodies[b].id());
+            dReal       s = 1.00;
+            dReal       t = 0.99;
+
+            dBodySetLinearVel (dyn_bodies[b].id(), s*vel[0],s*vel[1],s*vel[2]);
+            dBodySetAngularVel (dyn_bodies[b].id(),t*rot[0],t*rot[1],t*rot[2]);
+        }
+    }
+# endif  /* ] */
+
+
+    {
+        // ode  drawstuff
+
+        dsSetTexture (DS_WOOD);
+        for (int b = 0; b < N_BODIES; b ++)
+        {
+            if (b == 0)
+            dsSetColor (1.0, 0.5, 1.0);
+            else
+            dsSetColor (0, 0.5, 1.0);
+#ifdef dDOUBLE
+            dsDrawBoxD (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
+#else
+            dsDrawBox (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
+#endif
+        }
+    }
+}
+
+
+
+extern int      main
+/******************/
+(
+    int         argc,
+    char        **argv
+)
+{
+    int         b;
+    dsFunctions drawstuff_functions;
+
+
+	 dInitODE();
+
+    // dynamic world
+
+    dReal  cf_mixing;// = 1 / TIME_STEP * K_SPRING + K_DAMP;
+    dReal  err_reduct;// = TIME_STEP * K_SPRING * cf_mixing;
+    err_reduct = REAL( 0.5 );
+    cf_mixing = REAL( 0.001 );
+    dWorldSetERP (dyn_world.id (), err_reduct);
+    dWorldSetCFM (dyn_world.id (), cf_mixing);
+    dyn_world.setGravity (0, 0.0, -1.0);
+
+    coll_space_id = dSimpleSpaceCreate (0);
+
+    // dynamic bodies
+    for (b = 0; b < N_BODIES; b ++)
+    {
+        int     l = (int) (1 + sqrt ((double) N_BODIES));
+        dReal  x = dReal( (0.5 + (b / l)) / l * STAGE_SIZE );
+        dReal  y = dReal( (0.5 + (b % l)) / l * STAGE_SIZE );
+        dReal  z = REAL( 1.0 ) + REAL( 0.1 ) * (dReal)drand48();
+
+        bodies_sides[b][0] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) );
+        bodies_sides[b][1] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) );
+        bodies_sides[b][2] = z;
+
+        dyn_bodies[b].create (dyn_world);
+        dyn_bodies[b].setPosition (x, y, z/2);
+        dyn_bodies[b].setData ((void*) (size_t)b);
+        dBodySetLinearVel (dyn_bodies[b].id (),
+            dReal( 3 * (drand48 () - 0.5) ), 
+			dReal( 3 * (drand48 () - 0.5) ), 0);
+
+        dMass m;
+        m.setBox (1, bodies_sides[b][0],bodies_sides[b][1],bodies_sides[b][2]);
+        m.adjust (REAL(0.1) * bodies_sides[b][0] * bodies_sides[b][1]);
+        dyn_bodies[b].setMass (&m);
+
+        plane2d_joint_ids[b] = dJointCreatePlane2D (dyn_world.id (), 0);
+        dJointAttach (plane2d_joint_ids[b], dyn_bodies[b].id (), 0);
+    }
+
+    dJointSetPlane2DXParam (plane2d_joint_ids[0], dParamFMax, 10);
+    dJointSetPlane2DYParam (plane2d_joint_ids[0], dParamFMax, 10);
+
+
+    // collision geoms and joints
+    dCreatePlane (coll_space_id,  1, 0, 0, 0);
+    dCreatePlane (coll_space_id, -1, 0, 0, -STAGE_SIZE);
+    dCreatePlane (coll_space_id,  0,  1, 0, 0);
+    dCreatePlane (coll_space_id,  0, -1, 0, -STAGE_SIZE);
+
+    for (b = 0; b < N_BODIES; b ++)
+    {
+        dGeomID coll_box_id;
+        coll_box_id = dCreateBox (coll_space_id,
+            bodies_sides[b][0], bodies_sides[b][1], bodies_sides[b][2]);
+        dGeomSetBody (coll_box_id, dyn_bodies[b].id ());
+    }
+
+    coll_contacts.create (0);
+
+    {
+        // simulation loop (by drawstuff lib)
+        drawstuff_functions.version = DS_VERSION;
+        drawstuff_functions.start = &cb_start;
+        drawstuff_functions.step = &cb_sim_step;
+        drawstuff_functions.command = 0;
+        drawstuff_functions.stop = 0;
+        drawstuff_functions.path_to_textures = "../../drawstuff/textures";
+
+        dsSimulationLoop (argc, argv, 352,288,&drawstuff_functions);
+    }
+
+	 dCloseODE();
+    return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_slider.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_slider.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_slider.cpp	(revision 216)
@@ -0,0 +1,172 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#endif
+
+
+// some constants
+#define SIDE (0.5f)	// side length of a box
+#define MASS (1.0)	// mass of a box
+
+
+// dynamics and collision objects
+static dWorldID world;
+static dBodyID body[2];
+static dJointID slider;
+
+
+// state set by keyboard commands
+static int occasional_error = 0;
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {1.0382f,-1.0811f,1.4700f};
+  static float hpr[3] = {135.0000f,-19.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("Press 'e' to start/stop occasional error.\n");
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  if (cmd == 'e' || cmd == 'E') {
+    occasional_error ^= 1;
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  const dReal kd = -0.3;	// angular damping constant
+  const dReal ks = 0.5;	// spring constant
+  if (!pause) {
+    // add an oscillating torque to body 0, and also damp its rotational motion
+    static dReal a=0;
+    const dReal *w = dBodyGetAngularVel (body[0]);
+    dBodyAddTorque (body[0],kd*w[0],kd*w[1]+0.1*cos(a),kd*w[2]+0.1*sin(a));
+    a += 0.01;
+
+    // add a spring force to keep the bodies together, otherwise they will
+    // fly apart along the slider axis.
+    const dReal *p1 = dBodyGetPosition (body[0]);
+    const dReal *p2 = dBodyGetPosition (body[1]);
+    dBodyAddForce (body[0],ks*(p2[0]-p1[0]),ks*(p2[1]-p1[1]),
+		   ks*(p2[2]-p1[2]));
+    dBodyAddForce (body[1],ks*(p1[0]-p2[0]),ks*(p1[1]-p2[1]),
+		   ks*(p1[2]-p2[2]));
+
+    // occasionally re-orient one of the bodies to create a deliberate error.
+    if (occasional_error) {
+      static int count = 0;
+      if ((count % 20)==0) {
+	// randomly adjust orientation of body[0]
+	const dReal *R1;
+	dMatrix3 R2,R3;
+	R1 = dBodyGetRotation (body[0]);
+	dRFromAxisAndAngle (R2,dRandReal()-0.5,dRandReal()-0.5,
+			    dRandReal()-0.5,dRandReal()-0.5);
+	dMultiply0 (R3,R1,R2,3,3,3);
+	dBodySetRotation (body[0],R3);
+
+	// randomly adjust position of body[0]
+	const dReal *pos = dBodyGetPosition (body[0]);
+	dBodySetPosition (body[0],
+			  pos[0]+0.2*(dRandReal()-0.5),
+			  pos[1]+0.2*(dRandReal()-0.5),
+			  pos[2]+0.2*(dRandReal()-0.5));
+      }
+      count++;
+    }
+
+    dWorldStep (world,0.05);
+  }
+
+  dReal sides1[3] = {SIDE,SIDE,SIDE};
+  dReal sides2[3] = {SIDE*0.8f,SIDE*0.8f,SIDE*2.0f};
+  dsSetTexture (DS_WOOD);
+  dsSetColor (1,1,0);
+  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides1);
+  dsSetColor (0,1,1);
+  dsDrawBox (dBodyGetPosition(body[1]),dBodyGetRotation(body[1]),sides2);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+  dMass m;
+  dMassSetBox (&m,1,SIDE,SIDE,SIDE);
+  dMassAdjust (&m,MASS);
+
+  body[0] = dBodyCreate (world);
+  dBodySetMass (body[0],&m);
+  dBodySetPosition (body[0],0,0,1);
+  body[1] = dBodyCreate (world);
+  dBodySetMass (body[1],&m);
+  dQuaternion q;
+  dQFromAxisAndAngle (q,-1,1,0,0.25*M_PI);
+  dBodySetPosition (body[1],0.2,0.2,1.2);
+  dBodySetQuaternion (body[1],q);
+
+  slider = dJointCreateSlider (world,0);
+  dJointAttach (slider,body[0],body[1]);
+  dJointSetSliderAxis (slider,1,1,1);
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_space.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_space.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_space.cpp	(revision 216)
@@ -0,0 +1,233 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+testing procedure:
+  * create a bunch of random boxes
+  * test for intersections directly, put results in n^2 array
+  * get space to report collisions:
+    - all correct collisions reported
+    - no pair reported more than once
+    - no incorrect collisions reported
+
+*/
+
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define NUM 20			// number of boxes to test
+
+
+// collision objects and globals
+
+static dSpaceID space;
+static dGeomID geom[NUM];
+static dReal bounds[NUM][6];
+static size_t good_matrix[NUM][NUM];	// correct collision matrix
+static size_t test_matrix[NUM][NUM];	// testing collision matrix
+static size_t hits[NUM];		// number of collisions a box has
+static unsigned long seed=37;
+
+
+static void init_test()
+{
+  int i,j;
+  const dReal scale = 0.5;
+
+  // set random boxes
+  dRandSetSeed (seed);
+  for (i=0; i < NUM; i++) {
+    bounds[i][0] = dRandReal()*2-1;
+    bounds[i][1] = bounds[i][0] + dRandReal()*scale;
+    bounds[i][2] = dRandReal()*2-1;
+    bounds[i][3] = bounds[i][2] + dRandReal()*scale;
+    bounds[i][4] = dRandReal()*2;
+    bounds[i][5] = bounds[i][4] + dRandReal()*scale;
+
+    if (geom[i]) dGeomDestroy (geom[i]);
+    geom[i] = dCreateBox (space,
+			  bounds[i][1] - bounds[i][0],
+			  bounds[i][3] - bounds[i][2],
+			  bounds[i][5] - bounds[i][4]);
+    dGeomSetPosition (geom[i],
+		      (bounds[i][0] + bounds[i][1])*0.5,
+		      (bounds[i][2] + bounds[i][3])*0.5,
+		      (bounds[i][4] + bounds[i][5])*0.5);
+    dGeomSetData (geom[i],(void*)(size_t)(i));
+  }
+
+  // compute all intersections and put the results in "good_matrix"
+  for (i=0; i < NUM; i++) {
+    for (j=0; j < NUM; j++) good_matrix[i][j] = 0;
+  }
+  for (i=0; i < NUM; i++) hits[i] = 0;
+
+  for (i=0; i < NUM; i++) {
+    for (j=i+1; j < NUM; j++) {
+      dReal *bounds1 = &bounds[i][0];
+      dReal *bounds2 = &bounds[j][0];
+      if (bounds1[0] > bounds2[1] ||
+	  bounds1[1] < bounds2[0] ||
+	  bounds1[2] > bounds2[3] ||
+	  bounds1[3] < bounds2[2] ||
+	  bounds1[4] > bounds2[5] ||
+	  bounds1[5] < bounds2[4]) continue;
+      good_matrix[i][j] = 1;
+      good_matrix[j][i] = 1;
+      hits[i]++;
+      hits[j]++;
+    }
+  }
+}
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  size_t i,j;
+  i = (size_t) dGeomGetData (o1);
+  j = (size_t) dGeomGetData (o2);
+  if (i==j)
+    printf ("collision (%d,%d) is between the same object\n",i,j);
+  if (!good_matrix[i][j] || !good_matrix[j][i])
+    printf ("collision (%d,%d) is incorrect\n",i,j);
+  if (test_matrix[i][j] || test_matrix[j][i])
+    printf ("collision (%d,%d) reported more than once\n",i,j);
+  test_matrix[i][j] = 1;
+  test_matrix[j][i] = 1;
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+static void command (int cmd)
+{
+  if (cmd == ' ') {
+    seed++;
+    init_test();
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  int i,j;
+
+  for (i=0; i < NUM; i++) {
+    for (j=0; j < NUM; j++) test_matrix[i][j] = 0;
+  }
+  dSpaceCollide (space,0,&nearCallback);
+  for (i=0; i < NUM; i++) {
+    for (j=i+1; j < NUM; j++) {
+      if (good_matrix[i][j] && !test_matrix[i][j]) {
+	printf ("failed to report collision (%d,%d) (seed=%ld)\n",i,j,seed);
+      }
+    }
+  }
+
+  seed++;
+  init_test();
+
+  for (i=0; i<NUM; i++) {
+    dVector3 pos,side;
+    dMatrix3 R;
+    dRSetIdentity (R);
+    for (j=0; j<3; j++) pos[j] = (bounds[i][j*2+1] + bounds[i][j*2]) * 0.5;
+    for (j=0; j<3; j++) side[j] = bounds[i][j*2+1] - bounds[i][j*2];
+    if (hits[i] > 0) dsSetColor (1,0,0);
+    else dsSetColor (1,1,0);
+    dsDrawBox (pos,R,side);
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  int i;
+
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  dInitODE();
+
+  // test the simple space:
+  // space = dSimpleSpaceCreate();
+
+  // test the hash space:
+  // space = dHashSpaceCreate (0);
+  // dHashSpaceSetLevels (space,-10,10);
+
+  // test the quadtree space
+  dVector3 Center = {0, 0, 0, 0};
+  dVector3 Extents = {10, 0, 10, 0};
+  space = dQuadTreeSpaceCreate(0, Center, Extents, 7);
+
+  for (i=0; i < NUM; i++) geom[i] = 0;
+  init_test();
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dSpaceDestroy (space);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_space_stress.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_space_stress.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_space_stress.cpp	(revision 216)
@@ -0,0 +1,435 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define NUM 10000			// max number of objects
+#define DENSITY (5.0)		// density of all objects
+#define GPB 3			// maximum number of geometries per body
+#define MAX_CONTACTS 4		// maximum number of contact points per body
+#define WORLD_SIZE 100
+
+
+// dynamics and collision objects
+
+struct MyObject {
+  dBodyID body;			// the body
+  dGeomID geom[GPB];		// geometries representing this body
+};
+
+static int num=0;		// number of objects in simulation
+static int nextobj=0;		// next object to recycle if num==NUM
+static dWorldID world;
+static dSpaceID space;
+static MyObject obj[NUM];
+static dJointGroupID contactgroup;
+static int selected = -1;	// selected object
+static int show_aabb = 0;	// show geom AABBs?
+static int show_contacts = 0;	// show contact points?
+static int random_pos = 1;	// drop objects from random position?
+static int draw_geom = 1;
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+  // if (o1->body && o2->body) return;
+
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+
+  dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
+  for (i=0; i<MAX_CONTACTS; i++) {
+    contact[i].surface.mode = dContactBounce | dContactSoftCFM;
+    contact[i].surface.mu = dInfinity;
+    contact[i].surface.mu2 = 0;
+    contact[i].surface.bounce = 0.1;
+    contact[i].surface.bounce_vel = 0.1;
+    contact[i].surface.soft_cfm = 0.01;
+  }
+  if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
+			   sizeof(dContact))) {
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    const dReal ss[3] = {0.02,0.02,0.02};
+    for (i=0; i<numc; i++) {
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+      if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("To drop another object, press:\n");
+  printf ("   o to disable rendering.\n");
+  printf ("   b for box.\n");
+  printf ("   s for sphere.\n");
+  printf ("   c for cylinder.\n");
+  printf ("   x for a composite object.\n");
+  printf ("To select an object, press space.\n");
+  printf ("To disable the selected object, press d.\n");
+  printf ("To enable the selected object, press e.\n");
+  printf ("To toggle showing the geom AABBs, press a.\n");
+  printf ("To toggle showing the contact points, press t.\n");
+  printf ("To toggle dropping from random position/orientation, press r.\n");
+}
+
+
+char locase (char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+  else return c;
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  int i,j,k;
+  dReal sides[3];
+  dMass m;
+
+  cmd = locase (cmd);
+  if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x'
+      /* || cmd == 'l' */) {
+    if (num < NUM) {
+      i = num;
+      num++;
+    }
+    else {
+      i = nextobj;
+      nextobj++;
+      if (nextobj >= num) nextobj = 0;
+
+      // destroy the body and geoms for slot i
+      dBodyDestroy (obj[i].body);
+      for (k=0; k < GPB; k++) {
+	if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+      }
+      memset (&obj[i],0,sizeof(obj[i]));
+    }
+
+    obj[i].body = dBodyCreate (world);
+    for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+    dMatrix3 R;
+    if (random_pos) {
+      dBodySetPosition (obj[i].body,
+			dRandReal()*WORLD_SIZE-(WORLD_SIZE/2),dRandReal()*WORLD_SIZE-(WORLD_SIZE/2),dRandReal()+1);
+      dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			  dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+    }
+    else {
+      dReal maxheight = 0;
+      for (k=0; k<num; k++) {
+	const dReal *pos = dBodyGetPosition (obj[k].body);
+	if (pos[2] > maxheight) maxheight = pos[2];
+      }
+      dBodySetPosition (obj[i].body, 0,0,maxheight+1);
+      dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
+    }
+    dBodySetRotation (obj[i].body,R);
+    dBodySetData (obj[i].body,(void*)(size_t)i);
+
+    if (cmd == 'b') {
+      dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+      obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+    }
+    else if (cmd == 'c') {
+      sides[0] *= 0.5;
+      dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
+    }
+/*
+    // cylinder option not yet implemented
+    else if (cmd == 'l') {
+      sides[1] *= 0.5;
+      dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
+    }
+*/
+    else if (cmd == 's') {
+      sides[0] *= 0.5;
+      dMassSetSphere (&m,DENSITY,sides[0]);
+      obj[i].geom[0] = dCreateSphere (space,sides[0]);
+    }
+    else if (cmd == 'x') {
+      dGeomID g2[GPB];		// encapsulated geometries
+      dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+      // start accumulating masses for the encapsulated geometries
+      dMass m2;
+      dMassSetZero (&m);
+
+      // set random delta positions
+      for (j=0; j<GPB; j++) {
+	for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+      }
+
+      for (k=0; k<GPB; k++) {
+	obj[i].geom[k] = dCreateGeomTransform (space);
+	dGeomTransformSetCleanup (obj[i].geom[k],1);
+	if (k==0) {
+	  dReal radius = dRandReal()*0.25+0.05;
+	  g2[k] = dCreateSphere (0,radius);
+	  dMassSetSphere (&m2,DENSITY,radius);
+	}
+	else if (k==1) {
+	  g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+	  dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+	}
+	else {
+	  dReal radius = dRandReal()*0.1+0.05;
+	  dReal length = dRandReal()*1.0+0.1;
+	  g2[k] = dCreateCapsule (0,radius,length);
+	  dMassSetCapsule (&m2,DENSITY,3,radius,length);
+	}
+	dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+	// set the transformation (adjust the mass too)
+	dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMatrix3 Rtx;
+	dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+	dGeomSetRotation (g2[k],Rtx);
+	dMassRotate (&m2,Rtx);
+
+	// add to the total mass
+	dMassAdd (&m,&m2);
+      }
+
+      // move all encapsulated objects so that the center of mass is (0,0,0)
+      for (k=0; k<2; k++) {
+	dGeomSetPosition (g2[k],
+			  dpos[k][0]-m.c[0],
+			  dpos[k][1]-m.c[1],
+			  dpos[k][2]-m.c[2]);
+      }
+      dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+    }
+
+    for (k=0; k < GPB; k++) {
+      if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+    }
+
+    dBodySetMass (obj[i].body,&m);
+  }
+
+  if (cmd == ' ') {
+    selected++;
+    if (selected >= num) selected = 0;
+    if (selected < 0) selected = 0;
+  }
+  else if (cmd == 'd' && selected >= 0 && selected < num) {
+    dBodyDisable (obj[selected].body);
+  }
+  else if (cmd == 'e' && selected >= 0 && selected < num) {
+    dBodyEnable (obj[selected].body);
+  }
+  else if (cmd == 'a') {
+    show_aabb ^= 1;
+  }
+  else if (cmd == 't') {
+    show_contacts ^= 1;
+  }
+  else if (cmd == 'r') {
+    random_pos ^= 1;
+  }
+  else if (cmd == 'o') {
+    draw_geom ^= 1;
+  }
+}
+
+
+// draw a geom
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
+{
+	if (!draw_geom){
+		return;
+	}
+
+  if (!g) return;
+  if (!pos) pos = dGeomGetPosition (g);
+  if (!R) R = dGeomGetRotation (g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass) {
+    dVector3 sides;
+    dGeomBoxGetLengths (g,sides);
+    dsDrawBox (pos,R,sides);
+  }
+  else if (type == dSphereClass) {
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+  }
+  else if (type == dCapsuleClass) {
+    dReal radius,length;
+    dGeomCapsuleGetParams (g,&radius,&length);
+    dsDrawCapsule (pos,R,length,radius);
+  }
+/*
+  // cylinder option not yet implemented
+  else if (type == dCylinderClass) {
+    dReal radius,length;
+    dGeomCylinderGetParams (g,&radius,&length);
+    dsDrawCylinder (pos,R,length,radius);
+  }
+*/
+  else if (type == dGeomTransformClass) {
+    dGeomID g2 = dGeomTransformGetGeom (g);
+    const dReal *pos2 = dGeomGetPosition (g2);
+    const dReal *R2 = dGeomGetRotation (g2);
+    dVector3 actual_pos;
+    dMatrix3 actual_R;
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+    actual_pos[0] += pos[0];
+    actual_pos[1] += pos[1];
+    actual_pos[2] += pos[2];
+    dMULTIPLY0_333 (actual_R,R,R2);
+    drawGeom (g2,actual_pos,actual_R,0);
+  }
+
+  if (show_aabb) {
+    // draw the bounding box for this geom
+    dReal aabb[6];
+    dGeomGetAABB (g,aabb);
+    dVector3 bbpos;
+    for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+    dVector3 bbsides;
+    for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    dsSetColorAlpha (1,0,0,0.5);
+    dsDrawBox (bbpos,RI,bbsides);
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  dsSetColor (0,0,2);
+  dSpaceCollide (space,0,&nearCallback);
+  //if (!pause) dWorldStep (world,0.05);
+  //if (!pause) dWorldStepFast (world,0.05, 1);
+
+  // remove all contact joints
+  dJointGroupEmpty (contactgroup);
+
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+  for (int i=0; i<num; i++) {
+    for (int j=0; j < GPB; j++) {
+      if (i==selected) {
+	dsSetColor (0,0.7,1);
+      }
+      else if (! dBodyIsEnabled (obj[i].body)) {
+	dsSetColor (1,0,0);
+      }
+      else {
+	dsSetColor (1,1,0);
+      }
+      drawGeom (obj[i].geom[j],0,0,show_aabb);
+    }
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+
+
+  dVector3 Center = {0, 0, 0, 0};
+  dVector3 Extents = {WORLD_SIZE * 0.55, WORLD_SIZE * 0.55, WORLD_SIZE * 0.55, 0};
+
+  //space = dSimpleSpaceCreate(0);
+  //space = dHashSpaceCreate (0);
+  space = dQuadTreeSpaceCreate (0, Center, Extents, 6);
+  
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  dWorldSetCFM (world,1e-5);
+  dCreatePlane (space,0,0,1,0);
+  memset (obj,0,sizeof(obj));
+
+  for (int i = 0; i < NUM; i++){
+	command('s');
+  }
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_step.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_step.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_step.cpp	(revision 216)
@@ -0,0 +1,193 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// test the step function by comparing the output of the fast and the slow
+// version, for various systems. currently you have to define COMPARE_METHODS
+// in step.cpp for this to work properly.
+//
+// @@@ report MAX error
+
+#include <time.h>
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#endif
+
+
+// some constants
+
+#define NUM 10			// number of bodies
+#define NUMJ 9			// number of joints
+#define SIDE (0.2)		// side length of a box
+#define MASS (1.0)		// mass of a box
+#define RADIUS (0.1732f)	// sphere radius
+
+
+
+// dynamics and collision objects
+
+static dWorldID world=0;
+static dBodyID body[NUM];
+static dJointID joint[NUMJ];
+
+
+// create the test system
+
+void createTest()
+{
+  int i,j;
+  if (world) dWorldDestroy (world);
+
+  world = dWorldCreate();
+
+  // create random bodies
+  for (i=0; i<NUM; i++) {
+    // create bodies at random position and orientation
+    body[i] = dBodyCreate (world);
+    dBodySetPosition (body[i],dRandReal()*2-1,dRandReal()*2-1,
+		      dRandReal()*2+RADIUS);
+    dReal q[4];
+    for (j=0; j<4; j++) q[j] = dRandReal()*2-1;
+    dBodySetQuaternion (body[i],q);
+
+    // set random velocity
+    dBodySetLinearVel (body[i], dRandReal()*2-1,dRandReal()*2-1,
+		       dRandReal()*2-1);
+    dBodySetAngularVel (body[i], dRandReal()*2-1,dRandReal()*2-1,
+			dRandReal()*2-1);
+
+    // set random mass (random diagonal mass rotated by a random amount)
+    dMass m;
+    dMatrix3 R;
+    dMassSetBox (&m,1,dRandReal()+0.1,dRandReal()+0.1,dRandReal()+0.1);
+    dMassAdjust (&m,dRandReal()+1);
+    for (j=0; j<4; j++) q[j] = dRandReal()*2-1;
+    dQtoR (q,R);
+    dMassRotate (&m,R);
+    dBodySetMass (body[i],&m);
+  }
+
+  // create ball-n-socket joints at random positions, linking random bodies
+  // (but make sure not to link the same pair of bodies twice)
+  char linked[NUM*NUM];
+  for (i=0; i<NUM*NUM; i++) linked[i] = 0;
+  for (i=0; i<NUMJ; i++) {
+    int b1,b2;
+    do {
+      b1 = dRandInt (NUM);
+      b2 = dRandInt (NUM);
+    } while (linked[b1*NUM + b2] || b1==b2);
+    linked[b1*NUM + b2] = 1;
+    linked[b2*NUM + b1] = 1;
+    joint[i] = dJointCreateBall (world,0);
+    dJointAttach (joint[i],body[b1],body[b2]);
+    dJointSetBallAnchor (joint[i],dRandReal()*2-1,
+			 dRandReal()*2-1,dRandReal()*2+RADIUS);
+  }
+
+  for (i=0; i<NUM; i++) {
+    // move bodies a bit to get some joint error
+    const dReal *pos = dBodyGetPosition (body[i]); 
+    dBodySetPosition (body[i],pos[0]+dRandReal()*0.2-0.1,
+		      pos[1]+dRandReal()*0.2-0.1,pos[2]+dRandReal()*0.2-0.1);
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.6117f,-1.4433f,2.3700f};
+  static float hpr[3] = {151.5000f,-30.5000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  if (!pause) {
+    // add random forces and torques to all bodies
+    int i;
+    const dReal scale1 = 5;
+    const dReal scale2 = 5;
+    for (i=0; i<NUM; i++) {
+      dBodyAddForce (body[i],
+		     scale1*(dRandReal()*2-1),
+		     scale1*(dRandReal()*2-1),
+		     scale1*(dRandReal()*2-1));
+      dBodyAddTorque (body[i],
+		     scale2*(dRandReal()*2-1),
+		     scale2*(dRandReal()*2-1),
+		     scale2*(dRandReal()*2-1));
+    }
+
+    dWorldStep (world,0.05);
+    createTest();
+  }
+
+  // float sides[3] = {SIDE,SIDE,SIDE};
+  dsSetColor (1,1,0);
+  for (int i=0; i<NUM; i++)
+    dsDrawSphere (dBodyGetPosition(body[i]), dBodyGetRotation(body[i]),RADIUS);
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = 0;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  dInitODE();
+  dRandSetSeed (time(0));
+  createTest();
+
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/demo_trimesh.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/demo_trimesh.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/demo_trimesh.cpp	(revision 216)
@@ -0,0 +1,537 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// TriMesh test by Erwin de Vries
+
+#include <ode/ode.h>
+#include <drawstuff/drawstuff.h>
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+// select correct drawing functions
+
+#ifdef dDOUBLE
+#define dsDrawBox dsDrawBoxD
+#define dsDrawSphere dsDrawSphereD
+#define dsDrawCylinder dsDrawCylinderD
+#define dsDrawCapsule dsDrawCapsuleD
+#define dsDrawLine dsDrawLineD
+#define dsDrawTriangle dsDrawTriangleD
+#endif
+
+
+// some constants
+
+#define NUM 200			// max number of objects
+#define DENSITY (5.0)		// density of all objects
+#define GPB 3			// maximum number of geometries per body
+#define MAX_CONTACTS 40		// maximum number of contact points per body
+
+
+// dynamics and collision objects
+
+struct MyObject {
+  dBodyID body;			// the body
+  dGeomID geom[GPB];		// geometries representing this body
+};
+
+static int num=0;		// number of objects in simulation
+static int nextobj=0;		// next object to recycle if num==NUM
+static dWorldID world;
+static dSpaceID space;
+static MyObject obj[NUM];
+static dJointGroupID contactgroup;
+static int selected = -1;	// selected object
+static int show_aabb = 0;	// show geom AABBs?
+static int show_contacts = 0;	// show contact points?
+static int random_pos = 1;	// drop objects from random position?
+
+#define VertexCount 5
+#define IndexCount 12
+
+static dVector3 Size;
+static dVector3 Vertices[VertexCount];
+static int Indices[IndexCount];
+
+static dGeomID TriMesh;
+static dGeomID Ray;
+
+
+// this is called by dSpaceCollide when two objects in space are
+// potentially colliding.
+
+static void nearCallback (void *data, dGeomID o1, dGeomID o2)
+{
+  int i;
+  // if (o1->body && o2->body) return;
+
+  // exit without doing anything if the two bodies are connected by a joint
+  dBodyID b1 = dGeomGetBody(o1);
+  dBodyID b2 = dGeomGetBody(o2);
+  if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
+
+  dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
+  for (i=0; i<MAX_CONTACTS; i++) {
+    contact[i].surface.mode = dContactBounce | dContactSoftCFM;
+    contact[i].surface.mu = dInfinity;
+    contact[i].surface.mu2 = 0;
+    contact[i].surface.bounce = 0.1;
+    contact[i].surface.bounce_vel = 0.1;
+    contact[i].surface.soft_cfm = 0.01;
+  }
+  if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
+			   sizeof(dContact))) {
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    const dReal ss[3] = {0.02,0.02,0.02};
+    for (i=0; i<numc; i++) {
+		if (dGeomGetClass(o1) == dRayClass || dGeomGetClass(o2) == dRayClass){
+			dMatrix3 Rotation;
+			dRSetIdentity(Rotation);
+			dsDrawSphere(contact[i].geom.pos, Rotation, REAL(0.01));
+			
+			dVector3 End;
+			End[0] = contact[i].geom.pos[0] + (contact[i].geom.normal[0] * contact[i].geom.depth);
+			End[1] = contact[i].geom.pos[1] + (contact[i].geom.normal[1] * contact[i].geom.depth);
+			End[2] = contact[i].geom.pos[2] + (contact[i].geom.normal[2] * contact[i].geom.depth);
+			End[3] = contact[i].geom.pos[3] + (contact[i].geom.normal[3] * contact[i].geom.depth);
+			
+			dsDrawLine(contact[i].geom.pos, End);
+			continue;
+		}
+		
+      dJointID c = dJointCreateContact (world,contactgroup,contact+i);
+      dJointAttach (c,b1,b2);
+      if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
+    }
+  }
+}
+
+
+// start simulation - set viewpoint
+
+static void start()
+{
+  static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
+  static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
+  dsSetViewpoint (xyz,hpr);
+  printf ("To drop another object, press:\n");
+  printf ("   b for box.\n");
+  printf ("   s for sphere.\n");
+  printf ("   c for cylinder.\n");
+  printf ("   x for a composite object.\n");
+  printf ("To select an object, press space.\n");
+  printf ("To disable the selected object, press d.\n");
+  printf ("To enable the selected object, press e.\n");
+  printf ("To toggle showing the geom AABBs, press a.\n");
+  printf ("To toggle showing the contact points, press t.\n");
+  printf ("To toggle dropping from random position/orientation, press r.\n");
+}
+
+
+char locase (char c)
+{
+  if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
+  else return c;
+}
+
+
+// called when a key pressed
+
+static void command (int cmd)
+{
+  int i,j,k;
+  dReal sides[3];
+  dMass m;
+
+  cmd = locase (cmd);
+  if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x'
+      /* || cmd == 'l' */) {
+    if (num < NUM) {
+      i = num;
+      num++;
+    }
+    else {
+      i = nextobj;
+      nextobj++;
+      if (nextobj >= num) nextobj = 0;
+
+      // destroy the body and geoms for slot i
+      dBodyDestroy (obj[i].body);
+      for (k=0; k < GPB; k++) {
+	if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
+      }
+      memset (&obj[i],0,sizeof(obj[i]));
+    }
+
+    obj[i].body = dBodyCreate (world);
+    for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
+
+    dMatrix3 R;
+    if (random_pos) {
+      dBodySetPosition (obj[i].body,
+			dRandReal()*2-1,dRandReal()*2-1,dRandReal()+1);
+      dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			  dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+    }
+    else {
+      dReal maxheight = 0;
+      for (k=0; k<num; k++) {
+	const dReal *pos = dBodyGetPosition (obj[k].body);
+	if (pos[2] > maxheight) maxheight = pos[2];
+      }
+      dBodySetPosition (obj[i].body, 0,0,maxheight+1);
+      dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
+    }
+    dBodySetRotation (obj[i].body,R);
+    dBodySetData (obj[i].body,(void*)(size_t)i);
+
+    if (cmd == 'b') {
+      dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
+      obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
+    }
+    else if (cmd == 'c') {
+      sides[0] *= 0.5;
+      dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
+    }
+/*
+    // cylinder option not yet implemented
+    else if (cmd == 'l') {
+      sides[1] *= 0.5;
+      dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
+      obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
+    }
+*/
+    else if (cmd == 's') {
+      sides[0] *= 0.5;
+      dMassSetSphere (&m,DENSITY,sides[0]);
+      obj[i].geom[0] = dCreateSphere (space,sides[0]);
+    }
+    else if (cmd == 'x') {
+      dGeomID g2[GPB];		// encapsulated geometries
+      dReal dpos[GPB][3];	// delta-positions for encapsulated geometries
+
+      // start accumulating masses for the encapsulated geometries
+      dMass m2;
+      dMassSetZero (&m);
+
+      // set random delta positions
+      for (j=0; j<GPB; j++) {
+	for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
+      }
+
+      for (k=0; k<GPB; k++) {
+	obj[i].geom[k] = dCreateGeomTransform (space);
+	dGeomTransformSetCleanup (obj[i].geom[k],1);
+	if (k==0) {
+	  dReal radius = dRandReal()*0.25+0.05;
+	  g2[k] = dCreateSphere (0,radius);
+	  dMassSetSphere (&m2,DENSITY,radius);
+	}
+	else if (k==1) {
+	  g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
+	  dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
+	}
+	else {
+	  dReal radius = dRandReal()*0.1+0.05;
+	  dReal length = dRandReal()*1.0+0.1;
+	  g2[k] = dCreateCapsule (0,radius,length);
+	  dMassSetCapsule (&m2,DENSITY,3,radius,length);
+	}
+	dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
+
+	// set the transformation (adjust the mass too)
+	dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
+	dMatrix3 Rtx;
+	dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
+			    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
+	dGeomSetRotation (g2[k],Rtx);
+	dMassRotate (&m2,Rtx);
+
+	// add to the total mass
+	dMassAdd (&m,&m2);
+      }
+
+      // move all encapsulated objects so that the center of mass is (0,0,0)
+      for (k=0; k<2; k++) {
+	dGeomSetPosition (g2[k],
+			  dpos[k][0]-m.c[0],
+			  dpos[k][1]-m.c[1],
+			  dpos[k][2]-m.c[2]);
+      }
+      dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
+    }
+
+    for (k=0; k < GPB; k++) {
+      if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
+    }
+
+    dBodySetMass (obj[i].body,&m);
+  }
+
+  if (cmd == ' ') {
+    selected++;
+    if (selected >= num) selected = 0;
+    if (selected < 0) selected = 0;
+  }
+  else if (cmd == 'd' && selected >= 0 && selected < num) {
+    dBodyDisable (obj[selected].body);
+  }
+  else if (cmd == 'e' && selected >= 0 && selected < num) {
+    dBodyEnable (obj[selected].body);
+  }
+  else if (cmd == 'a') {
+    show_aabb ^= 1;
+  }
+  else if (cmd == 't') {
+    show_contacts ^= 1;
+  }
+  else if (cmd == 'r') {
+    random_pos ^= 1;
+  }
+}
+
+
+// draw a geom
+
+void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
+{
+  if (!g) return;
+  if (!pos) pos = dGeomGetPosition (g);
+  if (!R) R = dGeomGetRotation (g);
+
+  int type = dGeomGetClass (g);
+  if (type == dBoxClass) {
+    dVector3 sides;
+    dGeomBoxGetLengths (g,sides);
+    dsDrawBox (pos,R,sides);
+  }
+  else if (type == dSphereClass) {
+    dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
+  }
+  else if (type == dCapsuleClass) {
+    dReal radius,length;
+    dGeomCapsuleGetParams (g,&radius,&length);
+    dsDrawCapsule (pos,R,length,radius);
+  }
+/*
+  // cylinder option not yet implemented
+  else if (type == dCylinderClass) {
+    dReal radius,length;
+    dGeomCylinderGetParams (g,&radius,&length);
+    dsDrawCylinder (pos,R,length,radius);
+  }
+*/
+  else if (type == dGeomTransformClass) {
+    dGeomID g2 = dGeomTransformGetGeom (g);
+    const dReal *pos2 = dGeomGetPosition (g2);
+    const dReal *R2 = dGeomGetRotation (g2);
+    dVector3 actual_pos;
+    dMatrix3 actual_R;
+    dMULTIPLY0_331 (actual_pos,R,pos2);
+    actual_pos[0] += pos[0];
+    actual_pos[1] += pos[1];
+    actual_pos[2] += pos[2];
+    dMULTIPLY0_333 (actual_R,R,R2);
+    drawGeom (g2,actual_pos,actual_R,0);
+  }
+
+  if (show_aabb) {
+    // draw the bounding box for this geom
+    dReal aabb[6];
+    dGeomGetAABB (g,aabb);
+    dVector3 bbpos;
+    for (int i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
+    dVector3 bbsides;
+    for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];
+    dMatrix3 RI;
+    dRSetIdentity (RI);
+    dsSetColorAlpha (1,0,0,0.5);
+    dsDrawBox (bbpos,RI,bbsides);
+  }
+}
+
+
+// simulation loop
+
+static void simLoop (int pause)
+{
+  dsSetColor (0,0,2);
+  dSpaceCollide (space,0,&nearCallback);
+  if (!pause) dWorldStep (world,0.05);
+  //if (!pause) dWorldStepFast (world,0.05, 1);
+
+  // remove all contact joints
+  dJointGroupEmpty (contactgroup);
+
+  dsSetColor (1,1,0);
+  dsSetTexture (DS_WOOD);
+  for (int i=0; i<num; i++) {
+    for (int j=0; j < GPB; j++) {
+      if (i==selected) {
+	dsSetColor (0,0.7,1);
+      }
+      else if (! dBodyIsEnabled (obj[i].body)) {
+	dsSetColor (1,0,0);
+      }
+      else {
+	dsSetColor (1,1,0);
+      }
+      drawGeom (obj[i].geom[j],0,0,show_aabb);
+    }
+  }
+
+  /*{
+    for (int i = 1; i < IndexCount; i++) {
+      dsDrawLine(Vertices[Indices[i - 1]], Vertices[Indices[i]]);
+    }
+  }*/
+
+  {const dReal* Pos = dGeomGetPosition(TriMesh);
+  const dReal* Rot = dGeomGetRotation(TriMesh);
+
+  {for (int i = 0; i < IndexCount / 3; i++){
+    const dVector3& v0 = Vertices[Indices[i * 3 + 0]];
+	const dVector3& v1 = Vertices[Indices[i * 3 + 1]];
+	const dVector3& v2 = Vertices[Indices[i * 3 + 2]];
+	dsDrawTriangle(Pos, Rot, (dReal*)&v0, (dReal*)&v1, (dReal*)&v2, 0);
+  }}}
+
+  if (Ray){
+	  dVector3 Origin, Direction;
+	  dGeomRayGet(Ray, Origin, Direction);
+	  
+	  dReal Length = dGeomRayGetLength(Ray);
+	  
+	  dVector3 End;
+	  End[0] = Origin[0] + (Direction[0] * Length);
+	  End[1] = Origin[1] + (Direction[1] * Length);
+	  End[2] = Origin[2] + (Direction[2] * Length);
+	  End[3] = Origin[3] + (Direction[3] * Length);
+	  
+	  dsDrawLine(Origin, End);
+  }
+}
+
+
+int main (int argc, char **argv)
+{
+  // setup pointers to drawstuff callback functions
+  dsFunctions fn;
+  fn.version = DS_VERSION;
+  fn.start = &start;
+  fn.step = &simLoop;
+  fn.command = &command;
+  fn.stop = 0;
+  fn.path_to_textures = "../../drawstuff/textures";
+  if(argc==2)
+    {
+        fn.path_to_textures = argv[1];
+    }
+
+  // create world
+  dInitODE();
+  world = dWorldCreate();
+
+  space = dSimpleSpaceCreate(0);
+  contactgroup = dJointGroupCreate (0);
+  dWorldSetGravity (world,0,0,-0.5);
+  dWorldSetCFM (world,1e-5);
+  //dCreatePlane (space,0,0,1,0);
+  memset (obj,0,sizeof(obj));
+  
+  Size[0] = 5.0f;
+  Size[1] = 5.0f;
+  Size[2] = 2.5f;
+  
+  Vertices[0][0] = -Size[0];
+  Vertices[0][1] = -Size[1];
+  Vertices[0][2] = Size[2];
+  
+  Vertices[1][0] = Size[0];
+  Vertices[1][1] = -Size[1];
+  Vertices[1][2] = Size[2];
+  
+  Vertices[2][0] = Size[0];
+  Vertices[2][1] = Size[1];
+  Vertices[2][2] = Size[2];
+  
+  Vertices[3][0] = -Size[0];
+  Vertices[3][1] = Size[1];
+  Vertices[3][2] = Size[2];
+  
+  Vertices[4][0] = 0;
+  Vertices[4][1] = 0;
+  Vertices[4][2] = 0;
+  
+  Indices[0] = 0;
+  Indices[1] = 1;
+  Indices[2] = 4;
+  
+  Indices[3] = 1;
+  Indices[4] = 2;
+  Indices[5] = 4;
+  
+  Indices[6] = 2;
+  Indices[7] = 3;
+  Indices[8] = 4;
+  
+  Indices[9] = 3;
+  Indices[10] = 0;
+  Indices[11] = 4;
+
+  dTriMeshDataID Data = dGeomTriMeshDataCreate();
+
+  dGeomTriMeshDataBuildSimple(Data, (dReal*)Vertices, VertexCount, Indices, IndexCount);
+  
+  TriMesh = dCreateTriMesh(space, Data, 0, 0, 0);
+
+  //dGeomSetPosition(TriMesh, 0, 0, 1.0);
+  
+  Ray = dCreateRay(space, 0.9);
+  dVector3 Origin, Direction;
+  Origin[0] = 0.0;
+  Origin[1] = 0;
+  Origin[2] = 0.5;
+  Origin[3] = 0;
+  
+  Direction[0] = 0;
+  Direction[1] = 1.1f;
+  Direction[2] = -1;
+  Direction[3] = 0;
+  dNormalize3(Direction);
+  
+  dGeomRaySet(Ray, Origin[0], Origin[1], Origin[2], Direction[0], Direction[1], Direction[2]);
+  
+  // run simulation
+  dsSimulationLoop (argc,argv,352,288,&fn);
+
+  dJointGroupDestroy (contactgroup);
+  dSpaceDestroy (space);
+  dWorldDestroy (world);
+  dCloseODE();
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/demo/world_geom3.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/demo/world_geom3.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/demo/world_geom3.h	(revision 216)
@@ -0,0 +1,9 @@
+// mesh for a world model, to be used with test_cyl.cpp
+
+static float world_vertices[] = {10.000000f,-10.000000f,1.000000f,-10.000000f,-10.000000f,1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,10.000000f,-10.000000f,-1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,-10.000000f,-1.000000f,10.000000f,-10.000000f,-1.000000f,10.000000f,10.000000f,-1.000000f,10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,-1.000000f,10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,10.000000f,-1.000000f,10.000000f,10.000000f,-1.000000f,0.000000f,9.000000f,-0.000000f,0.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,0.000000f,0.000000f,9.000000f,-0.000000f,9.000000f,-9.000000f,0.000000f,9.000000f,9.000000f,-0.000000f,10.000000f,10.000000f,-1.000000f,-10.000000f,10.000000f,-1.000000f,-10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,-1.000000f,-10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,-10.000000f,-10.000000f,-1.000000f,-10.000000f,-10.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-10.000000f,10.000000f,-1.000000f,-10.000000f,-10.000000f,-1.000000f,9.000000f,-9.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,-10.000000f,-10.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,9.000000f,9.000000f,1.000000f,9.000000f,-9.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,-10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,9.000000f,9.000000f,1.000000f,10.000000f,10.000000f,1.000000f,10.000000f,10.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,-10.000000f,10.000000f,1.000000f,-10.000000f,-10.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,0.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,1.000000f,0.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,1.000000f,9.000000f,-9.000000f,1.000000f,0.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,1.000000f,9.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,0.000000f,9.000000f,-9.000000f,1.000000f,9.000000f,9.000000f,1.000000f,9.000000f,9.000000f,1.000000f,9.000000f,9.000000f,-0.000000f,9.000000f,-9.000000f,0.000000f,0.000000f,9.000000f,-0.000000f,9.000000f,9.000000f,-0.000000f,9.000000f,9.000000f,1.000000f,0.000000f,9.000000f,-0.000000f,9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,1.000000f,0.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,1.000000f,-9.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,1.000000f,-9.000000f,-9.000000f,1.000000f,-9.000000f,-9.000000f,0.000000f,-9.000000f,-9.000000f,0.000000f,-9.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,1.000000f,-2.997000f,-1.748874f,0.000000f,-2.997000f,-2.001000f,0.000000f,0.000000f,-9.000000f,0.000000f,-2.997000f,-1.748874f,0.000000f,0.000000f,-9.000000f,0.000000f,-2.997000f,1.748874f,-0.000000f,-2.997000f,-2.001000f,0.000000f,-2.997000f,-6.003000f,0.002697f,0.000000f,-9.000000f,0.000000f,0.000000f,9.000000f,-0.000000f,-2.997000f,2.001000f,-0.000000f,-2.997000f,1.748874f,-0.000000f,0.000000f,9.000000f,-0.000000f,-2.997000f,1.748874f,-0.000000f,0.000000f,-9.000000f,0.000000f,-2.997000f,2.001000f,-0.000000f,0.000000f,9.000000f,-0.000000f,-2.997000f,6.003000f,0.002697f,-6.003000f,6.003000f,0.002697f,-2.997000f,6.003000f,0.002697f,0.000000f,9.000000f,-0.000000f,0.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,-0.000000f,-6.003000f,6.003000f,0.002697f,-6.003000f,1.748874f,-0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,2.001000f,-0.000000f,-6.003000f,6.003000f,0.002697f,-9.000000f,9.000000f,-0.000000f,-9.000000f,9.000000f,-0.000000f,-6.003000f,1.748874f,-0.000000f,-6.003000f,2.001000f,-0.000000f,-9.000000f,9.000000f,-0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,1.748874f,-0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,-6.003000f,0.002697f,-6.003000f,-2.001000f,0.000000f,-9.000000f,-9.000000f,0.000000f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-6.003000f,0.002697f,-9.000000f,-9.000000f,0.000000f,0.000000f,-9.000000f,0.000000f,-6.003000f,-6.003000f,0.002697f,0.000000f,-9.000000f,0.000000f,-2.997000f,-6.003000f,0.002697f,-2.997000f,1.748874f,1.237951f,-2.997000f,1.748874f,-0.000000f,-2.997000f,2.001000f,-0.000000f,-2.997000f,1.748874f,1.237951f,-2.997000f,2.001000f,-0.000000f,-2.997000f,2.001000f,1.515748f,-6.003000f,-2.001000f,1.515748f,-6.003000f,-6.003000f,0.002697f,-2.997000f,-6.003000f,0.002697f,-6.003000f,-2.001000f,1.515748f,-2.997000f,-6.003000f,0.002697f,-2.997000f,-2.001000f,1.515748f,-2.997000f,2.001000f,1.515748f,-2.997000f,6.003000f,0.002697f,-6.003000f,6.003000f,0.002697f,-6.003000f,6.003000f,0.002697f,-6.003000f,2.001000f,1.515748f,-2.997000f,2.001000f,1.515748f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-6.003000f,0.002697f,-6.003000f,-2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,6.003000f,0.002697f,-6.003000f,2.001000f,-0.000000f,-2.997000f,-2.001000f,1.515748f,-2.997000f,-6.003000f,0.002697f,-2.997000f,-2.001000f,0.000000f,-2.997000f,2.001000f,-0.000000f,-2.997000f,6.003000f,0.002697f,-2.997000f,2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-2.997000f,2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,-2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-2.997000f,-1.748874f,1.237951f,-2.997000f,1.748874f,1.237951f,-2.997000f,2.001000f,1.515748f,-2.997000f,-1.748874f,1.237951f,-2.997000f,2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-6.003000f,-1.748874f,1.237951f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-1.748874f,1.237951f,-6.003000f,-2.001000f,0.000000f,-6.003000f,-2.001000f,1.515748f,-2.997000f,-2.001000f,1.515748f,-2.997000f,-2.001000f,0.000000f,-2.997000f,-1.748874f,1.237951f,-2.997000f,-2.001000f,0.000000f,-2.997000f,-1.748874f,0.000000f,-2.997000f,-1.748874f,1.237951f,-6.003000f,1.748874f,1.237951f,-6.003000f,2.001000f,1.515748f,-6.003000f,2.001000f,-0.000000f,-6.003000f,1.748874f,1.237951f,-6.003000f,2.001000f,-0.000000f,-6.003000f,1.748874f,-0.000000f,-6.003000f,1.748874f,1.237951f,-6.003000f,-1.748874f,1.237951f,-6.003000f,-2.001000f,1.515748f,-6.003000f,1.748874f,1.237951f,-6.003000f,-2.001000f,1.515748f,-6.003000f,2.001000f,1.515748f,-6.003000f,1.748874f,1.237951f,-6.003000f,1.748874f,-0.000000f,-2.997000f,1.748874f,1.237951f,-6.003000f,1.748874f,-0.000000f,-2.997000f,1.748874f,-0.000000f,-2.997000f,1.748874f,1.237951f,-6.003000f,1.748874f,-0.000000f,-6.003000f,-1.748874f,0.000000f,-2.997000f,-1.748874f,0.000000f,-6.003000f,1.748874f,-0.000000f,-2.997000f,-1.748874f,0.000000f,-2.997000f,1.748874f,-0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f,-2.997000f,-1.748874f,0.000000f,-6.003000f,-1.748874f,0.000000f,-6.003000f,-1.748874f,1.237951f,-6.003000f,1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f,-6.003000f,1.748874f,1.237951f,-2.997000f,1.748874f,1.237951f,-2.997000f,-1.748874f,1.237951f};
+
+static float world_normals[] = {0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000225f,0.000161f,1.000000f,0.000225f,-0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,0.000225f,0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,-0.000000f,0.000000f,1.000000f,0.000787f,0.000337f,1.000000f,0.000225f,-0.000161f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000225f,-0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,0.000787f,0.000337f,1.000000f,0.000400f,-0.179805f,0.983702f,0.000225f,-0.000161f,1.000000f,0.000225f,0.000161f,1.000000f,0.000787f,-0.000337f,1.000000f,0.000000f,0.000000f,1.000000f,0.000225f,0.000161f,1.000000f,0.000000f,0.000000f,1.000000f,0.000225f,-0.000161f,1.000000f,0.000787f,-0.000337f,1.000000f,0.000225f,0.000161f,1.000000f,0.000532f,0.119686f,0.992812f,-0.000320f,0.143927f,0.989588f,0.000532f,0.119686f,0.992812f,0.000225f,0.000161f,1.000000f,0.000225f,0.000161f,1.000000f,-0.000393f,0.000056f,1.000000f,-0.000320f,0.143927f,0.989588f,-0.000000f,0.000000f,1.000000f,-0.000315f,-0.000045f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000787f,-0.000337f,1.000000f,-0.000320f,0.143927f,0.989588f,-0.000393f,0.000056f,1.000000f,-0.000393f,0.000056f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000787f,-0.000337f,1.000000f,-0.000393f,0.000056f,1.000000f,-0.000315f,-0.000045f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000315f,-0.000045f,1.000000f,-0.000398f,-0.089784f,0.995961f,-0.000787f,0.000337f,1.000000f,-0.000315f,-0.000045f,1.000000f,-0.000787f,0.000337f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000398f,-0.089784f,0.995961f,-0.000315f,-0.000045f,1.000000f,0.000225f,-0.000161f,1.000000f,-0.000398f,-0.089784f,0.995961f,0.000225f,-0.000161f,1.000000f,0.000400f,-0.179805f,0.983702f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,-0.239222f,0.970965f,-0.000398f,-0.089784f,0.995961f,0.000400f,-0.179805f,0.983702f,0.000000f,-0.239222f,0.970965f,0.000400f,-0.179805f,0.983702f,0.000000f,-0.119611f,0.992821f,0.000000f,0.239222f,0.970965f,0.000532f,0.119686f,0.992812f,-0.000320f,0.143927f,0.989588f,-0.000320f,0.143927f,0.989588f,0.000000f,0.119611f,0.992821f,0.000000f,0.239222f,0.970965f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,-0.119611f,0.992821f,0.000000f,0.239222f,0.970965f,0.000000f,0.119611f,0.992821f,0.000000f,0.119611f,0.992821f,0.000000f,-0.239222f,0.970965f,0.000000f,-0.119611f,0.992821f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,-0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,1.000000f,0.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f,0.000000f,0.000000f,-1.000000f};
+
+
+static int world_indices[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227};
+
Index: /code/branches/ode/ode-0.9/ode/doc/Doxyfile
===================================================================
--- /code/branches/ode/ode-0.9/ode/doc/Doxyfile	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/doc/Doxyfile	(revision 216)
@@ -0,0 +1,1237 @@
+# Doxyfile 1.4.6-NO
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "Open Dynamics Engine"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../../docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = YES
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 3
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to 
+# include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = . ../../include/ode ../../include/drawstuff
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS          = *.h *.c *.cpp *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = pix
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = .
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
Index: /code/branches/ode/ode-0.9/ode/doc/main.dox
===================================================================
--- /code/branches/ode/ode-0.9/ode/doc/main.dox	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/doc/main.dox	(revision 216)
@@ -0,0 +1,22 @@
+/**
+@mainpage Open Dynamics Engine API Reference
+ 
+<center><em>This document is &copy; Russell Smith and the ODE Project</em></center>
+
+The Open Dynamics Engine (ODE) is a free, industrial quality library for 
+simulating articulated rigid body dynamics. ODE is being developed by 
+<a href="http://www.q12.org/">Russell Smith</a> with help from several 
+<a href="http://ode.org/community.html">contributors</a>.
+
+This document describes the library API. For a more general introduction 
+to ODE, please see the <a href="http://opende.sourceforge.net/wiki/index.php/Manual">
+Online Handbook</a>.
+
+<h2>Important: this document is not yet complete!</h2>
+
+We are still working on getting the full API documentated. In the meantime,
+please refer to the <a href="http://opende.sourceforge.net/wiki/index.php/Manual">
+Online Handbook</a>
+ 
+*/
+ 
Index: /code/branches/ode/ode-0.9/ode/src/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/Makefile.am	(revision 216)
@@ -0,0 +1,207 @@
+AM_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CPPFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+lib_LIBRARIES = libode.a
+libode_a_CPPFLAGS = -O2
+
+libode_a_CPPFLAGS += -fPIC
+
+# Fake an executable in order to get a shared library
+# Note the elegant and cunning way to trick Autotools to install a program
+# in a lib directory. --Rodrigo
+traplibdir=$(libdir)
+EXEEXT=@so_ext@
+traplib_PROGRAMS=libode
+libode_SOURCES=
+libode_DEPENDENCIES = libfast.a libode.a
+libode_LDFLAGS= @SHARED_LDFLAGS@
+if USE_SONAME
+libode_LDFLAGS+=-Wl,-soname,@ODE_SONAME@
+endif
+libode_LDADD=$(libode_a_OBJECTS) $(libfast_a_OBJECTS)
+
+if OPCODE
+libode_DEPENDENCIES+= libOPCODE.a
+libode_LDADD+=$(libOPCODE_a_OBJECTS)
+endif
+
+
+if GIMPACT
+libode_DEPENDENCIES+= libGIMPACT.a
+libode_LDADD+=$(libGIMPACT_a_OBJECTS)
+endif
+
+
+# convenience library to simulate per object cflags
+noinst_LIBRARIES= libfast.a
+libfast_a_CFLAGS= -O1
+libfast_a_SOURCES= fastldlt.c fastltsolve.c fastdot.c fastlsolve.c
+
+libfast_a_CFLAGS += -fPIC
+
+libode_a_DEPENDENCIES = libfast.a
+libode_a_LIBADD= $(libfast_a_OBJECTS)
+
+libode_a_SOURCES = 	objects.h \
+			obstack.cpp \
+			collision_util.cpp \
+			obstack.h \
+			array.cpp \
+			collision_util.h \
+			ode.cpp \
+			array.h \
+			error.cpp \
+			odemath.cpp \
+			collision_kernel.cpp \
+			export-dif.cpp \
+			quickstep.cpp \
+			collision_kernel.h \
+			quickstep.h \
+			collision_quadtreespace.cpp \
+			rotation.cpp \
+			collision_space.cpp \
+			collision_space_internal.h \
+                        collision_cylinder_box.cpp \
+                        collision_cylinder_sphere.cpp \
+                        collision_cylinder_plane.cpp \
+			sphere.cpp \
+			box.cpp \
+			capsule.cpp \
+			plane.cpp \
+			ray.cpp \
+			cylinder.cpp \
+			convex.cpp \
+			joint.cpp \
+			stack.h \
+			collision_std.h \
+			joint.h \
+			step.cpp \
+			collision_transform.cpp \
+			lcp.cpp \
+			step.h \
+			collision_transform.h \
+			lcp.h \
+			stepfast.cpp \
+			mass.cpp \
+			testing.cpp \
+			mat.cpp \
+			testing.h \
+			mat.h \
+			timer.cpp \
+			matrix.cpp \
+			util.cpp \
+			memory.cpp \
+			util.h \
+			misc.cpp \
+			heightfield.cpp \
+			heightfield.h
+
+
+
+###################################
+#   G I M P A C T    S T U F F
+###################################
+
+
+if GIMPACT
+noinst_LIBRARIES+= libGIMPACT.a
+libGIMPACT_a_CPPFLAGS= -O2 -fno-strict-aliasing -fPIC
+
+libode_a_SOURCES+= collision_trimesh_gimpact.cpp
+
+libGIMPACT_a_SOURCES = \
+  @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp \
+  @TOPDIR@/GIMPACT/src/gim_contact.cpp \
+  @TOPDIR@/GIMPACT/src/gim_math.cpp \
+  @TOPDIR@/GIMPACT/src/gim_memory.cpp \
+  @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp \
+  @TOPDIR@/GIMPACT/src/gim_trimesh.cpp \
+  @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp \
+  @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp \
+  @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp \
+  @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp \
+  @TOPDIR@/GIMPACT/src/gimpact.cpp
+
+libode_a_DEPENDENCIES+=libGIMPACT.a
+libode_a_LIBADD+= $(libGIMPACT_a_OBJECTS)
+AM_CXXFLAGS += -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
+AM_CFLAGS += -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
+
+libode_a_SOURCES+=	collision_trimesh_trimesh.cpp \
+			collision_trimesh_sphere.cpp \
+			collision_trimesh_ray.cpp \
+			collision_trimesh_opcode.cpp \
+			collision_trimesh_box.cpp \
+			collision_trimesh_ccylinder.cpp \
+			collision_trimesh_distance.cpp \
+			collision_trimesh_internal.h \
+                        collision_cylinder_trimesh.cpp \
+                        collision_trimesh_plane.cpp
+endif
+
+
+
+#################################
+#   O P C O D E    S T U F F
+#################################
+
+
+if OPCODE
+noinst_LIBRARIES+= libOPCODE.a
+libOPCODE_a_CPPFLAGS= -O2 -fno-strict-aliasing -fPIC
+
+
+libOPCODE_a_SOURCES=	@TOPDIR@/OPCODE/OPC_AABBCollider.cpp \
+			@TOPDIR@/OPCODE/OPC_AABBTree.cpp \
+			@TOPDIR@/OPCODE/OPC_BaseModel.cpp \
+			@TOPDIR@/OPCODE/OPC_BoxPruning.cpp \
+			@TOPDIR@/OPCODE/OPC_Collider.cpp \
+			@TOPDIR@/OPCODE/OPC_Common.cpp \
+			@TOPDIR@/OPCODE/OPC_HybridModel.cpp \
+			@TOPDIR@/OPCODE/OPC_LSSCollider.cpp \
+			@TOPDIR@/OPCODE/OPC_MeshInterface.cpp \
+			@TOPDIR@/OPCODE/OPC_Model.cpp \
+			@TOPDIR@/OPCODE/OPC_OBBCollider.cpp \
+			@TOPDIR@/OPCODE/Opcode.cpp \
+			@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp \
+			@TOPDIR@/OPCODE/OPC_Picking.cpp \
+			@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp \
+			@TOPDIR@/OPCODE/OPC_RayCollider.cpp \
+			@TOPDIR@/OPCODE/OPC_SphereCollider.cpp \
+			@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp \
+			@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp \
+			@TOPDIR@/OPCODE/OPC_TreeCollider.cpp \
+			@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp \
+			@TOPDIR@/OPCODE/Ice/IceAABB.cpp \
+			@TOPDIR@/OPCODE/Ice/IceContainer.cpp \
+			@TOPDIR@/OPCODE/Ice/IceHPoint.cpp \
+			@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp \
+			@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp \
+			@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp \
+			@TOPDIR@/OPCODE/Ice/IceOBB.cpp \
+			@TOPDIR@/OPCODE/Ice/IcePlane.cpp \
+			@TOPDIR@/OPCODE/Ice/IcePoint.cpp \
+			@TOPDIR@/OPCODE/Ice/IceRandom.cpp \
+			@TOPDIR@/OPCODE/Ice/IceRay.cpp \
+			@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp \
+			@TOPDIR@/OPCODE/Ice/IceSegment.cpp \
+			@TOPDIR@/OPCODE/Ice/IceTriangle.cpp \
+			@TOPDIR@/OPCODE/Ice/IceUtils.cpp
+libode_a_DEPENDENCIES+=libOPCODE.a
+
+libode_a_LIBADD+= $(libOPCODE_a_OBJECTS)
+AM_CXXFLAGS += -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
+AM_CFLAGS += -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
+libode_a_SOURCES+=	collision_trimesh_trimesh.cpp \
+			collision_trimesh_sphere.cpp \
+			collision_trimesh_ray.cpp \
+			collision_trimesh_opcode.cpp \
+			collision_trimesh_box.cpp \
+			collision_trimesh_ccylinder.cpp \
+			collision_trimesh_distance.cpp \
+			collision_trimesh_internal.h \
+                        collision_cylinder_trimesh.cpp \
+                        collision_trimesh_plane.cpp
+endif
+
+
Index: /code/branches/ode/ode-0.9/ode/src/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/Makefile.in	(revision 216)
@@ -0,0 +1,2290 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+traplib_PROGRAMS = libode$(EXEEXT)
+@USE_SONAME_TRUE@am__append_1 = -Wl,-soname,@ODE_SONAME@
+@OPCODE_TRUE@am__append_2 = libOPCODE.a
+@OPCODE_TRUE@am__append_3 = $(libOPCODE_a_OBJECTS)
+@GIMPACT_TRUE@am__append_4 = libGIMPACT.a
+@GIMPACT_TRUE@am__append_5 = $(libGIMPACT_a_OBJECTS)
+
+###################################
+#   G I M P A C T    S T U F F
+###################################
+@GIMPACT_TRUE@am__append_6 = libGIMPACT.a
+@GIMPACT_TRUE@am__append_7 = collision_trimesh_gimpact.cpp \
+@GIMPACT_TRUE@	collision_trimesh_trimesh.cpp \
+@GIMPACT_TRUE@	collision_trimesh_sphere.cpp \
+@GIMPACT_TRUE@	collision_trimesh_ray.cpp \
+@GIMPACT_TRUE@	collision_trimesh_opcode.cpp \
+@GIMPACT_TRUE@	collision_trimesh_box.cpp \
+@GIMPACT_TRUE@	collision_trimesh_ccylinder.cpp \
+@GIMPACT_TRUE@	collision_trimesh_distance.cpp \
+@GIMPACT_TRUE@	collision_trimesh_internal.h \
+@GIMPACT_TRUE@	collision_cylinder_trimesh.cpp \
+@GIMPACT_TRUE@	collision_trimesh_plane.cpp
+@GIMPACT_TRUE@am__append_8 = libGIMPACT.a
+@GIMPACT_TRUE@am__append_9 = $(libGIMPACT_a_OBJECTS)
+@GIMPACT_TRUE@am__append_10 = -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
+@GIMPACT_TRUE@am__append_11 = -I@TOPDIR@/GIMPACT/include -DdTRIMESH_ENABLED -DdTRIMESH_GIMPACT
+
+#################################
+#   O P C O D E    S T U F F
+#################################
+@OPCODE_TRUE@am__append_12 = libOPCODE.a
+@OPCODE_TRUE@am__append_13 = libOPCODE.a
+@OPCODE_TRUE@am__append_14 = $(libOPCODE_a_OBJECTS)
+@OPCODE_TRUE@am__append_15 = -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
+@OPCODE_TRUE@am__append_16 = -I@TOPDIR@/OPCODE -I@TOPDIR@/OPCODE/Ice -DdTRIMESH_ENABLED -DdTRIMESH_OPCODE
+@OPCODE_TRUE@am__append_17 = collision_trimesh_trimesh.cpp \
+@OPCODE_TRUE@			collision_trimesh_sphere.cpp \
+@OPCODE_TRUE@			collision_trimesh_ray.cpp \
+@OPCODE_TRUE@			collision_trimesh_opcode.cpp \
+@OPCODE_TRUE@			collision_trimesh_box.cpp \
+@OPCODE_TRUE@			collision_trimesh_ccylinder.cpp \
+@OPCODE_TRUE@			collision_trimesh_distance.cpp \
+@OPCODE_TRUE@			collision_trimesh_internal.h \
+@OPCODE_TRUE@                        collision_cylinder_trimesh.cpp \
+@OPCODE_TRUE@                        collision_trimesh_plane.cpp
+
+subdir = ode/src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(traplibdir)"
+libLIBRARIES_INSTALL = $(INSTALL_DATA)
+LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libGIMPACT_a_AR = $(AR) $(ARFLAGS)
+libGIMPACT_a_LIBADD =
+am__libGIMPACT_a_SOURCES_DIST =  \
+	@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp \
+	@TOPDIR@/GIMPACT/src/gim_contact.cpp \
+	@TOPDIR@/GIMPACT/src/gim_math.cpp \
+	@TOPDIR@/GIMPACT/src/gim_memory.cpp \
+	@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp \
+	@TOPDIR@/GIMPACT/src/gim_trimesh.cpp \
+	@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp \
+	@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp \
+	@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp \
+	@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp \
+	@TOPDIR@/GIMPACT/src/gimpact.cpp
+@GIMPACT_TRUE@am_libGIMPACT_a_OBJECTS =  \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_boxpruning.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_contact.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_math.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_memory.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_tri_tri_overlap.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_trimesh.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_trimesh_capsule_collision.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_trimesh_ray_collision.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_trimesh_sphere_collision.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gim_trimesh_trimesh_collision.$(OBJEXT) \
+@GIMPACT_TRUE@	libGIMPACT_a-gimpact.$(OBJEXT)
+libGIMPACT_a_OBJECTS = $(am_libGIMPACT_a_OBJECTS)
+libOPCODE_a_AR = $(AR) $(ARFLAGS)
+libOPCODE_a_LIBADD =
+am__libOPCODE_a_SOURCES_DIST = @TOPDIR@/OPCODE/OPC_AABBCollider.cpp \
+	@TOPDIR@/OPCODE/OPC_AABBTree.cpp \
+	@TOPDIR@/OPCODE/OPC_BaseModel.cpp \
+	@TOPDIR@/OPCODE/OPC_BoxPruning.cpp \
+	@TOPDIR@/OPCODE/OPC_Collider.cpp \
+	@TOPDIR@/OPCODE/OPC_Common.cpp \
+	@TOPDIR@/OPCODE/OPC_HybridModel.cpp \
+	@TOPDIR@/OPCODE/OPC_LSSCollider.cpp \
+	@TOPDIR@/OPCODE/OPC_MeshInterface.cpp \
+	@TOPDIR@/OPCODE/OPC_Model.cpp \
+	@TOPDIR@/OPCODE/OPC_OBBCollider.cpp @TOPDIR@/OPCODE/Opcode.cpp \
+	@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp \
+	@TOPDIR@/OPCODE/OPC_Picking.cpp \
+	@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp \
+	@TOPDIR@/OPCODE/OPC_RayCollider.cpp \
+	@TOPDIR@/OPCODE/OPC_SphereCollider.cpp \
+	@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp \
+	@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp \
+	@TOPDIR@/OPCODE/OPC_TreeCollider.cpp \
+	@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp \
+	@TOPDIR@/OPCODE/Ice/IceAABB.cpp \
+	@TOPDIR@/OPCODE/Ice/IceContainer.cpp \
+	@TOPDIR@/OPCODE/Ice/IceHPoint.cpp \
+	@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp \
+	@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp \
+	@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp \
+	@TOPDIR@/OPCODE/Ice/IceOBB.cpp \
+	@TOPDIR@/OPCODE/Ice/IcePlane.cpp \
+	@TOPDIR@/OPCODE/Ice/IcePoint.cpp \
+	@TOPDIR@/OPCODE/Ice/IceRandom.cpp \
+	@TOPDIR@/OPCODE/Ice/IceRay.cpp \
+	@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp \
+	@TOPDIR@/OPCODE/Ice/IceSegment.cpp \
+	@TOPDIR@/OPCODE/Ice/IceTriangle.cpp \
+	@TOPDIR@/OPCODE/Ice/IceUtils.cpp
+@OPCODE_TRUE@am_libOPCODE_a_OBJECTS =  \
+@OPCODE_TRUE@	libOPCODE_a-OPC_AABBCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_AABBTree.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_BaseModel.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_BoxPruning.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_Collider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_Common.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_HybridModel.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_LSSCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_MeshInterface.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_Model.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_OBBCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-Opcode.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_OptimizedTree.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_Picking.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_PlanesCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_RayCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_SphereCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_SweepAndPrune.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_TreeBuilders.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_TreeCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-OPC_VolumeCollider.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceAABB.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceContainer.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceHPoint.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceIndexedTriangle.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceMatrix3x3.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceMatrix4x4.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceOBB.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IcePlane.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IcePoint.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceRandom.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceRay.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceRevisitedRadix.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceSegment.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceTriangle.$(OBJEXT) \
+@OPCODE_TRUE@	libOPCODE_a-IceUtils.$(OBJEXT)
+libOPCODE_a_OBJECTS = $(am_libOPCODE_a_OBJECTS)
+libfast_a_AR = $(AR) $(ARFLAGS)
+libfast_a_LIBADD =
+am_libfast_a_OBJECTS = libfast_a-fastldlt.$(OBJEXT) \
+	libfast_a-fastltsolve.$(OBJEXT) libfast_a-fastdot.$(OBJEXT) \
+	libfast_a-fastlsolve.$(OBJEXT)
+libfast_a_OBJECTS = $(am_libfast_a_OBJECTS)
+libode_a_AR = $(AR) $(ARFLAGS)
+am__libode_a_SOURCES_DIST = objects.h obstack.cpp collision_util.cpp \
+	obstack.h array.cpp collision_util.h ode.cpp array.h error.cpp \
+	odemath.cpp collision_kernel.cpp export-dif.cpp quickstep.cpp \
+	collision_kernel.h quickstep.h collision_quadtreespace.cpp \
+	rotation.cpp collision_space.cpp collision_space_internal.h \
+	collision_cylinder_box.cpp collision_cylinder_sphere.cpp \
+	collision_cylinder_plane.cpp sphere.cpp box.cpp capsule.cpp \
+	plane.cpp ray.cpp cylinder.cpp convex.cpp joint.cpp stack.h \
+	collision_std.h joint.h step.cpp collision_transform.cpp \
+	lcp.cpp step.h collision_transform.h lcp.h stepfast.cpp \
+	mass.cpp testing.cpp mat.cpp testing.h mat.h timer.cpp \
+	matrix.cpp util.cpp memory.cpp util.h misc.cpp heightfield.cpp \
+	heightfield.h collision_trimesh_gimpact.cpp \
+	collision_trimesh_trimesh.cpp collision_trimesh_sphere.cpp \
+	collision_trimesh_ray.cpp collision_trimesh_opcode.cpp \
+	collision_trimesh_box.cpp collision_trimesh_ccylinder.cpp \
+	collision_trimesh_distance.cpp collision_trimesh_internal.h \
+	collision_cylinder_trimesh.cpp collision_trimesh_plane.cpp
+@GIMPACT_TRUE@am__objects_1 =  \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_gimpact.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_trimesh.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_sphere.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_ray.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_opcode.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_box.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_ccylinder.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_distance.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_cylinder_trimesh.$(OBJEXT) \
+@GIMPACT_TRUE@	libode_a-collision_trimesh_plane.$(OBJEXT)
+@OPCODE_TRUE@am__objects_2 =  \
+@OPCODE_TRUE@	libode_a-collision_trimesh_trimesh.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_sphere.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_ray.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_opcode.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_box.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_ccylinder.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_distance.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_cylinder_trimesh.$(OBJEXT) \
+@OPCODE_TRUE@	libode_a-collision_trimesh_plane.$(OBJEXT)
+am_libode_a_OBJECTS = libode_a-obstack.$(OBJEXT) \
+	libode_a-collision_util.$(OBJEXT) libode_a-array.$(OBJEXT) \
+	libode_a-ode.$(OBJEXT) libode_a-error.$(OBJEXT) \
+	libode_a-odemath.$(OBJEXT) libode_a-collision_kernel.$(OBJEXT) \
+	libode_a-export-dif.$(OBJEXT) libode_a-quickstep.$(OBJEXT) \
+	libode_a-collision_quadtreespace.$(OBJEXT) \
+	libode_a-rotation.$(OBJEXT) libode_a-collision_space.$(OBJEXT) \
+	libode_a-collision_cylinder_box.$(OBJEXT) \
+	libode_a-collision_cylinder_sphere.$(OBJEXT) \
+	libode_a-collision_cylinder_plane.$(OBJEXT) \
+	libode_a-sphere.$(OBJEXT) libode_a-box.$(OBJEXT) \
+	libode_a-capsule.$(OBJEXT) libode_a-plane.$(OBJEXT) \
+	libode_a-ray.$(OBJEXT) libode_a-cylinder.$(OBJEXT) \
+	libode_a-convex.$(OBJEXT) libode_a-joint.$(OBJEXT) \
+	libode_a-step.$(OBJEXT) libode_a-collision_transform.$(OBJEXT) \
+	libode_a-lcp.$(OBJEXT) libode_a-stepfast.$(OBJEXT) \
+	libode_a-mass.$(OBJEXT) libode_a-testing.$(OBJEXT) \
+	libode_a-mat.$(OBJEXT) libode_a-timer.$(OBJEXT) \
+	libode_a-matrix.$(OBJEXT) libode_a-util.$(OBJEXT) \
+	libode_a-memory.$(OBJEXT) libode_a-misc.$(OBJEXT) \
+	libode_a-heightfield.$(OBJEXT) $(am__objects_1) \
+	$(am__objects_2)
+libode_a_OBJECTS = $(am_libode_a_OBJECTS)
+traplibPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(traplib_PROGRAMS)
+am_libode_OBJECTS =
+libode_OBJECTS = $(am_libode_OBJECTS)
+libode_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libode_LDFLAGS) \
+	$(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+SOURCES = $(libGIMPACT_a_SOURCES) $(libOPCODE_a_SOURCES) \
+	$(libfast_a_SOURCES) $(libode_a_SOURCES) $(libode_SOURCES)
+DIST_SOURCES = $(am__libGIMPACT_a_SOURCES_DIST) \
+	$(am__libOPCODE_a_SOURCES_DIST) $(libfast_a_SOURCES) \
+	$(am__libode_a_SOURCES_DIST) $(libode_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @so_ext@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include \
+	-I$(top_builddir)/include $(am__append_10) $(am__append_15)
+AM_CPPFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+AM_CFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include \
+	-I$(top_builddir)/include $(am__append_11) $(am__append_16)
+lib_LIBRARIES = libode.a
+libode_a_CPPFLAGS = -O2 -fPIC
+
+# Fake an executable in order to get a shared library
+# Note the elegant and cunning way to trick Autotools to install a program
+# in a lib directory. --Rodrigo
+traplibdir = $(libdir)
+libode_SOURCES = 
+libode_DEPENDENCIES = libfast.a libode.a $(am__append_2) \
+	$(am__append_4)
+libode_LDFLAGS = @SHARED_LDFLAGS@ $(am__append_1)
+libode_LDADD = $(libode_a_OBJECTS) $(libfast_a_OBJECTS) \
+	$(am__append_3) $(am__append_5)
+
+# convenience library to simulate per object cflags
+noinst_LIBRARIES = libfast.a $(am__append_6) $(am__append_12)
+libfast_a_CFLAGS = -O1 -fPIC
+libfast_a_SOURCES = fastldlt.c fastltsolve.c fastdot.c fastlsolve.c
+libode_a_DEPENDENCIES = libfast.a $(am__append_8) $(am__append_13)
+libode_a_LIBADD = $(libfast_a_OBJECTS) $(am__append_9) \
+	$(am__append_14)
+libode_a_SOURCES = objects.h obstack.cpp collision_util.cpp obstack.h \
+	array.cpp collision_util.h ode.cpp array.h error.cpp \
+	odemath.cpp collision_kernel.cpp export-dif.cpp quickstep.cpp \
+	collision_kernel.h quickstep.h collision_quadtreespace.cpp \
+	rotation.cpp collision_space.cpp collision_space_internal.h \
+	collision_cylinder_box.cpp collision_cylinder_sphere.cpp \
+	collision_cylinder_plane.cpp sphere.cpp box.cpp capsule.cpp \
+	plane.cpp ray.cpp cylinder.cpp convex.cpp joint.cpp stack.h \
+	collision_std.h joint.h step.cpp collision_transform.cpp \
+	lcp.cpp step.h collision_transform.h lcp.h stepfast.cpp \
+	mass.cpp testing.cpp mat.cpp testing.h mat.h timer.cpp \
+	matrix.cpp util.cpp memory.cpp util.h misc.cpp heightfield.cpp \
+	heightfield.h $(am__append_7) $(am__append_17)
+@GIMPACT_TRUE@libGIMPACT_a_CPPFLAGS = -O2 -fno-strict-aliasing -fPIC
+@GIMPACT_TRUE@libGIMPACT_a_SOURCES = \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_contact.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_math.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_memory.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_trimesh.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp \
+@GIMPACT_TRUE@  @TOPDIR@/GIMPACT/src/gimpact.cpp
+
+@OPCODE_TRUE@libOPCODE_a_CPPFLAGS = -O2 -fno-strict-aliasing -fPIC
+@OPCODE_TRUE@libOPCODE_a_SOURCES = @TOPDIR@/OPCODE/OPC_AABBCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_AABBTree.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_BaseModel.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_BoxPruning.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_Collider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_Common.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_HybridModel.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_LSSCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_MeshInterface.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_Model.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_OBBCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Opcode.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_Picking.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_RayCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_SphereCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_TreeCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceAABB.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceContainer.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceHPoint.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceOBB.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IcePlane.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IcePoint.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceRandom.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceRay.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceSegment.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceTriangle.cpp \
+@OPCODE_TRUE@			@TOPDIR@/OPCODE/Ice/IceUtils.cpp
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  ode/src/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  ode/src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLIBRARIES: $(lib_LIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+	@$(POST_INSTALL)
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    p=$(am__strip_dir) \
+	    echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \
+	    $(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \
+	  else :; fi; \
+	done
+
+uninstall-libLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLIBRARIES:
+	-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libGIMPACT.a: $(libGIMPACT_a_OBJECTS) $(libGIMPACT_a_DEPENDENCIES) 
+	-rm -f libGIMPACT.a
+	$(libGIMPACT_a_AR) libGIMPACT.a $(libGIMPACT_a_OBJECTS) $(libGIMPACT_a_LIBADD)
+	$(RANLIB) libGIMPACT.a
+libOPCODE.a: $(libOPCODE_a_OBJECTS) $(libOPCODE_a_DEPENDENCIES) 
+	-rm -f libOPCODE.a
+	$(libOPCODE_a_AR) libOPCODE.a $(libOPCODE_a_OBJECTS) $(libOPCODE_a_LIBADD)
+	$(RANLIB) libOPCODE.a
+libfast.a: $(libfast_a_OBJECTS) $(libfast_a_DEPENDENCIES) 
+	-rm -f libfast.a
+	$(libfast_a_AR) libfast.a $(libfast_a_OBJECTS) $(libfast_a_LIBADD)
+	$(RANLIB) libfast.a
+libode.a: $(libode_a_OBJECTS) $(libode_a_DEPENDENCIES) 
+	-rm -f libode.a
+	$(libode_a_AR) libode.a $(libode_a_OBJECTS) $(libode_a_LIBADD)
+	$(RANLIB) libode.a
+install-traplibPROGRAMS: $(traplib_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	test -z "$(traplibdir)" || $(MKDIR_P) "$(DESTDIR)$(traplibdir)"
+	@list='$(traplib_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(traplibPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(traplibdir)/$$f'"; \
+	   $(INSTALL_PROGRAM_ENV) $(traplibPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(traplibdir)/$$f" || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-traplibPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(traplib_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f '$(DESTDIR)$(traplibdir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(traplibdir)/$$f"; \
+	done
+
+clean-traplibPROGRAMS:
+	-test -z "$(traplib_PROGRAMS)" || rm -f $(traplib_PROGRAMS)
+libode$(EXEEXT): $(libode_OBJECTS) $(libode_DEPENDENCIES) 
+	@rm -f libode$(EXEEXT)
+	$(libode_LINK) $(libode_OBJECTS) $(libode_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_boxpruning.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_contact.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_math.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_memory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libGIMPACT_a-gimpact.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceAABB.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceContainer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceHPoint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceMatrix3x3.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceMatrix4x4.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceOBB.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IcePlane.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IcePoint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceRandom.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceRay.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceSegment.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceTriangle.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-IceUtils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_AABBTree.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_BaseModel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Collider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_HybridModel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Model.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_Picking.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_RayCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libOPCODE_a-Opcode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastdot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastldlt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastlsolve.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfast_a-fastltsolve.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-array.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-box.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-capsule.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_box.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_plane.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_sphere.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_cylinder_trimesh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_kernel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_quadtreespace.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_space.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_transform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_box.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_ccylinder.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_distance.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_gimpact.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_opcode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_plane.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_ray.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_sphere.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_trimesh_trimesh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-collision_util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-convex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-cylinder.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-export-dif.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-heightfield.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-joint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-lcp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-mass.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-mat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-matrix.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-memory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-obstack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-ode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-odemath.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-plane.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-quickstep.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-ray.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-rotation.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-sphere.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-step.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-stepfast.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-testing.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-timer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libode_a-util.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+libfast_a-fastldlt.o: fastldlt.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastldlt.o -MD -MP -MF $(DEPDIR)/libfast_a-fastldlt.Tpo -c -o libfast_a-fastldlt.o `test -f 'fastldlt.c' || echo '$(srcdir)/'`fastldlt.c
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastldlt.Tpo $(DEPDIR)/libfast_a-fastldlt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastldlt.c' object='libfast_a-fastldlt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastldlt.o `test -f 'fastldlt.c' || echo '$(srcdir)/'`fastldlt.c
+
+libfast_a-fastldlt.obj: fastldlt.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastldlt.obj -MD -MP -MF $(DEPDIR)/libfast_a-fastldlt.Tpo -c -o libfast_a-fastldlt.obj `if test -f 'fastldlt.c'; then $(CYGPATH_W) 'fastldlt.c'; else $(CYGPATH_W) '$(srcdir)/fastldlt.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastldlt.Tpo $(DEPDIR)/libfast_a-fastldlt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastldlt.c' object='libfast_a-fastldlt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastldlt.obj `if test -f 'fastldlt.c'; then $(CYGPATH_W) 'fastldlt.c'; else $(CYGPATH_W) '$(srcdir)/fastldlt.c'; fi`
+
+libfast_a-fastltsolve.o: fastltsolve.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastltsolve.o -MD -MP -MF $(DEPDIR)/libfast_a-fastltsolve.Tpo -c -o libfast_a-fastltsolve.o `test -f 'fastltsolve.c' || echo '$(srcdir)/'`fastltsolve.c
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastltsolve.Tpo $(DEPDIR)/libfast_a-fastltsolve.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastltsolve.c' object='libfast_a-fastltsolve.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastltsolve.o `test -f 'fastltsolve.c' || echo '$(srcdir)/'`fastltsolve.c
+
+libfast_a-fastltsolve.obj: fastltsolve.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastltsolve.obj -MD -MP -MF $(DEPDIR)/libfast_a-fastltsolve.Tpo -c -o libfast_a-fastltsolve.obj `if test -f 'fastltsolve.c'; then $(CYGPATH_W) 'fastltsolve.c'; else $(CYGPATH_W) '$(srcdir)/fastltsolve.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastltsolve.Tpo $(DEPDIR)/libfast_a-fastltsolve.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastltsolve.c' object='libfast_a-fastltsolve.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastltsolve.obj `if test -f 'fastltsolve.c'; then $(CYGPATH_W) 'fastltsolve.c'; else $(CYGPATH_W) '$(srcdir)/fastltsolve.c'; fi`
+
+libfast_a-fastdot.o: fastdot.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastdot.o -MD -MP -MF $(DEPDIR)/libfast_a-fastdot.Tpo -c -o libfast_a-fastdot.o `test -f 'fastdot.c' || echo '$(srcdir)/'`fastdot.c
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastdot.Tpo $(DEPDIR)/libfast_a-fastdot.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastdot.c' object='libfast_a-fastdot.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastdot.o `test -f 'fastdot.c' || echo '$(srcdir)/'`fastdot.c
+
+libfast_a-fastdot.obj: fastdot.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastdot.obj -MD -MP -MF $(DEPDIR)/libfast_a-fastdot.Tpo -c -o libfast_a-fastdot.obj `if test -f 'fastdot.c'; then $(CYGPATH_W) 'fastdot.c'; else $(CYGPATH_W) '$(srcdir)/fastdot.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastdot.Tpo $(DEPDIR)/libfast_a-fastdot.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastdot.c' object='libfast_a-fastdot.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastdot.obj `if test -f 'fastdot.c'; then $(CYGPATH_W) 'fastdot.c'; else $(CYGPATH_W) '$(srcdir)/fastdot.c'; fi`
+
+libfast_a-fastlsolve.o: fastlsolve.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastlsolve.o -MD -MP -MF $(DEPDIR)/libfast_a-fastlsolve.Tpo -c -o libfast_a-fastlsolve.o `test -f 'fastlsolve.c' || echo '$(srcdir)/'`fastlsolve.c
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastlsolve.Tpo $(DEPDIR)/libfast_a-fastlsolve.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastlsolve.c' object='libfast_a-fastlsolve.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastlsolve.o `test -f 'fastlsolve.c' || echo '$(srcdir)/'`fastlsolve.c
+
+libfast_a-fastlsolve.obj: fastlsolve.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -MT libfast_a-fastlsolve.obj -MD -MP -MF $(DEPDIR)/libfast_a-fastlsolve.Tpo -c -o libfast_a-fastlsolve.obj `if test -f 'fastlsolve.c'; then $(CYGPATH_W) 'fastlsolve.c'; else $(CYGPATH_W) '$(srcdir)/fastlsolve.c'; fi`
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libfast_a-fastlsolve.Tpo $(DEPDIR)/libfast_a-fastlsolve.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='fastlsolve.c' object='libfast_a-fastlsolve.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libfast_a_CFLAGS) $(CFLAGS) -c -o libfast_a-fastlsolve.obj `if test -f 'fastlsolve.c'; then $(CYGPATH_W) 'fastlsolve.c'; else $(CYGPATH_W) '$(srcdir)/fastlsolve.c'; fi`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libGIMPACT_a-gim_boxpruning.o: @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_boxpruning.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Tpo -c -o libGIMPACT_a-gim_boxpruning.o `test -f '@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Tpo $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp' object='libGIMPACT_a-gim_boxpruning.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_boxpruning.o `test -f '@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp
+
+libGIMPACT_a-gim_boxpruning.obj: @TOPDIR@/GIMPACT/src/gim_boxpruning.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_boxpruning.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Tpo -c -o libGIMPACT_a-gim_boxpruning.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Tpo $(DEPDIR)/libGIMPACT_a-gim_boxpruning.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp' object='libGIMPACT_a-gim_boxpruning.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_boxpruning.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_boxpruning.cpp'; fi`
+
+libGIMPACT_a-gim_contact.o: @TOPDIR@/GIMPACT/src/gim_contact.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_contact.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_contact.Tpo -c -o libGIMPACT_a-gim_contact.o `test -f '@TOPDIR@/GIMPACT/src/gim_contact.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_contact.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_contact.Tpo $(DEPDIR)/libGIMPACT_a-gim_contact.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_contact.cpp' object='libGIMPACT_a-gim_contact.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_contact.o `test -f '@TOPDIR@/GIMPACT/src/gim_contact.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_contact.cpp
+
+libGIMPACT_a-gim_contact.obj: @TOPDIR@/GIMPACT/src/gim_contact.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_contact.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_contact.Tpo -c -o libGIMPACT_a-gim_contact.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_contact.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_contact.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_contact.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_contact.Tpo $(DEPDIR)/libGIMPACT_a-gim_contact.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_contact.cpp' object='libGIMPACT_a-gim_contact.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_contact.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_contact.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_contact.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_contact.cpp'; fi`
+
+libGIMPACT_a-gim_math.o: @TOPDIR@/GIMPACT/src/gim_math.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_math.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_math.Tpo -c -o libGIMPACT_a-gim_math.o `test -f '@TOPDIR@/GIMPACT/src/gim_math.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_math.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_math.Tpo $(DEPDIR)/libGIMPACT_a-gim_math.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_math.cpp' object='libGIMPACT_a-gim_math.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_math.o `test -f '@TOPDIR@/GIMPACT/src/gim_math.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_math.cpp
+
+libGIMPACT_a-gim_math.obj: @TOPDIR@/GIMPACT/src/gim_math.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_math.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_math.Tpo -c -o libGIMPACT_a-gim_math.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_math.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_math.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_math.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_math.Tpo $(DEPDIR)/libGIMPACT_a-gim_math.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_math.cpp' object='libGIMPACT_a-gim_math.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_math.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_math.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_math.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_math.cpp'; fi`
+
+libGIMPACT_a-gim_memory.o: @TOPDIR@/GIMPACT/src/gim_memory.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_memory.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_memory.Tpo -c -o libGIMPACT_a-gim_memory.o `test -f '@TOPDIR@/GIMPACT/src/gim_memory.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_memory.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_memory.Tpo $(DEPDIR)/libGIMPACT_a-gim_memory.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_memory.cpp' object='libGIMPACT_a-gim_memory.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_memory.o `test -f '@TOPDIR@/GIMPACT/src/gim_memory.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_memory.cpp
+
+libGIMPACT_a-gim_memory.obj: @TOPDIR@/GIMPACT/src/gim_memory.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_memory.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_memory.Tpo -c -o libGIMPACT_a-gim_memory.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_memory.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_memory.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_memory.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_memory.Tpo $(DEPDIR)/libGIMPACT_a-gim_memory.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_memory.cpp' object='libGIMPACT_a-gim_memory.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_memory.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_memory.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_memory.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_memory.cpp'; fi`
+
+libGIMPACT_a-gim_tri_tri_overlap.o: @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_tri_tri_overlap.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Tpo -c -o libGIMPACT_a-gim_tri_tri_overlap.o `test -f '@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Tpo $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp' object='libGIMPACT_a-gim_tri_tri_overlap.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_tri_tri_overlap.o `test -f '@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp
+
+libGIMPACT_a-gim_tri_tri_overlap.obj: @TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_tri_tri_overlap.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Tpo -c -o libGIMPACT_a-gim_tri_tri_overlap.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Tpo $(DEPDIR)/libGIMPACT_a-gim_tri_tri_overlap.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp' object='libGIMPACT_a-gim_tri_tri_overlap.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_tri_tri_overlap.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_tri_tri_overlap.cpp'; fi`
+
+libGIMPACT_a-gim_trimesh.o: @TOPDIR@/GIMPACT/src/gim_trimesh.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh.Tpo -c -o libGIMPACT_a-gim_trimesh.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh.cpp' object='libGIMPACT_a-gim_trimesh.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh.cpp
+
+libGIMPACT_a-gim_trimesh.obj: @TOPDIR@/GIMPACT/src/gim_trimesh.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh.Tpo -c -o libGIMPACT_a-gim_trimesh.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh.cpp' object='libGIMPACT_a-gim_trimesh.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh.cpp'; fi`
+
+libGIMPACT_a-gim_trimesh_capsule_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_capsule_collision.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_capsule_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp' object='libGIMPACT_a-gim_trimesh_capsule_collision.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_capsule_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp
+
+libGIMPACT_a-gim_trimesh_capsule_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_capsule_collision.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_capsule_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_capsule_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp' object='libGIMPACT_a-gim_trimesh_capsule_collision.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_capsule_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_capsule_collision.cpp'; fi`
+
+libGIMPACT_a-gim_trimesh_ray_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_ray_collision.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_ray_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp' object='libGIMPACT_a-gim_trimesh_ray_collision.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_ray_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp
+
+libGIMPACT_a-gim_trimesh_ray_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_ray_collision.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_ray_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_ray_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp' object='libGIMPACT_a-gim_trimesh_ray_collision.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_ray_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_ray_collision.cpp'; fi`
+
+libGIMPACT_a-gim_trimesh_sphere_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_sphere_collision.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_sphere_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp' object='libGIMPACT_a-gim_trimesh_sphere_collision.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_sphere_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp
+
+libGIMPACT_a-gim_trimesh_sphere_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_sphere_collision.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_sphere_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_sphere_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp' object='libGIMPACT_a-gim_trimesh_sphere_collision.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_sphere_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_sphere_collision.cpp'; fi`
+
+libGIMPACT_a-gim_trimesh_trimesh_collision.o: @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_trimesh_collision.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_trimesh_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp' object='libGIMPACT_a-gim_trimesh_trimesh_collision.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_trimesh_collision.o `test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
+
+libGIMPACT_a-gim_trimesh_trimesh_collision.obj: @TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gim_trimesh_trimesh_collision.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Tpo -c -o libGIMPACT_a-gim_trimesh_trimesh_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Tpo $(DEPDIR)/libGIMPACT_a-gim_trimesh_trimesh_collision.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp' object='libGIMPACT_a-gim_trimesh_trimesh_collision.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gim_trimesh_trimesh_collision.obj `if test -f '@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gim_trimesh_trimesh_collision.cpp'; fi`
+
+libGIMPACT_a-gimpact.o: @TOPDIR@/GIMPACT/src/gimpact.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gimpact.o -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gimpact.Tpo -c -o libGIMPACT_a-gimpact.o `test -f '@TOPDIR@/GIMPACT/src/gimpact.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gimpact.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gimpact.Tpo $(DEPDIR)/libGIMPACT_a-gimpact.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gimpact.cpp' object='libGIMPACT_a-gimpact.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gimpact.o `test -f '@TOPDIR@/GIMPACT/src/gimpact.cpp' || echo '$(srcdir)/'`@TOPDIR@/GIMPACT/src/gimpact.cpp
+
+libGIMPACT_a-gimpact.obj: @TOPDIR@/GIMPACT/src/gimpact.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libGIMPACT_a-gimpact.obj -MD -MP -MF $(DEPDIR)/libGIMPACT_a-gimpact.Tpo -c -o libGIMPACT_a-gimpact.obj `if test -f '@TOPDIR@/GIMPACT/src/gimpact.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gimpact.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gimpact.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libGIMPACT_a-gimpact.Tpo $(DEPDIR)/libGIMPACT_a-gimpact.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/GIMPACT/src/gimpact.cpp' object='libGIMPACT_a-gimpact.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libGIMPACT_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libGIMPACT_a-gimpact.obj `if test -f '@TOPDIR@/GIMPACT/src/gimpact.cpp'; then $(CYGPATH_W) '@TOPDIR@/GIMPACT/src/gimpact.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/GIMPACT/src/gimpact.cpp'; fi`
+
+libOPCODE_a-OPC_AABBCollider.o: @TOPDIR@/OPCODE/OPC_AABBCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_AABBCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Tpo -c -o libOPCODE_a-OPC_AABBCollider.o `test -f '@TOPDIR@/OPCODE/OPC_AABBCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_AABBCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_AABBCollider.cpp' object='libOPCODE_a-OPC_AABBCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_AABBCollider.o `test -f '@TOPDIR@/OPCODE/OPC_AABBCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_AABBCollider.cpp
+
+libOPCODE_a-OPC_AABBCollider.obj: @TOPDIR@/OPCODE/OPC_AABBCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_AABBCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Tpo -c -o libOPCODE_a-OPC_AABBCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_AABBCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_AABBCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_AABBCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_AABBCollider.cpp' object='libOPCODE_a-OPC_AABBCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_AABBCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_AABBCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_AABBCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_AABBCollider.cpp'; fi`
+
+libOPCODE_a-OPC_AABBTree.o: @TOPDIR@/OPCODE/OPC_AABBTree.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_AABBTree.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Tpo -c -o libOPCODE_a-OPC_AABBTree.o `test -f '@TOPDIR@/OPCODE/OPC_AABBTree.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_AABBTree.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_AABBTree.cpp' object='libOPCODE_a-OPC_AABBTree.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_AABBTree.o `test -f '@TOPDIR@/OPCODE/OPC_AABBTree.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_AABBTree.cpp
+
+libOPCODE_a-OPC_AABBTree.obj: @TOPDIR@/OPCODE/OPC_AABBTree.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_AABBTree.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Tpo -c -o libOPCODE_a-OPC_AABBTree.obj `if test -f '@TOPDIR@/OPCODE/OPC_AABBTree.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_AABBTree.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_AABBTree.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_AABBTree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_AABBTree.cpp' object='libOPCODE_a-OPC_AABBTree.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_AABBTree.obj `if test -f '@TOPDIR@/OPCODE/OPC_AABBTree.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_AABBTree.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_AABBTree.cpp'; fi`
+
+libOPCODE_a-OPC_BaseModel.o: @TOPDIR@/OPCODE/OPC_BaseModel.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_BaseModel.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Tpo -c -o libOPCODE_a-OPC_BaseModel.o `test -f '@TOPDIR@/OPCODE/OPC_BaseModel.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_BaseModel.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_BaseModel.cpp' object='libOPCODE_a-OPC_BaseModel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_BaseModel.o `test -f '@TOPDIR@/OPCODE/OPC_BaseModel.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_BaseModel.cpp
+
+libOPCODE_a-OPC_BaseModel.obj: @TOPDIR@/OPCODE/OPC_BaseModel.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_BaseModel.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Tpo -c -o libOPCODE_a-OPC_BaseModel.obj `if test -f '@TOPDIR@/OPCODE/OPC_BaseModel.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_BaseModel.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_BaseModel.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_BaseModel.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_BaseModel.cpp' object='libOPCODE_a-OPC_BaseModel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_BaseModel.obj `if test -f '@TOPDIR@/OPCODE/OPC_BaseModel.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_BaseModel.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_BaseModel.cpp'; fi`
+
+libOPCODE_a-OPC_BoxPruning.o: @TOPDIR@/OPCODE/OPC_BoxPruning.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_BoxPruning.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Tpo -c -o libOPCODE_a-OPC_BoxPruning.o `test -f '@TOPDIR@/OPCODE/OPC_BoxPruning.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_BoxPruning.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Tpo $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_BoxPruning.cpp' object='libOPCODE_a-OPC_BoxPruning.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_BoxPruning.o `test -f '@TOPDIR@/OPCODE/OPC_BoxPruning.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_BoxPruning.cpp
+
+libOPCODE_a-OPC_BoxPruning.obj: @TOPDIR@/OPCODE/OPC_BoxPruning.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_BoxPruning.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Tpo -c -o libOPCODE_a-OPC_BoxPruning.obj `if test -f '@TOPDIR@/OPCODE/OPC_BoxPruning.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_BoxPruning.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_BoxPruning.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Tpo $(DEPDIR)/libOPCODE_a-OPC_BoxPruning.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_BoxPruning.cpp' object='libOPCODE_a-OPC_BoxPruning.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_BoxPruning.obj `if test -f '@TOPDIR@/OPCODE/OPC_BoxPruning.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_BoxPruning.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_BoxPruning.cpp'; fi`
+
+libOPCODE_a-OPC_Collider.o: @TOPDIR@/OPCODE/OPC_Collider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Collider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Collider.Tpo -c -o libOPCODE_a-OPC_Collider.o `test -f '@TOPDIR@/OPCODE/OPC_Collider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Collider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Collider.Tpo $(DEPDIR)/libOPCODE_a-OPC_Collider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Collider.cpp' object='libOPCODE_a-OPC_Collider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Collider.o `test -f '@TOPDIR@/OPCODE/OPC_Collider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Collider.cpp
+
+libOPCODE_a-OPC_Collider.obj: @TOPDIR@/OPCODE/OPC_Collider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Collider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Collider.Tpo -c -o libOPCODE_a-OPC_Collider.obj `if test -f '@TOPDIR@/OPCODE/OPC_Collider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Collider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Collider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Collider.Tpo $(DEPDIR)/libOPCODE_a-OPC_Collider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Collider.cpp' object='libOPCODE_a-OPC_Collider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Collider.obj `if test -f '@TOPDIR@/OPCODE/OPC_Collider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Collider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Collider.cpp'; fi`
+
+libOPCODE_a-OPC_Common.o: @TOPDIR@/OPCODE/OPC_Common.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Common.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Common.Tpo -c -o libOPCODE_a-OPC_Common.o `test -f '@TOPDIR@/OPCODE/OPC_Common.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Common.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Common.Tpo $(DEPDIR)/libOPCODE_a-OPC_Common.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Common.cpp' object='libOPCODE_a-OPC_Common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Common.o `test -f '@TOPDIR@/OPCODE/OPC_Common.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Common.cpp
+
+libOPCODE_a-OPC_Common.obj: @TOPDIR@/OPCODE/OPC_Common.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Common.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Common.Tpo -c -o libOPCODE_a-OPC_Common.obj `if test -f '@TOPDIR@/OPCODE/OPC_Common.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Common.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Common.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Common.Tpo $(DEPDIR)/libOPCODE_a-OPC_Common.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Common.cpp' object='libOPCODE_a-OPC_Common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Common.obj `if test -f '@TOPDIR@/OPCODE/OPC_Common.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Common.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Common.cpp'; fi`
+
+libOPCODE_a-OPC_HybridModel.o: @TOPDIR@/OPCODE/OPC_HybridModel.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_HybridModel.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Tpo -c -o libOPCODE_a-OPC_HybridModel.o `test -f '@TOPDIR@/OPCODE/OPC_HybridModel.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_HybridModel.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_HybridModel.cpp' object='libOPCODE_a-OPC_HybridModel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_HybridModel.o `test -f '@TOPDIR@/OPCODE/OPC_HybridModel.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_HybridModel.cpp
+
+libOPCODE_a-OPC_HybridModel.obj: @TOPDIR@/OPCODE/OPC_HybridModel.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_HybridModel.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Tpo -c -o libOPCODE_a-OPC_HybridModel.obj `if test -f '@TOPDIR@/OPCODE/OPC_HybridModel.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_HybridModel.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_HybridModel.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Tpo $(DEPDIR)/libOPCODE_a-OPC_HybridModel.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_HybridModel.cpp' object='libOPCODE_a-OPC_HybridModel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_HybridModel.obj `if test -f '@TOPDIR@/OPCODE/OPC_HybridModel.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_HybridModel.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_HybridModel.cpp'; fi`
+
+libOPCODE_a-OPC_LSSCollider.o: @TOPDIR@/OPCODE/OPC_LSSCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_LSSCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Tpo -c -o libOPCODE_a-OPC_LSSCollider.o `test -f '@TOPDIR@/OPCODE/OPC_LSSCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_LSSCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_LSSCollider.cpp' object='libOPCODE_a-OPC_LSSCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_LSSCollider.o `test -f '@TOPDIR@/OPCODE/OPC_LSSCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_LSSCollider.cpp
+
+libOPCODE_a-OPC_LSSCollider.obj: @TOPDIR@/OPCODE/OPC_LSSCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_LSSCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Tpo -c -o libOPCODE_a-OPC_LSSCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_LSSCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_LSSCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_LSSCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_LSSCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_LSSCollider.cpp' object='libOPCODE_a-OPC_LSSCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_LSSCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_LSSCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_LSSCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_LSSCollider.cpp'; fi`
+
+libOPCODE_a-OPC_MeshInterface.o: @TOPDIR@/OPCODE/OPC_MeshInterface.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_MeshInterface.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Tpo -c -o libOPCODE_a-OPC_MeshInterface.o `test -f '@TOPDIR@/OPCODE/OPC_MeshInterface.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_MeshInterface.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Tpo $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_MeshInterface.cpp' object='libOPCODE_a-OPC_MeshInterface.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_MeshInterface.o `test -f '@TOPDIR@/OPCODE/OPC_MeshInterface.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_MeshInterface.cpp
+
+libOPCODE_a-OPC_MeshInterface.obj: @TOPDIR@/OPCODE/OPC_MeshInterface.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_MeshInterface.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Tpo -c -o libOPCODE_a-OPC_MeshInterface.obj `if test -f '@TOPDIR@/OPCODE/OPC_MeshInterface.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_MeshInterface.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_MeshInterface.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Tpo $(DEPDIR)/libOPCODE_a-OPC_MeshInterface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_MeshInterface.cpp' object='libOPCODE_a-OPC_MeshInterface.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_MeshInterface.obj `if test -f '@TOPDIR@/OPCODE/OPC_MeshInterface.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_MeshInterface.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_MeshInterface.cpp'; fi`
+
+libOPCODE_a-OPC_Model.o: @TOPDIR@/OPCODE/OPC_Model.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Model.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Model.Tpo -c -o libOPCODE_a-OPC_Model.o `test -f '@TOPDIR@/OPCODE/OPC_Model.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Model.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Model.Tpo $(DEPDIR)/libOPCODE_a-OPC_Model.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Model.cpp' object='libOPCODE_a-OPC_Model.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Model.o `test -f '@TOPDIR@/OPCODE/OPC_Model.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Model.cpp
+
+libOPCODE_a-OPC_Model.obj: @TOPDIR@/OPCODE/OPC_Model.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Model.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Model.Tpo -c -o libOPCODE_a-OPC_Model.obj `if test -f '@TOPDIR@/OPCODE/OPC_Model.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Model.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Model.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Model.Tpo $(DEPDIR)/libOPCODE_a-OPC_Model.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Model.cpp' object='libOPCODE_a-OPC_Model.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Model.obj `if test -f '@TOPDIR@/OPCODE/OPC_Model.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Model.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Model.cpp'; fi`
+
+libOPCODE_a-OPC_OBBCollider.o: @TOPDIR@/OPCODE/OPC_OBBCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_OBBCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Tpo -c -o libOPCODE_a-OPC_OBBCollider.o `test -f '@TOPDIR@/OPCODE/OPC_OBBCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_OBBCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_OBBCollider.cpp' object='libOPCODE_a-OPC_OBBCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_OBBCollider.o `test -f '@TOPDIR@/OPCODE/OPC_OBBCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_OBBCollider.cpp
+
+libOPCODE_a-OPC_OBBCollider.obj: @TOPDIR@/OPCODE/OPC_OBBCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_OBBCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Tpo -c -o libOPCODE_a-OPC_OBBCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_OBBCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_OBBCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_OBBCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_OBBCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_OBBCollider.cpp' object='libOPCODE_a-OPC_OBBCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_OBBCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_OBBCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_OBBCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_OBBCollider.cpp'; fi`
+
+libOPCODE_a-Opcode.o: @TOPDIR@/OPCODE/Opcode.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-Opcode.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-Opcode.Tpo -c -o libOPCODE_a-Opcode.o `test -f '@TOPDIR@/OPCODE/Opcode.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Opcode.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-Opcode.Tpo $(DEPDIR)/libOPCODE_a-Opcode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Opcode.cpp' object='libOPCODE_a-Opcode.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-Opcode.o `test -f '@TOPDIR@/OPCODE/Opcode.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Opcode.cpp
+
+libOPCODE_a-Opcode.obj: @TOPDIR@/OPCODE/Opcode.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-Opcode.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-Opcode.Tpo -c -o libOPCODE_a-Opcode.obj `if test -f '@TOPDIR@/OPCODE/Opcode.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Opcode.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Opcode.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-Opcode.Tpo $(DEPDIR)/libOPCODE_a-Opcode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Opcode.cpp' object='libOPCODE_a-Opcode.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-Opcode.obj `if test -f '@TOPDIR@/OPCODE/Opcode.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Opcode.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Opcode.cpp'; fi`
+
+libOPCODE_a-OPC_OptimizedTree.o: @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_OptimizedTree.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Tpo -c -o libOPCODE_a-OPC_OptimizedTree.o `test -f '@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp' object='libOPCODE_a-OPC_OptimizedTree.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_OptimizedTree.o `test -f '@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp
+
+libOPCODE_a-OPC_OptimizedTree.obj: @TOPDIR@/OPCODE/OPC_OptimizedTree.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_OptimizedTree.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Tpo -c -o libOPCODE_a-OPC_OptimizedTree.obj `if test -f '@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Tpo $(DEPDIR)/libOPCODE_a-OPC_OptimizedTree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp' object='libOPCODE_a-OPC_OptimizedTree.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_OptimizedTree.obj `if test -f '@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_OptimizedTree.cpp'; fi`
+
+libOPCODE_a-OPC_Picking.o: @TOPDIR@/OPCODE/OPC_Picking.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Picking.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Picking.Tpo -c -o libOPCODE_a-OPC_Picking.o `test -f '@TOPDIR@/OPCODE/OPC_Picking.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Picking.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Picking.Tpo $(DEPDIR)/libOPCODE_a-OPC_Picking.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Picking.cpp' object='libOPCODE_a-OPC_Picking.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Picking.o `test -f '@TOPDIR@/OPCODE/OPC_Picking.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_Picking.cpp
+
+libOPCODE_a-OPC_Picking.obj: @TOPDIR@/OPCODE/OPC_Picking.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_Picking.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_Picking.Tpo -c -o libOPCODE_a-OPC_Picking.obj `if test -f '@TOPDIR@/OPCODE/OPC_Picking.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Picking.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Picking.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_Picking.Tpo $(DEPDIR)/libOPCODE_a-OPC_Picking.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_Picking.cpp' object='libOPCODE_a-OPC_Picking.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_Picking.obj `if test -f '@TOPDIR@/OPCODE/OPC_Picking.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_Picking.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_Picking.cpp'; fi`
+
+libOPCODE_a-OPC_PlanesCollider.o: @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_PlanesCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Tpo -c -o libOPCODE_a-OPC_PlanesCollider.o `test -f '@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp' object='libOPCODE_a-OPC_PlanesCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_PlanesCollider.o `test -f '@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp
+
+libOPCODE_a-OPC_PlanesCollider.obj: @TOPDIR@/OPCODE/OPC_PlanesCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_PlanesCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Tpo -c -o libOPCODE_a-OPC_PlanesCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_PlanesCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp' object='libOPCODE_a-OPC_PlanesCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_PlanesCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_PlanesCollider.cpp'; fi`
+
+libOPCODE_a-OPC_RayCollider.o: @TOPDIR@/OPCODE/OPC_RayCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_RayCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Tpo -c -o libOPCODE_a-OPC_RayCollider.o `test -f '@TOPDIR@/OPCODE/OPC_RayCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_RayCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_RayCollider.cpp' object='libOPCODE_a-OPC_RayCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_RayCollider.o `test -f '@TOPDIR@/OPCODE/OPC_RayCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_RayCollider.cpp
+
+libOPCODE_a-OPC_RayCollider.obj: @TOPDIR@/OPCODE/OPC_RayCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_RayCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Tpo -c -o libOPCODE_a-OPC_RayCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_RayCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_RayCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_RayCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_RayCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_RayCollider.cpp' object='libOPCODE_a-OPC_RayCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_RayCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_RayCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_RayCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_RayCollider.cpp'; fi`
+
+libOPCODE_a-OPC_SphereCollider.o: @TOPDIR@/OPCODE/OPC_SphereCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_SphereCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Tpo -c -o libOPCODE_a-OPC_SphereCollider.o `test -f '@TOPDIR@/OPCODE/OPC_SphereCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_SphereCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_SphereCollider.cpp' object='libOPCODE_a-OPC_SphereCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_SphereCollider.o `test -f '@TOPDIR@/OPCODE/OPC_SphereCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_SphereCollider.cpp
+
+libOPCODE_a-OPC_SphereCollider.obj: @TOPDIR@/OPCODE/OPC_SphereCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_SphereCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Tpo -c -o libOPCODE_a-OPC_SphereCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_SphereCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_SphereCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_SphereCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_SphereCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_SphereCollider.cpp' object='libOPCODE_a-OPC_SphereCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_SphereCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_SphereCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_SphereCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_SphereCollider.cpp'; fi`
+
+libOPCODE_a-OPC_SweepAndPrune.o: @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_SweepAndPrune.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Tpo -c -o libOPCODE_a-OPC_SweepAndPrune.o `test -f '@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Tpo $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp' object='libOPCODE_a-OPC_SweepAndPrune.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_SweepAndPrune.o `test -f '@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp
+
+libOPCODE_a-OPC_SweepAndPrune.obj: @TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_SweepAndPrune.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Tpo -c -o libOPCODE_a-OPC_SweepAndPrune.obj `if test -f '@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Tpo $(DEPDIR)/libOPCODE_a-OPC_SweepAndPrune.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp' object='libOPCODE_a-OPC_SweepAndPrune.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_SweepAndPrune.obj `if test -f '@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_SweepAndPrune.cpp'; fi`
+
+libOPCODE_a-OPC_TreeBuilders.o: @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_TreeBuilders.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Tpo -c -o libOPCODE_a-OPC_TreeBuilders.o `test -f '@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp' object='libOPCODE_a-OPC_TreeBuilders.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_TreeBuilders.o `test -f '@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp
+
+libOPCODE_a-OPC_TreeBuilders.obj: @TOPDIR@/OPCODE/OPC_TreeBuilders.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_TreeBuilders.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Tpo -c -o libOPCODE_a-OPC_TreeBuilders.obj `if test -f '@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeBuilders.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp' object='libOPCODE_a-OPC_TreeBuilders.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_TreeBuilders.obj `if test -f '@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_TreeBuilders.cpp'; fi`
+
+libOPCODE_a-OPC_TreeCollider.o: @TOPDIR@/OPCODE/OPC_TreeCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_TreeCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Tpo -c -o libOPCODE_a-OPC_TreeCollider.o `test -f '@TOPDIR@/OPCODE/OPC_TreeCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_TreeCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_TreeCollider.cpp' object='libOPCODE_a-OPC_TreeCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_TreeCollider.o `test -f '@TOPDIR@/OPCODE/OPC_TreeCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_TreeCollider.cpp
+
+libOPCODE_a-OPC_TreeCollider.obj: @TOPDIR@/OPCODE/OPC_TreeCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_TreeCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Tpo -c -o libOPCODE_a-OPC_TreeCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_TreeCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_TreeCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_TreeCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_TreeCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_TreeCollider.cpp' object='libOPCODE_a-OPC_TreeCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_TreeCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_TreeCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_TreeCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_TreeCollider.cpp'; fi`
+
+libOPCODE_a-OPC_VolumeCollider.o: @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_VolumeCollider.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Tpo -c -o libOPCODE_a-OPC_VolumeCollider.o `test -f '@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp' object='libOPCODE_a-OPC_VolumeCollider.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_VolumeCollider.o `test -f '@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp
+
+libOPCODE_a-OPC_VolumeCollider.obj: @TOPDIR@/OPCODE/OPC_VolumeCollider.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-OPC_VolumeCollider.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Tpo -c -o libOPCODE_a-OPC_VolumeCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Tpo $(DEPDIR)/libOPCODE_a-OPC_VolumeCollider.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp' object='libOPCODE_a-OPC_VolumeCollider.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-OPC_VolumeCollider.obj `if test -f '@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/OPC_VolumeCollider.cpp'; fi`
+
+libOPCODE_a-IceAABB.o: @TOPDIR@/OPCODE/Ice/IceAABB.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceAABB.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceAABB.Tpo -c -o libOPCODE_a-IceAABB.o `test -f '@TOPDIR@/OPCODE/Ice/IceAABB.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceAABB.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceAABB.Tpo $(DEPDIR)/libOPCODE_a-IceAABB.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceAABB.cpp' object='libOPCODE_a-IceAABB.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceAABB.o `test -f '@TOPDIR@/OPCODE/Ice/IceAABB.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceAABB.cpp
+
+libOPCODE_a-IceAABB.obj: @TOPDIR@/OPCODE/Ice/IceAABB.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceAABB.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceAABB.Tpo -c -o libOPCODE_a-IceAABB.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceAABB.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceAABB.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceAABB.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceAABB.Tpo $(DEPDIR)/libOPCODE_a-IceAABB.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceAABB.cpp' object='libOPCODE_a-IceAABB.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceAABB.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceAABB.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceAABB.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceAABB.cpp'; fi`
+
+libOPCODE_a-IceContainer.o: @TOPDIR@/OPCODE/Ice/IceContainer.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceContainer.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceContainer.Tpo -c -o libOPCODE_a-IceContainer.o `test -f '@TOPDIR@/OPCODE/Ice/IceContainer.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceContainer.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceContainer.Tpo $(DEPDIR)/libOPCODE_a-IceContainer.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceContainer.cpp' object='libOPCODE_a-IceContainer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceContainer.o `test -f '@TOPDIR@/OPCODE/Ice/IceContainer.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceContainer.cpp
+
+libOPCODE_a-IceContainer.obj: @TOPDIR@/OPCODE/Ice/IceContainer.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceContainer.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceContainer.Tpo -c -o libOPCODE_a-IceContainer.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceContainer.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceContainer.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceContainer.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceContainer.Tpo $(DEPDIR)/libOPCODE_a-IceContainer.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceContainer.cpp' object='libOPCODE_a-IceContainer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceContainer.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceContainer.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceContainer.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceContainer.cpp'; fi`
+
+libOPCODE_a-IceHPoint.o: @TOPDIR@/OPCODE/Ice/IceHPoint.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceHPoint.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceHPoint.Tpo -c -o libOPCODE_a-IceHPoint.o `test -f '@TOPDIR@/OPCODE/Ice/IceHPoint.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceHPoint.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceHPoint.Tpo $(DEPDIR)/libOPCODE_a-IceHPoint.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceHPoint.cpp' object='libOPCODE_a-IceHPoint.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceHPoint.o `test -f '@TOPDIR@/OPCODE/Ice/IceHPoint.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceHPoint.cpp
+
+libOPCODE_a-IceHPoint.obj: @TOPDIR@/OPCODE/Ice/IceHPoint.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceHPoint.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceHPoint.Tpo -c -o libOPCODE_a-IceHPoint.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceHPoint.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceHPoint.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceHPoint.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceHPoint.Tpo $(DEPDIR)/libOPCODE_a-IceHPoint.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceHPoint.cpp' object='libOPCODE_a-IceHPoint.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceHPoint.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceHPoint.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceHPoint.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceHPoint.cpp'; fi`
+
+libOPCODE_a-IceIndexedTriangle.o: @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceIndexedTriangle.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Tpo -c -o libOPCODE_a-IceIndexedTriangle.o `test -f '@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp' object='libOPCODE_a-IceIndexedTriangle.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceIndexedTriangle.o `test -f '@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp
+
+libOPCODE_a-IceIndexedTriangle.obj: @TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceIndexedTriangle.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Tpo -c -o libOPCODE_a-IceIndexedTriangle.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceIndexedTriangle.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp' object='libOPCODE_a-IceIndexedTriangle.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceIndexedTriangle.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceIndexedTriangle.cpp'; fi`
+
+libOPCODE_a-IceMatrix3x3.o: @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceMatrix3x3.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Tpo -c -o libOPCODE_a-IceMatrix3x3.o `test -f '@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp' object='libOPCODE_a-IceMatrix3x3.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceMatrix3x3.o `test -f '@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp
+
+libOPCODE_a-IceMatrix3x3.obj: @TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceMatrix3x3.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Tpo -c -o libOPCODE_a-IceMatrix3x3.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix3x3.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp' object='libOPCODE_a-IceMatrix3x3.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceMatrix3x3.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceMatrix3x3.cpp'; fi`
+
+libOPCODE_a-IceMatrix4x4.o: @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceMatrix4x4.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Tpo -c -o libOPCODE_a-IceMatrix4x4.o `test -f '@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp' object='libOPCODE_a-IceMatrix4x4.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceMatrix4x4.o `test -f '@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp
+
+libOPCODE_a-IceMatrix4x4.obj: @TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceMatrix4x4.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Tpo -c -o libOPCODE_a-IceMatrix4x4.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Tpo $(DEPDIR)/libOPCODE_a-IceMatrix4x4.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp' object='libOPCODE_a-IceMatrix4x4.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceMatrix4x4.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceMatrix4x4.cpp'; fi`
+
+libOPCODE_a-IceOBB.o: @TOPDIR@/OPCODE/Ice/IceOBB.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceOBB.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceOBB.Tpo -c -o libOPCODE_a-IceOBB.o `test -f '@TOPDIR@/OPCODE/Ice/IceOBB.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceOBB.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceOBB.Tpo $(DEPDIR)/libOPCODE_a-IceOBB.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceOBB.cpp' object='libOPCODE_a-IceOBB.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceOBB.o `test -f '@TOPDIR@/OPCODE/Ice/IceOBB.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceOBB.cpp
+
+libOPCODE_a-IceOBB.obj: @TOPDIR@/OPCODE/Ice/IceOBB.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceOBB.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceOBB.Tpo -c -o libOPCODE_a-IceOBB.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceOBB.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceOBB.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceOBB.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceOBB.Tpo $(DEPDIR)/libOPCODE_a-IceOBB.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceOBB.cpp' object='libOPCODE_a-IceOBB.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceOBB.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceOBB.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceOBB.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceOBB.cpp'; fi`
+
+libOPCODE_a-IcePlane.o: @TOPDIR@/OPCODE/Ice/IcePlane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IcePlane.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IcePlane.Tpo -c -o libOPCODE_a-IcePlane.o `test -f '@TOPDIR@/OPCODE/Ice/IcePlane.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IcePlane.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IcePlane.Tpo $(DEPDIR)/libOPCODE_a-IcePlane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IcePlane.cpp' object='libOPCODE_a-IcePlane.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IcePlane.o `test -f '@TOPDIR@/OPCODE/Ice/IcePlane.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IcePlane.cpp
+
+libOPCODE_a-IcePlane.obj: @TOPDIR@/OPCODE/Ice/IcePlane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IcePlane.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IcePlane.Tpo -c -o libOPCODE_a-IcePlane.obj `if test -f '@TOPDIR@/OPCODE/Ice/IcePlane.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IcePlane.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IcePlane.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IcePlane.Tpo $(DEPDIR)/libOPCODE_a-IcePlane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IcePlane.cpp' object='libOPCODE_a-IcePlane.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IcePlane.obj `if test -f '@TOPDIR@/OPCODE/Ice/IcePlane.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IcePlane.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IcePlane.cpp'; fi`
+
+libOPCODE_a-IcePoint.o: @TOPDIR@/OPCODE/Ice/IcePoint.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IcePoint.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IcePoint.Tpo -c -o libOPCODE_a-IcePoint.o `test -f '@TOPDIR@/OPCODE/Ice/IcePoint.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IcePoint.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IcePoint.Tpo $(DEPDIR)/libOPCODE_a-IcePoint.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IcePoint.cpp' object='libOPCODE_a-IcePoint.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IcePoint.o `test -f '@TOPDIR@/OPCODE/Ice/IcePoint.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IcePoint.cpp
+
+libOPCODE_a-IcePoint.obj: @TOPDIR@/OPCODE/Ice/IcePoint.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IcePoint.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IcePoint.Tpo -c -o libOPCODE_a-IcePoint.obj `if test -f '@TOPDIR@/OPCODE/Ice/IcePoint.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IcePoint.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IcePoint.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IcePoint.Tpo $(DEPDIR)/libOPCODE_a-IcePoint.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IcePoint.cpp' object='libOPCODE_a-IcePoint.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IcePoint.obj `if test -f '@TOPDIR@/OPCODE/Ice/IcePoint.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IcePoint.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IcePoint.cpp'; fi`
+
+libOPCODE_a-IceRandom.o: @TOPDIR@/OPCODE/Ice/IceRandom.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceRandom.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceRandom.Tpo -c -o libOPCODE_a-IceRandom.o `test -f '@TOPDIR@/OPCODE/Ice/IceRandom.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceRandom.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceRandom.Tpo $(DEPDIR)/libOPCODE_a-IceRandom.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceRandom.cpp' object='libOPCODE_a-IceRandom.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceRandom.o `test -f '@TOPDIR@/OPCODE/Ice/IceRandom.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceRandom.cpp
+
+libOPCODE_a-IceRandom.obj: @TOPDIR@/OPCODE/Ice/IceRandom.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceRandom.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceRandom.Tpo -c -o libOPCODE_a-IceRandom.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceRandom.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceRandom.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceRandom.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceRandom.Tpo $(DEPDIR)/libOPCODE_a-IceRandom.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceRandom.cpp' object='libOPCODE_a-IceRandom.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceRandom.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceRandom.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceRandom.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceRandom.cpp'; fi`
+
+libOPCODE_a-IceRay.o: @TOPDIR@/OPCODE/Ice/IceRay.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceRay.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceRay.Tpo -c -o libOPCODE_a-IceRay.o `test -f '@TOPDIR@/OPCODE/Ice/IceRay.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceRay.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceRay.Tpo $(DEPDIR)/libOPCODE_a-IceRay.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceRay.cpp' object='libOPCODE_a-IceRay.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceRay.o `test -f '@TOPDIR@/OPCODE/Ice/IceRay.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceRay.cpp
+
+libOPCODE_a-IceRay.obj: @TOPDIR@/OPCODE/Ice/IceRay.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceRay.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceRay.Tpo -c -o libOPCODE_a-IceRay.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceRay.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceRay.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceRay.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceRay.Tpo $(DEPDIR)/libOPCODE_a-IceRay.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceRay.cpp' object='libOPCODE_a-IceRay.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceRay.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceRay.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceRay.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceRay.cpp'; fi`
+
+libOPCODE_a-IceRevisitedRadix.o: @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceRevisitedRadix.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Tpo -c -o libOPCODE_a-IceRevisitedRadix.o `test -f '@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Tpo $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp' object='libOPCODE_a-IceRevisitedRadix.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceRevisitedRadix.o `test -f '@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp
+
+libOPCODE_a-IceRevisitedRadix.obj: @TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceRevisitedRadix.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Tpo -c -o libOPCODE_a-IceRevisitedRadix.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Tpo $(DEPDIR)/libOPCODE_a-IceRevisitedRadix.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp' object='libOPCODE_a-IceRevisitedRadix.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceRevisitedRadix.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceRevisitedRadix.cpp'; fi`
+
+libOPCODE_a-IceSegment.o: @TOPDIR@/OPCODE/Ice/IceSegment.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceSegment.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceSegment.Tpo -c -o libOPCODE_a-IceSegment.o `test -f '@TOPDIR@/OPCODE/Ice/IceSegment.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceSegment.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceSegment.Tpo $(DEPDIR)/libOPCODE_a-IceSegment.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceSegment.cpp' object='libOPCODE_a-IceSegment.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceSegment.o `test -f '@TOPDIR@/OPCODE/Ice/IceSegment.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceSegment.cpp
+
+libOPCODE_a-IceSegment.obj: @TOPDIR@/OPCODE/Ice/IceSegment.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceSegment.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceSegment.Tpo -c -o libOPCODE_a-IceSegment.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceSegment.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceSegment.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceSegment.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceSegment.Tpo $(DEPDIR)/libOPCODE_a-IceSegment.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceSegment.cpp' object='libOPCODE_a-IceSegment.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceSegment.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceSegment.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceSegment.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceSegment.cpp'; fi`
+
+libOPCODE_a-IceTriangle.o: @TOPDIR@/OPCODE/Ice/IceTriangle.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceTriangle.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceTriangle.Tpo -c -o libOPCODE_a-IceTriangle.o `test -f '@TOPDIR@/OPCODE/Ice/IceTriangle.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceTriangle.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceTriangle.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceTriangle.cpp' object='libOPCODE_a-IceTriangle.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceTriangle.o `test -f '@TOPDIR@/OPCODE/Ice/IceTriangle.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceTriangle.cpp
+
+libOPCODE_a-IceTriangle.obj: @TOPDIR@/OPCODE/Ice/IceTriangle.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceTriangle.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceTriangle.Tpo -c -o libOPCODE_a-IceTriangle.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceTriangle.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceTriangle.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceTriangle.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceTriangle.Tpo $(DEPDIR)/libOPCODE_a-IceTriangle.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceTriangle.cpp' object='libOPCODE_a-IceTriangle.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceTriangle.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceTriangle.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceTriangle.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceTriangle.cpp'; fi`
+
+libOPCODE_a-IceUtils.o: @TOPDIR@/OPCODE/Ice/IceUtils.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceUtils.o -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceUtils.Tpo -c -o libOPCODE_a-IceUtils.o `test -f '@TOPDIR@/OPCODE/Ice/IceUtils.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceUtils.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceUtils.Tpo $(DEPDIR)/libOPCODE_a-IceUtils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceUtils.cpp' object='libOPCODE_a-IceUtils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceUtils.o `test -f '@TOPDIR@/OPCODE/Ice/IceUtils.cpp' || echo '$(srcdir)/'`@TOPDIR@/OPCODE/Ice/IceUtils.cpp
+
+libOPCODE_a-IceUtils.obj: @TOPDIR@/OPCODE/Ice/IceUtils.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libOPCODE_a-IceUtils.obj -MD -MP -MF $(DEPDIR)/libOPCODE_a-IceUtils.Tpo -c -o libOPCODE_a-IceUtils.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceUtils.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceUtils.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libOPCODE_a-IceUtils.Tpo $(DEPDIR)/libOPCODE_a-IceUtils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='@TOPDIR@/OPCODE/Ice/IceUtils.cpp' object='libOPCODE_a-IceUtils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libOPCODE_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libOPCODE_a-IceUtils.obj `if test -f '@TOPDIR@/OPCODE/Ice/IceUtils.cpp'; then $(CYGPATH_W) '@TOPDIR@/OPCODE/Ice/IceUtils.cpp'; else $(CYGPATH_W) '$(srcdir)/@TOPDIR@/OPCODE/Ice/IceUtils.cpp'; fi`
+
+libode_a-obstack.o: obstack.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-obstack.o -MD -MP -MF $(DEPDIR)/libode_a-obstack.Tpo -c -o libode_a-obstack.o `test -f 'obstack.cpp' || echo '$(srcdir)/'`obstack.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-obstack.Tpo $(DEPDIR)/libode_a-obstack.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='obstack.cpp' object='libode_a-obstack.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-obstack.o `test -f 'obstack.cpp' || echo '$(srcdir)/'`obstack.cpp
+
+libode_a-obstack.obj: obstack.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-obstack.obj -MD -MP -MF $(DEPDIR)/libode_a-obstack.Tpo -c -o libode_a-obstack.obj `if test -f 'obstack.cpp'; then $(CYGPATH_W) 'obstack.cpp'; else $(CYGPATH_W) '$(srcdir)/obstack.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-obstack.Tpo $(DEPDIR)/libode_a-obstack.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='obstack.cpp' object='libode_a-obstack.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-obstack.obj `if test -f 'obstack.cpp'; then $(CYGPATH_W) 'obstack.cpp'; else $(CYGPATH_W) '$(srcdir)/obstack.cpp'; fi`
+
+libode_a-collision_util.o: collision_util.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_util.o -MD -MP -MF $(DEPDIR)/libode_a-collision_util.Tpo -c -o libode_a-collision_util.o `test -f 'collision_util.cpp' || echo '$(srcdir)/'`collision_util.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_util.Tpo $(DEPDIR)/libode_a-collision_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_util.cpp' object='libode_a-collision_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_util.o `test -f 'collision_util.cpp' || echo '$(srcdir)/'`collision_util.cpp
+
+libode_a-collision_util.obj: collision_util.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_util.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_util.Tpo -c -o libode_a-collision_util.obj `if test -f 'collision_util.cpp'; then $(CYGPATH_W) 'collision_util.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_util.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_util.Tpo $(DEPDIR)/libode_a-collision_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_util.cpp' object='libode_a-collision_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_util.obj `if test -f 'collision_util.cpp'; then $(CYGPATH_W) 'collision_util.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_util.cpp'; fi`
+
+libode_a-array.o: array.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-array.o -MD -MP -MF $(DEPDIR)/libode_a-array.Tpo -c -o libode_a-array.o `test -f 'array.cpp' || echo '$(srcdir)/'`array.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-array.Tpo $(DEPDIR)/libode_a-array.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='array.cpp' object='libode_a-array.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-array.o `test -f 'array.cpp' || echo '$(srcdir)/'`array.cpp
+
+libode_a-array.obj: array.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-array.obj -MD -MP -MF $(DEPDIR)/libode_a-array.Tpo -c -o libode_a-array.obj `if test -f 'array.cpp'; then $(CYGPATH_W) 'array.cpp'; else $(CYGPATH_W) '$(srcdir)/array.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-array.Tpo $(DEPDIR)/libode_a-array.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='array.cpp' object='libode_a-array.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-array.obj `if test -f 'array.cpp'; then $(CYGPATH_W) 'array.cpp'; else $(CYGPATH_W) '$(srcdir)/array.cpp'; fi`
+
+libode_a-ode.o: ode.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-ode.o -MD -MP -MF $(DEPDIR)/libode_a-ode.Tpo -c -o libode_a-ode.o `test -f 'ode.cpp' || echo '$(srcdir)/'`ode.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-ode.Tpo $(DEPDIR)/libode_a-ode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='ode.cpp' object='libode_a-ode.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-ode.o `test -f 'ode.cpp' || echo '$(srcdir)/'`ode.cpp
+
+libode_a-ode.obj: ode.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-ode.obj -MD -MP -MF $(DEPDIR)/libode_a-ode.Tpo -c -o libode_a-ode.obj `if test -f 'ode.cpp'; then $(CYGPATH_W) 'ode.cpp'; else $(CYGPATH_W) '$(srcdir)/ode.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-ode.Tpo $(DEPDIR)/libode_a-ode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='ode.cpp' object='libode_a-ode.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-ode.obj `if test -f 'ode.cpp'; then $(CYGPATH_W) 'ode.cpp'; else $(CYGPATH_W) '$(srcdir)/ode.cpp'; fi`
+
+libode_a-error.o: error.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-error.o -MD -MP -MF $(DEPDIR)/libode_a-error.Tpo -c -o libode_a-error.o `test -f 'error.cpp' || echo '$(srcdir)/'`error.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-error.Tpo $(DEPDIR)/libode_a-error.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='error.cpp' object='libode_a-error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-error.o `test -f 'error.cpp' || echo '$(srcdir)/'`error.cpp
+
+libode_a-error.obj: error.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-error.obj -MD -MP -MF $(DEPDIR)/libode_a-error.Tpo -c -o libode_a-error.obj `if test -f 'error.cpp'; then $(CYGPATH_W) 'error.cpp'; else $(CYGPATH_W) '$(srcdir)/error.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-error.Tpo $(DEPDIR)/libode_a-error.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='error.cpp' object='libode_a-error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-error.obj `if test -f 'error.cpp'; then $(CYGPATH_W) 'error.cpp'; else $(CYGPATH_W) '$(srcdir)/error.cpp'; fi`
+
+libode_a-odemath.o: odemath.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-odemath.o -MD -MP -MF $(DEPDIR)/libode_a-odemath.Tpo -c -o libode_a-odemath.o `test -f 'odemath.cpp' || echo '$(srcdir)/'`odemath.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-odemath.Tpo $(DEPDIR)/libode_a-odemath.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='odemath.cpp' object='libode_a-odemath.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-odemath.o `test -f 'odemath.cpp' || echo '$(srcdir)/'`odemath.cpp
+
+libode_a-odemath.obj: odemath.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-odemath.obj -MD -MP -MF $(DEPDIR)/libode_a-odemath.Tpo -c -o libode_a-odemath.obj `if test -f 'odemath.cpp'; then $(CYGPATH_W) 'odemath.cpp'; else $(CYGPATH_W) '$(srcdir)/odemath.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-odemath.Tpo $(DEPDIR)/libode_a-odemath.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='odemath.cpp' object='libode_a-odemath.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-odemath.obj `if test -f 'odemath.cpp'; then $(CYGPATH_W) 'odemath.cpp'; else $(CYGPATH_W) '$(srcdir)/odemath.cpp'; fi`
+
+libode_a-collision_kernel.o: collision_kernel.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_kernel.o -MD -MP -MF $(DEPDIR)/libode_a-collision_kernel.Tpo -c -o libode_a-collision_kernel.o `test -f 'collision_kernel.cpp' || echo '$(srcdir)/'`collision_kernel.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_kernel.Tpo $(DEPDIR)/libode_a-collision_kernel.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_kernel.cpp' object='libode_a-collision_kernel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_kernel.o `test -f 'collision_kernel.cpp' || echo '$(srcdir)/'`collision_kernel.cpp
+
+libode_a-collision_kernel.obj: collision_kernel.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_kernel.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_kernel.Tpo -c -o libode_a-collision_kernel.obj `if test -f 'collision_kernel.cpp'; then $(CYGPATH_W) 'collision_kernel.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_kernel.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_kernel.Tpo $(DEPDIR)/libode_a-collision_kernel.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_kernel.cpp' object='libode_a-collision_kernel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_kernel.obj `if test -f 'collision_kernel.cpp'; then $(CYGPATH_W) 'collision_kernel.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_kernel.cpp'; fi`
+
+libode_a-export-dif.o: export-dif.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-export-dif.o -MD -MP -MF $(DEPDIR)/libode_a-export-dif.Tpo -c -o libode_a-export-dif.o `test -f 'export-dif.cpp' || echo '$(srcdir)/'`export-dif.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-export-dif.Tpo $(DEPDIR)/libode_a-export-dif.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='export-dif.cpp' object='libode_a-export-dif.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-export-dif.o `test -f 'export-dif.cpp' || echo '$(srcdir)/'`export-dif.cpp
+
+libode_a-export-dif.obj: export-dif.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-export-dif.obj -MD -MP -MF $(DEPDIR)/libode_a-export-dif.Tpo -c -o libode_a-export-dif.obj `if test -f 'export-dif.cpp'; then $(CYGPATH_W) 'export-dif.cpp'; else $(CYGPATH_W) '$(srcdir)/export-dif.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-export-dif.Tpo $(DEPDIR)/libode_a-export-dif.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='export-dif.cpp' object='libode_a-export-dif.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-export-dif.obj `if test -f 'export-dif.cpp'; then $(CYGPATH_W) 'export-dif.cpp'; else $(CYGPATH_W) '$(srcdir)/export-dif.cpp'; fi`
+
+libode_a-quickstep.o: quickstep.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-quickstep.o -MD -MP -MF $(DEPDIR)/libode_a-quickstep.Tpo -c -o libode_a-quickstep.o `test -f 'quickstep.cpp' || echo '$(srcdir)/'`quickstep.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-quickstep.Tpo $(DEPDIR)/libode_a-quickstep.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='quickstep.cpp' object='libode_a-quickstep.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-quickstep.o `test -f 'quickstep.cpp' || echo '$(srcdir)/'`quickstep.cpp
+
+libode_a-quickstep.obj: quickstep.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-quickstep.obj -MD -MP -MF $(DEPDIR)/libode_a-quickstep.Tpo -c -o libode_a-quickstep.obj `if test -f 'quickstep.cpp'; then $(CYGPATH_W) 'quickstep.cpp'; else $(CYGPATH_W) '$(srcdir)/quickstep.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-quickstep.Tpo $(DEPDIR)/libode_a-quickstep.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='quickstep.cpp' object='libode_a-quickstep.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-quickstep.obj `if test -f 'quickstep.cpp'; then $(CYGPATH_W) 'quickstep.cpp'; else $(CYGPATH_W) '$(srcdir)/quickstep.cpp'; fi`
+
+libode_a-collision_quadtreespace.o: collision_quadtreespace.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_quadtreespace.o -MD -MP -MF $(DEPDIR)/libode_a-collision_quadtreespace.Tpo -c -o libode_a-collision_quadtreespace.o `test -f 'collision_quadtreespace.cpp' || echo '$(srcdir)/'`collision_quadtreespace.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_quadtreespace.Tpo $(DEPDIR)/libode_a-collision_quadtreespace.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_quadtreespace.cpp' object='libode_a-collision_quadtreespace.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_quadtreespace.o `test -f 'collision_quadtreespace.cpp' || echo '$(srcdir)/'`collision_quadtreespace.cpp
+
+libode_a-collision_quadtreespace.obj: collision_quadtreespace.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_quadtreespace.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_quadtreespace.Tpo -c -o libode_a-collision_quadtreespace.obj `if test -f 'collision_quadtreespace.cpp'; then $(CYGPATH_W) 'collision_quadtreespace.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_quadtreespace.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_quadtreespace.Tpo $(DEPDIR)/libode_a-collision_quadtreespace.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_quadtreespace.cpp' object='libode_a-collision_quadtreespace.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_quadtreespace.obj `if test -f 'collision_quadtreespace.cpp'; then $(CYGPATH_W) 'collision_quadtreespace.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_quadtreespace.cpp'; fi`
+
+libode_a-rotation.o: rotation.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-rotation.o -MD -MP -MF $(DEPDIR)/libode_a-rotation.Tpo -c -o libode_a-rotation.o `test -f 'rotation.cpp' || echo '$(srcdir)/'`rotation.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-rotation.Tpo $(DEPDIR)/libode_a-rotation.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='rotation.cpp' object='libode_a-rotation.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-rotation.o `test -f 'rotation.cpp' || echo '$(srcdir)/'`rotation.cpp
+
+libode_a-rotation.obj: rotation.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-rotation.obj -MD -MP -MF $(DEPDIR)/libode_a-rotation.Tpo -c -o libode_a-rotation.obj `if test -f 'rotation.cpp'; then $(CYGPATH_W) 'rotation.cpp'; else $(CYGPATH_W) '$(srcdir)/rotation.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-rotation.Tpo $(DEPDIR)/libode_a-rotation.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='rotation.cpp' object='libode_a-rotation.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-rotation.obj `if test -f 'rotation.cpp'; then $(CYGPATH_W) 'rotation.cpp'; else $(CYGPATH_W) '$(srcdir)/rotation.cpp'; fi`
+
+libode_a-collision_space.o: collision_space.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_space.o -MD -MP -MF $(DEPDIR)/libode_a-collision_space.Tpo -c -o libode_a-collision_space.o `test -f 'collision_space.cpp' || echo '$(srcdir)/'`collision_space.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_space.Tpo $(DEPDIR)/libode_a-collision_space.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_space.cpp' object='libode_a-collision_space.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_space.o `test -f 'collision_space.cpp' || echo '$(srcdir)/'`collision_space.cpp
+
+libode_a-collision_space.obj: collision_space.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_space.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_space.Tpo -c -o libode_a-collision_space.obj `if test -f 'collision_space.cpp'; then $(CYGPATH_W) 'collision_space.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_space.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_space.Tpo $(DEPDIR)/libode_a-collision_space.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_space.cpp' object='libode_a-collision_space.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_space.obj `if test -f 'collision_space.cpp'; then $(CYGPATH_W) 'collision_space.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_space.cpp'; fi`
+
+libode_a-collision_cylinder_box.o: collision_cylinder_box.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_box.o -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_box.Tpo -c -o libode_a-collision_cylinder_box.o `test -f 'collision_cylinder_box.cpp' || echo '$(srcdir)/'`collision_cylinder_box.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_box.Tpo $(DEPDIR)/libode_a-collision_cylinder_box.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_box.cpp' object='libode_a-collision_cylinder_box.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_box.o `test -f 'collision_cylinder_box.cpp' || echo '$(srcdir)/'`collision_cylinder_box.cpp
+
+libode_a-collision_cylinder_box.obj: collision_cylinder_box.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_box.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_box.Tpo -c -o libode_a-collision_cylinder_box.obj `if test -f 'collision_cylinder_box.cpp'; then $(CYGPATH_W) 'collision_cylinder_box.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_box.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_box.Tpo $(DEPDIR)/libode_a-collision_cylinder_box.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_box.cpp' object='libode_a-collision_cylinder_box.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_box.obj `if test -f 'collision_cylinder_box.cpp'; then $(CYGPATH_W) 'collision_cylinder_box.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_box.cpp'; fi`
+
+libode_a-collision_cylinder_sphere.o: collision_cylinder_sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_sphere.o -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_sphere.Tpo -c -o libode_a-collision_cylinder_sphere.o `test -f 'collision_cylinder_sphere.cpp' || echo '$(srcdir)/'`collision_cylinder_sphere.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_sphere.Tpo $(DEPDIR)/libode_a-collision_cylinder_sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_sphere.cpp' object='libode_a-collision_cylinder_sphere.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_sphere.o `test -f 'collision_cylinder_sphere.cpp' || echo '$(srcdir)/'`collision_cylinder_sphere.cpp
+
+libode_a-collision_cylinder_sphere.obj: collision_cylinder_sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_sphere.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_sphere.Tpo -c -o libode_a-collision_cylinder_sphere.obj `if test -f 'collision_cylinder_sphere.cpp'; then $(CYGPATH_W) 'collision_cylinder_sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_sphere.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_sphere.Tpo $(DEPDIR)/libode_a-collision_cylinder_sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_sphere.cpp' object='libode_a-collision_cylinder_sphere.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_sphere.obj `if test -f 'collision_cylinder_sphere.cpp'; then $(CYGPATH_W) 'collision_cylinder_sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_sphere.cpp'; fi`
+
+libode_a-collision_cylinder_plane.o: collision_cylinder_plane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_plane.o -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_plane.Tpo -c -o libode_a-collision_cylinder_plane.o `test -f 'collision_cylinder_plane.cpp' || echo '$(srcdir)/'`collision_cylinder_plane.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_plane.Tpo $(DEPDIR)/libode_a-collision_cylinder_plane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_plane.cpp' object='libode_a-collision_cylinder_plane.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_plane.o `test -f 'collision_cylinder_plane.cpp' || echo '$(srcdir)/'`collision_cylinder_plane.cpp
+
+libode_a-collision_cylinder_plane.obj: collision_cylinder_plane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_plane.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_plane.Tpo -c -o libode_a-collision_cylinder_plane.obj `if test -f 'collision_cylinder_plane.cpp'; then $(CYGPATH_W) 'collision_cylinder_plane.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_plane.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_plane.Tpo $(DEPDIR)/libode_a-collision_cylinder_plane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_plane.cpp' object='libode_a-collision_cylinder_plane.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_plane.obj `if test -f 'collision_cylinder_plane.cpp'; then $(CYGPATH_W) 'collision_cylinder_plane.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_plane.cpp'; fi`
+
+libode_a-sphere.o: sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-sphere.o -MD -MP -MF $(DEPDIR)/libode_a-sphere.Tpo -c -o libode_a-sphere.o `test -f 'sphere.cpp' || echo '$(srcdir)/'`sphere.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-sphere.Tpo $(DEPDIR)/libode_a-sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='sphere.cpp' object='libode_a-sphere.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-sphere.o `test -f 'sphere.cpp' || echo '$(srcdir)/'`sphere.cpp
+
+libode_a-sphere.obj: sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-sphere.obj -MD -MP -MF $(DEPDIR)/libode_a-sphere.Tpo -c -o libode_a-sphere.obj `if test -f 'sphere.cpp'; then $(CYGPATH_W) 'sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/sphere.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-sphere.Tpo $(DEPDIR)/libode_a-sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='sphere.cpp' object='libode_a-sphere.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-sphere.obj `if test -f 'sphere.cpp'; then $(CYGPATH_W) 'sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/sphere.cpp'; fi`
+
+libode_a-box.o: box.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-box.o -MD -MP -MF $(DEPDIR)/libode_a-box.Tpo -c -o libode_a-box.o `test -f 'box.cpp' || echo '$(srcdir)/'`box.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-box.Tpo $(DEPDIR)/libode_a-box.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='box.cpp' object='libode_a-box.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-box.o `test -f 'box.cpp' || echo '$(srcdir)/'`box.cpp
+
+libode_a-box.obj: box.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-box.obj -MD -MP -MF $(DEPDIR)/libode_a-box.Tpo -c -o libode_a-box.obj `if test -f 'box.cpp'; then $(CYGPATH_W) 'box.cpp'; else $(CYGPATH_W) '$(srcdir)/box.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-box.Tpo $(DEPDIR)/libode_a-box.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='box.cpp' object='libode_a-box.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-box.obj `if test -f 'box.cpp'; then $(CYGPATH_W) 'box.cpp'; else $(CYGPATH_W) '$(srcdir)/box.cpp'; fi`
+
+libode_a-capsule.o: capsule.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-capsule.o -MD -MP -MF $(DEPDIR)/libode_a-capsule.Tpo -c -o libode_a-capsule.o `test -f 'capsule.cpp' || echo '$(srcdir)/'`capsule.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-capsule.Tpo $(DEPDIR)/libode_a-capsule.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='capsule.cpp' object='libode_a-capsule.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-capsule.o `test -f 'capsule.cpp' || echo '$(srcdir)/'`capsule.cpp
+
+libode_a-capsule.obj: capsule.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-capsule.obj -MD -MP -MF $(DEPDIR)/libode_a-capsule.Tpo -c -o libode_a-capsule.obj `if test -f 'capsule.cpp'; then $(CYGPATH_W) 'capsule.cpp'; else $(CYGPATH_W) '$(srcdir)/capsule.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-capsule.Tpo $(DEPDIR)/libode_a-capsule.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='capsule.cpp' object='libode_a-capsule.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-capsule.obj `if test -f 'capsule.cpp'; then $(CYGPATH_W) 'capsule.cpp'; else $(CYGPATH_W) '$(srcdir)/capsule.cpp'; fi`
+
+libode_a-plane.o: plane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-plane.o -MD -MP -MF $(DEPDIR)/libode_a-plane.Tpo -c -o libode_a-plane.o `test -f 'plane.cpp' || echo '$(srcdir)/'`plane.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-plane.Tpo $(DEPDIR)/libode_a-plane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='plane.cpp' object='libode_a-plane.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-plane.o `test -f 'plane.cpp' || echo '$(srcdir)/'`plane.cpp
+
+libode_a-plane.obj: plane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-plane.obj -MD -MP -MF $(DEPDIR)/libode_a-plane.Tpo -c -o libode_a-plane.obj `if test -f 'plane.cpp'; then $(CYGPATH_W) 'plane.cpp'; else $(CYGPATH_W) '$(srcdir)/plane.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-plane.Tpo $(DEPDIR)/libode_a-plane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='plane.cpp' object='libode_a-plane.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-plane.obj `if test -f 'plane.cpp'; then $(CYGPATH_W) 'plane.cpp'; else $(CYGPATH_W) '$(srcdir)/plane.cpp'; fi`
+
+libode_a-ray.o: ray.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-ray.o -MD -MP -MF $(DEPDIR)/libode_a-ray.Tpo -c -o libode_a-ray.o `test -f 'ray.cpp' || echo '$(srcdir)/'`ray.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-ray.Tpo $(DEPDIR)/libode_a-ray.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='ray.cpp' object='libode_a-ray.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-ray.o `test -f 'ray.cpp' || echo '$(srcdir)/'`ray.cpp
+
+libode_a-ray.obj: ray.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-ray.obj -MD -MP -MF $(DEPDIR)/libode_a-ray.Tpo -c -o libode_a-ray.obj `if test -f 'ray.cpp'; then $(CYGPATH_W) 'ray.cpp'; else $(CYGPATH_W) '$(srcdir)/ray.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-ray.Tpo $(DEPDIR)/libode_a-ray.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='ray.cpp' object='libode_a-ray.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-ray.obj `if test -f 'ray.cpp'; then $(CYGPATH_W) 'ray.cpp'; else $(CYGPATH_W) '$(srcdir)/ray.cpp'; fi`
+
+libode_a-cylinder.o: cylinder.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-cylinder.o -MD -MP -MF $(DEPDIR)/libode_a-cylinder.Tpo -c -o libode_a-cylinder.o `test -f 'cylinder.cpp' || echo '$(srcdir)/'`cylinder.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-cylinder.Tpo $(DEPDIR)/libode_a-cylinder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='cylinder.cpp' object='libode_a-cylinder.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-cylinder.o `test -f 'cylinder.cpp' || echo '$(srcdir)/'`cylinder.cpp
+
+libode_a-cylinder.obj: cylinder.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-cylinder.obj -MD -MP -MF $(DEPDIR)/libode_a-cylinder.Tpo -c -o libode_a-cylinder.obj `if test -f 'cylinder.cpp'; then $(CYGPATH_W) 'cylinder.cpp'; else $(CYGPATH_W) '$(srcdir)/cylinder.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-cylinder.Tpo $(DEPDIR)/libode_a-cylinder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='cylinder.cpp' object='libode_a-cylinder.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-cylinder.obj `if test -f 'cylinder.cpp'; then $(CYGPATH_W) 'cylinder.cpp'; else $(CYGPATH_W) '$(srcdir)/cylinder.cpp'; fi`
+
+libode_a-convex.o: convex.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-convex.o -MD -MP -MF $(DEPDIR)/libode_a-convex.Tpo -c -o libode_a-convex.o `test -f 'convex.cpp' || echo '$(srcdir)/'`convex.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-convex.Tpo $(DEPDIR)/libode_a-convex.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='convex.cpp' object='libode_a-convex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-convex.o `test -f 'convex.cpp' || echo '$(srcdir)/'`convex.cpp
+
+libode_a-convex.obj: convex.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-convex.obj -MD -MP -MF $(DEPDIR)/libode_a-convex.Tpo -c -o libode_a-convex.obj `if test -f 'convex.cpp'; then $(CYGPATH_W) 'convex.cpp'; else $(CYGPATH_W) '$(srcdir)/convex.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-convex.Tpo $(DEPDIR)/libode_a-convex.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='convex.cpp' object='libode_a-convex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-convex.obj `if test -f 'convex.cpp'; then $(CYGPATH_W) 'convex.cpp'; else $(CYGPATH_W) '$(srcdir)/convex.cpp'; fi`
+
+libode_a-joint.o: joint.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-joint.o -MD -MP -MF $(DEPDIR)/libode_a-joint.Tpo -c -o libode_a-joint.o `test -f 'joint.cpp' || echo '$(srcdir)/'`joint.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-joint.Tpo $(DEPDIR)/libode_a-joint.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='joint.cpp' object='libode_a-joint.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-joint.o `test -f 'joint.cpp' || echo '$(srcdir)/'`joint.cpp
+
+libode_a-joint.obj: joint.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-joint.obj -MD -MP -MF $(DEPDIR)/libode_a-joint.Tpo -c -o libode_a-joint.obj `if test -f 'joint.cpp'; then $(CYGPATH_W) 'joint.cpp'; else $(CYGPATH_W) '$(srcdir)/joint.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-joint.Tpo $(DEPDIR)/libode_a-joint.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='joint.cpp' object='libode_a-joint.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-joint.obj `if test -f 'joint.cpp'; then $(CYGPATH_W) 'joint.cpp'; else $(CYGPATH_W) '$(srcdir)/joint.cpp'; fi`
+
+libode_a-step.o: step.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-step.o -MD -MP -MF $(DEPDIR)/libode_a-step.Tpo -c -o libode_a-step.o `test -f 'step.cpp' || echo '$(srcdir)/'`step.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-step.Tpo $(DEPDIR)/libode_a-step.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='step.cpp' object='libode_a-step.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-step.o `test -f 'step.cpp' || echo '$(srcdir)/'`step.cpp
+
+libode_a-step.obj: step.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-step.obj -MD -MP -MF $(DEPDIR)/libode_a-step.Tpo -c -o libode_a-step.obj `if test -f 'step.cpp'; then $(CYGPATH_W) 'step.cpp'; else $(CYGPATH_W) '$(srcdir)/step.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-step.Tpo $(DEPDIR)/libode_a-step.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='step.cpp' object='libode_a-step.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-step.obj `if test -f 'step.cpp'; then $(CYGPATH_W) 'step.cpp'; else $(CYGPATH_W) '$(srcdir)/step.cpp'; fi`
+
+libode_a-collision_transform.o: collision_transform.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_transform.o -MD -MP -MF $(DEPDIR)/libode_a-collision_transform.Tpo -c -o libode_a-collision_transform.o `test -f 'collision_transform.cpp' || echo '$(srcdir)/'`collision_transform.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_transform.Tpo $(DEPDIR)/libode_a-collision_transform.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_transform.cpp' object='libode_a-collision_transform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_transform.o `test -f 'collision_transform.cpp' || echo '$(srcdir)/'`collision_transform.cpp
+
+libode_a-collision_transform.obj: collision_transform.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_transform.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_transform.Tpo -c -o libode_a-collision_transform.obj `if test -f 'collision_transform.cpp'; then $(CYGPATH_W) 'collision_transform.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_transform.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_transform.Tpo $(DEPDIR)/libode_a-collision_transform.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_transform.cpp' object='libode_a-collision_transform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_transform.obj `if test -f 'collision_transform.cpp'; then $(CYGPATH_W) 'collision_transform.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_transform.cpp'; fi`
+
+libode_a-lcp.o: lcp.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-lcp.o -MD -MP -MF $(DEPDIR)/libode_a-lcp.Tpo -c -o libode_a-lcp.o `test -f 'lcp.cpp' || echo '$(srcdir)/'`lcp.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-lcp.Tpo $(DEPDIR)/libode_a-lcp.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='lcp.cpp' object='libode_a-lcp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-lcp.o `test -f 'lcp.cpp' || echo '$(srcdir)/'`lcp.cpp
+
+libode_a-lcp.obj: lcp.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-lcp.obj -MD -MP -MF $(DEPDIR)/libode_a-lcp.Tpo -c -o libode_a-lcp.obj `if test -f 'lcp.cpp'; then $(CYGPATH_W) 'lcp.cpp'; else $(CYGPATH_W) '$(srcdir)/lcp.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-lcp.Tpo $(DEPDIR)/libode_a-lcp.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='lcp.cpp' object='libode_a-lcp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-lcp.obj `if test -f 'lcp.cpp'; then $(CYGPATH_W) 'lcp.cpp'; else $(CYGPATH_W) '$(srcdir)/lcp.cpp'; fi`
+
+libode_a-stepfast.o: stepfast.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-stepfast.o -MD -MP -MF $(DEPDIR)/libode_a-stepfast.Tpo -c -o libode_a-stepfast.o `test -f 'stepfast.cpp' || echo '$(srcdir)/'`stepfast.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-stepfast.Tpo $(DEPDIR)/libode_a-stepfast.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='stepfast.cpp' object='libode_a-stepfast.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-stepfast.o `test -f 'stepfast.cpp' || echo '$(srcdir)/'`stepfast.cpp
+
+libode_a-stepfast.obj: stepfast.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-stepfast.obj -MD -MP -MF $(DEPDIR)/libode_a-stepfast.Tpo -c -o libode_a-stepfast.obj `if test -f 'stepfast.cpp'; then $(CYGPATH_W) 'stepfast.cpp'; else $(CYGPATH_W) '$(srcdir)/stepfast.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-stepfast.Tpo $(DEPDIR)/libode_a-stepfast.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='stepfast.cpp' object='libode_a-stepfast.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-stepfast.obj `if test -f 'stepfast.cpp'; then $(CYGPATH_W) 'stepfast.cpp'; else $(CYGPATH_W) '$(srcdir)/stepfast.cpp'; fi`
+
+libode_a-mass.o: mass.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-mass.o -MD -MP -MF $(DEPDIR)/libode_a-mass.Tpo -c -o libode_a-mass.o `test -f 'mass.cpp' || echo '$(srcdir)/'`mass.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-mass.Tpo $(DEPDIR)/libode_a-mass.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='mass.cpp' object='libode_a-mass.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-mass.o `test -f 'mass.cpp' || echo '$(srcdir)/'`mass.cpp
+
+libode_a-mass.obj: mass.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-mass.obj -MD -MP -MF $(DEPDIR)/libode_a-mass.Tpo -c -o libode_a-mass.obj `if test -f 'mass.cpp'; then $(CYGPATH_W) 'mass.cpp'; else $(CYGPATH_W) '$(srcdir)/mass.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-mass.Tpo $(DEPDIR)/libode_a-mass.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='mass.cpp' object='libode_a-mass.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-mass.obj `if test -f 'mass.cpp'; then $(CYGPATH_W) 'mass.cpp'; else $(CYGPATH_W) '$(srcdir)/mass.cpp'; fi`
+
+libode_a-testing.o: testing.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-testing.o -MD -MP -MF $(DEPDIR)/libode_a-testing.Tpo -c -o libode_a-testing.o `test -f 'testing.cpp' || echo '$(srcdir)/'`testing.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-testing.Tpo $(DEPDIR)/libode_a-testing.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='testing.cpp' object='libode_a-testing.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-testing.o `test -f 'testing.cpp' || echo '$(srcdir)/'`testing.cpp
+
+libode_a-testing.obj: testing.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-testing.obj -MD -MP -MF $(DEPDIR)/libode_a-testing.Tpo -c -o libode_a-testing.obj `if test -f 'testing.cpp'; then $(CYGPATH_W) 'testing.cpp'; else $(CYGPATH_W) '$(srcdir)/testing.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-testing.Tpo $(DEPDIR)/libode_a-testing.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='testing.cpp' object='libode_a-testing.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-testing.obj `if test -f 'testing.cpp'; then $(CYGPATH_W) 'testing.cpp'; else $(CYGPATH_W) '$(srcdir)/testing.cpp'; fi`
+
+libode_a-mat.o: mat.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-mat.o -MD -MP -MF $(DEPDIR)/libode_a-mat.Tpo -c -o libode_a-mat.o `test -f 'mat.cpp' || echo '$(srcdir)/'`mat.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-mat.Tpo $(DEPDIR)/libode_a-mat.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='mat.cpp' object='libode_a-mat.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-mat.o `test -f 'mat.cpp' || echo '$(srcdir)/'`mat.cpp
+
+libode_a-mat.obj: mat.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-mat.obj -MD -MP -MF $(DEPDIR)/libode_a-mat.Tpo -c -o libode_a-mat.obj `if test -f 'mat.cpp'; then $(CYGPATH_W) 'mat.cpp'; else $(CYGPATH_W) '$(srcdir)/mat.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-mat.Tpo $(DEPDIR)/libode_a-mat.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='mat.cpp' object='libode_a-mat.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-mat.obj `if test -f 'mat.cpp'; then $(CYGPATH_W) 'mat.cpp'; else $(CYGPATH_W) '$(srcdir)/mat.cpp'; fi`
+
+libode_a-timer.o: timer.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-timer.o -MD -MP -MF $(DEPDIR)/libode_a-timer.Tpo -c -o libode_a-timer.o `test -f 'timer.cpp' || echo '$(srcdir)/'`timer.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-timer.Tpo $(DEPDIR)/libode_a-timer.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='timer.cpp' object='libode_a-timer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-timer.o `test -f 'timer.cpp' || echo '$(srcdir)/'`timer.cpp
+
+libode_a-timer.obj: timer.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-timer.obj -MD -MP -MF $(DEPDIR)/libode_a-timer.Tpo -c -o libode_a-timer.obj `if test -f 'timer.cpp'; then $(CYGPATH_W) 'timer.cpp'; else $(CYGPATH_W) '$(srcdir)/timer.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-timer.Tpo $(DEPDIR)/libode_a-timer.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='timer.cpp' object='libode_a-timer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-timer.obj `if test -f 'timer.cpp'; then $(CYGPATH_W) 'timer.cpp'; else $(CYGPATH_W) '$(srcdir)/timer.cpp'; fi`
+
+libode_a-matrix.o: matrix.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-matrix.o -MD -MP -MF $(DEPDIR)/libode_a-matrix.Tpo -c -o libode_a-matrix.o `test -f 'matrix.cpp' || echo '$(srcdir)/'`matrix.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-matrix.Tpo $(DEPDIR)/libode_a-matrix.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='matrix.cpp' object='libode_a-matrix.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-matrix.o `test -f 'matrix.cpp' || echo '$(srcdir)/'`matrix.cpp
+
+libode_a-matrix.obj: matrix.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-matrix.obj -MD -MP -MF $(DEPDIR)/libode_a-matrix.Tpo -c -o libode_a-matrix.obj `if test -f 'matrix.cpp'; then $(CYGPATH_W) 'matrix.cpp'; else $(CYGPATH_W) '$(srcdir)/matrix.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-matrix.Tpo $(DEPDIR)/libode_a-matrix.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='matrix.cpp' object='libode_a-matrix.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-matrix.obj `if test -f 'matrix.cpp'; then $(CYGPATH_W) 'matrix.cpp'; else $(CYGPATH_W) '$(srcdir)/matrix.cpp'; fi`
+
+libode_a-util.o: util.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-util.o -MD -MP -MF $(DEPDIR)/libode_a-util.Tpo -c -o libode_a-util.o `test -f 'util.cpp' || echo '$(srcdir)/'`util.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-util.Tpo $(DEPDIR)/libode_a-util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='util.cpp' object='libode_a-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-util.o `test -f 'util.cpp' || echo '$(srcdir)/'`util.cpp
+
+libode_a-util.obj: util.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-util.obj -MD -MP -MF $(DEPDIR)/libode_a-util.Tpo -c -o libode_a-util.obj `if test -f 'util.cpp'; then $(CYGPATH_W) 'util.cpp'; else $(CYGPATH_W) '$(srcdir)/util.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-util.Tpo $(DEPDIR)/libode_a-util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='util.cpp' object='libode_a-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-util.obj `if test -f 'util.cpp'; then $(CYGPATH_W) 'util.cpp'; else $(CYGPATH_W) '$(srcdir)/util.cpp'; fi`
+
+libode_a-memory.o: memory.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-memory.o -MD -MP -MF $(DEPDIR)/libode_a-memory.Tpo -c -o libode_a-memory.o `test -f 'memory.cpp' || echo '$(srcdir)/'`memory.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-memory.Tpo $(DEPDIR)/libode_a-memory.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='memory.cpp' object='libode_a-memory.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-memory.o `test -f 'memory.cpp' || echo '$(srcdir)/'`memory.cpp
+
+libode_a-memory.obj: memory.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-memory.obj -MD -MP -MF $(DEPDIR)/libode_a-memory.Tpo -c -o libode_a-memory.obj `if test -f 'memory.cpp'; then $(CYGPATH_W) 'memory.cpp'; else $(CYGPATH_W) '$(srcdir)/memory.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-memory.Tpo $(DEPDIR)/libode_a-memory.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='memory.cpp' object='libode_a-memory.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-memory.obj `if test -f 'memory.cpp'; then $(CYGPATH_W) 'memory.cpp'; else $(CYGPATH_W) '$(srcdir)/memory.cpp'; fi`
+
+libode_a-misc.o: misc.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-misc.o -MD -MP -MF $(DEPDIR)/libode_a-misc.Tpo -c -o libode_a-misc.o `test -f 'misc.cpp' || echo '$(srcdir)/'`misc.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-misc.Tpo $(DEPDIR)/libode_a-misc.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='misc.cpp' object='libode_a-misc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-misc.o `test -f 'misc.cpp' || echo '$(srcdir)/'`misc.cpp
+
+libode_a-misc.obj: misc.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-misc.obj -MD -MP -MF $(DEPDIR)/libode_a-misc.Tpo -c -o libode_a-misc.obj `if test -f 'misc.cpp'; then $(CYGPATH_W) 'misc.cpp'; else $(CYGPATH_W) '$(srcdir)/misc.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-misc.Tpo $(DEPDIR)/libode_a-misc.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='misc.cpp' object='libode_a-misc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-misc.obj `if test -f 'misc.cpp'; then $(CYGPATH_W) 'misc.cpp'; else $(CYGPATH_W) '$(srcdir)/misc.cpp'; fi`
+
+libode_a-heightfield.o: heightfield.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-heightfield.o -MD -MP -MF $(DEPDIR)/libode_a-heightfield.Tpo -c -o libode_a-heightfield.o `test -f 'heightfield.cpp' || echo '$(srcdir)/'`heightfield.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-heightfield.Tpo $(DEPDIR)/libode_a-heightfield.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='heightfield.cpp' object='libode_a-heightfield.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-heightfield.o `test -f 'heightfield.cpp' || echo '$(srcdir)/'`heightfield.cpp
+
+libode_a-heightfield.obj: heightfield.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-heightfield.obj -MD -MP -MF $(DEPDIR)/libode_a-heightfield.Tpo -c -o libode_a-heightfield.obj `if test -f 'heightfield.cpp'; then $(CYGPATH_W) 'heightfield.cpp'; else $(CYGPATH_W) '$(srcdir)/heightfield.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-heightfield.Tpo $(DEPDIR)/libode_a-heightfield.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='heightfield.cpp' object='libode_a-heightfield.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-heightfield.obj `if test -f 'heightfield.cpp'; then $(CYGPATH_W) 'heightfield.cpp'; else $(CYGPATH_W) '$(srcdir)/heightfield.cpp'; fi`
+
+libode_a-collision_trimesh_gimpact.o: collision_trimesh_gimpact.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_gimpact.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_gimpact.Tpo -c -o libode_a-collision_trimesh_gimpact.o `test -f 'collision_trimesh_gimpact.cpp' || echo '$(srcdir)/'`collision_trimesh_gimpact.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_gimpact.Tpo $(DEPDIR)/libode_a-collision_trimesh_gimpact.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_gimpact.cpp' object='libode_a-collision_trimesh_gimpact.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_gimpact.o `test -f 'collision_trimesh_gimpact.cpp' || echo '$(srcdir)/'`collision_trimesh_gimpact.cpp
+
+libode_a-collision_trimesh_gimpact.obj: collision_trimesh_gimpact.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_gimpact.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_gimpact.Tpo -c -o libode_a-collision_trimesh_gimpact.obj `if test -f 'collision_trimesh_gimpact.cpp'; then $(CYGPATH_W) 'collision_trimesh_gimpact.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_gimpact.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_gimpact.Tpo $(DEPDIR)/libode_a-collision_trimesh_gimpact.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_gimpact.cpp' object='libode_a-collision_trimesh_gimpact.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_gimpact.obj `if test -f 'collision_trimesh_gimpact.cpp'; then $(CYGPATH_W) 'collision_trimesh_gimpact.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_gimpact.cpp'; fi`
+
+libode_a-collision_trimesh_trimesh.o: collision_trimesh_trimesh.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_trimesh.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_trimesh.Tpo -c -o libode_a-collision_trimesh_trimesh.o `test -f 'collision_trimesh_trimesh.cpp' || echo '$(srcdir)/'`collision_trimesh_trimesh.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_trimesh.Tpo $(DEPDIR)/libode_a-collision_trimesh_trimesh.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_trimesh.cpp' object='libode_a-collision_trimesh_trimesh.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_trimesh.o `test -f 'collision_trimesh_trimesh.cpp' || echo '$(srcdir)/'`collision_trimesh_trimesh.cpp
+
+libode_a-collision_trimesh_trimesh.obj: collision_trimesh_trimesh.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_trimesh.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_trimesh.Tpo -c -o libode_a-collision_trimesh_trimesh.obj `if test -f 'collision_trimesh_trimesh.cpp'; then $(CYGPATH_W) 'collision_trimesh_trimesh.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_trimesh.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_trimesh.Tpo $(DEPDIR)/libode_a-collision_trimesh_trimesh.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_trimesh.cpp' object='libode_a-collision_trimesh_trimesh.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_trimesh.obj `if test -f 'collision_trimesh_trimesh.cpp'; then $(CYGPATH_W) 'collision_trimesh_trimesh.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_trimesh.cpp'; fi`
+
+libode_a-collision_trimesh_sphere.o: collision_trimesh_sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_sphere.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_sphere.Tpo -c -o libode_a-collision_trimesh_sphere.o `test -f 'collision_trimesh_sphere.cpp' || echo '$(srcdir)/'`collision_trimesh_sphere.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_sphere.Tpo $(DEPDIR)/libode_a-collision_trimesh_sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_sphere.cpp' object='libode_a-collision_trimesh_sphere.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_sphere.o `test -f 'collision_trimesh_sphere.cpp' || echo '$(srcdir)/'`collision_trimesh_sphere.cpp
+
+libode_a-collision_trimesh_sphere.obj: collision_trimesh_sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_sphere.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_sphere.Tpo -c -o libode_a-collision_trimesh_sphere.obj `if test -f 'collision_trimesh_sphere.cpp'; then $(CYGPATH_W) 'collision_trimesh_sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_sphere.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_sphere.Tpo $(DEPDIR)/libode_a-collision_trimesh_sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_sphere.cpp' object='libode_a-collision_trimesh_sphere.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_sphere.obj `if test -f 'collision_trimesh_sphere.cpp'; then $(CYGPATH_W) 'collision_trimesh_sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_sphere.cpp'; fi`
+
+libode_a-collision_trimesh_ray.o: collision_trimesh_ray.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_ray.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_ray.Tpo -c -o libode_a-collision_trimesh_ray.o `test -f 'collision_trimesh_ray.cpp' || echo '$(srcdir)/'`collision_trimesh_ray.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_ray.Tpo $(DEPDIR)/libode_a-collision_trimesh_ray.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_ray.cpp' object='libode_a-collision_trimesh_ray.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_ray.o `test -f 'collision_trimesh_ray.cpp' || echo '$(srcdir)/'`collision_trimesh_ray.cpp
+
+libode_a-collision_trimesh_ray.obj: collision_trimesh_ray.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_ray.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_ray.Tpo -c -o libode_a-collision_trimesh_ray.obj `if test -f 'collision_trimesh_ray.cpp'; then $(CYGPATH_W) 'collision_trimesh_ray.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_ray.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_ray.Tpo $(DEPDIR)/libode_a-collision_trimesh_ray.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_ray.cpp' object='libode_a-collision_trimesh_ray.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_ray.obj `if test -f 'collision_trimesh_ray.cpp'; then $(CYGPATH_W) 'collision_trimesh_ray.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_ray.cpp'; fi`
+
+libode_a-collision_trimesh_opcode.o: collision_trimesh_opcode.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_opcode.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_opcode.Tpo -c -o libode_a-collision_trimesh_opcode.o `test -f 'collision_trimesh_opcode.cpp' || echo '$(srcdir)/'`collision_trimesh_opcode.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_opcode.Tpo $(DEPDIR)/libode_a-collision_trimesh_opcode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_opcode.cpp' object='libode_a-collision_trimesh_opcode.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_opcode.o `test -f 'collision_trimesh_opcode.cpp' || echo '$(srcdir)/'`collision_trimesh_opcode.cpp
+
+libode_a-collision_trimesh_opcode.obj: collision_trimesh_opcode.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_opcode.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_opcode.Tpo -c -o libode_a-collision_trimesh_opcode.obj `if test -f 'collision_trimesh_opcode.cpp'; then $(CYGPATH_W) 'collision_trimesh_opcode.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_opcode.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_opcode.Tpo $(DEPDIR)/libode_a-collision_trimesh_opcode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_opcode.cpp' object='libode_a-collision_trimesh_opcode.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_opcode.obj `if test -f 'collision_trimesh_opcode.cpp'; then $(CYGPATH_W) 'collision_trimesh_opcode.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_opcode.cpp'; fi`
+
+libode_a-collision_trimesh_box.o: collision_trimesh_box.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_box.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_box.Tpo -c -o libode_a-collision_trimesh_box.o `test -f 'collision_trimesh_box.cpp' || echo '$(srcdir)/'`collision_trimesh_box.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_box.Tpo $(DEPDIR)/libode_a-collision_trimesh_box.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_box.cpp' object='libode_a-collision_trimesh_box.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_box.o `test -f 'collision_trimesh_box.cpp' || echo '$(srcdir)/'`collision_trimesh_box.cpp
+
+libode_a-collision_trimesh_box.obj: collision_trimesh_box.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_box.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_box.Tpo -c -o libode_a-collision_trimesh_box.obj `if test -f 'collision_trimesh_box.cpp'; then $(CYGPATH_W) 'collision_trimesh_box.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_box.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_box.Tpo $(DEPDIR)/libode_a-collision_trimesh_box.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_box.cpp' object='libode_a-collision_trimesh_box.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_box.obj `if test -f 'collision_trimesh_box.cpp'; then $(CYGPATH_W) 'collision_trimesh_box.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_box.cpp'; fi`
+
+libode_a-collision_trimesh_ccylinder.o: collision_trimesh_ccylinder.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_ccylinder.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Tpo -c -o libode_a-collision_trimesh_ccylinder.o `test -f 'collision_trimesh_ccylinder.cpp' || echo '$(srcdir)/'`collision_trimesh_ccylinder.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Tpo $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_ccylinder.cpp' object='libode_a-collision_trimesh_ccylinder.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_ccylinder.o `test -f 'collision_trimesh_ccylinder.cpp' || echo '$(srcdir)/'`collision_trimesh_ccylinder.cpp
+
+libode_a-collision_trimesh_ccylinder.obj: collision_trimesh_ccylinder.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_ccylinder.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Tpo -c -o libode_a-collision_trimesh_ccylinder.obj `if test -f 'collision_trimesh_ccylinder.cpp'; then $(CYGPATH_W) 'collision_trimesh_ccylinder.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_ccylinder.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Tpo $(DEPDIR)/libode_a-collision_trimesh_ccylinder.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_ccylinder.cpp' object='libode_a-collision_trimesh_ccylinder.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_ccylinder.obj `if test -f 'collision_trimesh_ccylinder.cpp'; then $(CYGPATH_W) 'collision_trimesh_ccylinder.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_ccylinder.cpp'; fi`
+
+libode_a-collision_trimesh_distance.o: collision_trimesh_distance.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_distance.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_distance.Tpo -c -o libode_a-collision_trimesh_distance.o `test -f 'collision_trimesh_distance.cpp' || echo '$(srcdir)/'`collision_trimesh_distance.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_distance.Tpo $(DEPDIR)/libode_a-collision_trimesh_distance.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_distance.cpp' object='libode_a-collision_trimesh_distance.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_distance.o `test -f 'collision_trimesh_distance.cpp' || echo '$(srcdir)/'`collision_trimesh_distance.cpp
+
+libode_a-collision_trimesh_distance.obj: collision_trimesh_distance.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_distance.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_distance.Tpo -c -o libode_a-collision_trimesh_distance.obj `if test -f 'collision_trimesh_distance.cpp'; then $(CYGPATH_W) 'collision_trimesh_distance.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_distance.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_distance.Tpo $(DEPDIR)/libode_a-collision_trimesh_distance.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_distance.cpp' object='libode_a-collision_trimesh_distance.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_distance.obj `if test -f 'collision_trimesh_distance.cpp'; then $(CYGPATH_W) 'collision_trimesh_distance.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_distance.cpp'; fi`
+
+libode_a-collision_cylinder_trimesh.o: collision_cylinder_trimesh.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_trimesh.o -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_trimesh.Tpo -c -o libode_a-collision_cylinder_trimesh.o `test -f 'collision_cylinder_trimesh.cpp' || echo '$(srcdir)/'`collision_cylinder_trimesh.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_trimesh.Tpo $(DEPDIR)/libode_a-collision_cylinder_trimesh.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_trimesh.cpp' object='libode_a-collision_cylinder_trimesh.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_trimesh.o `test -f 'collision_cylinder_trimesh.cpp' || echo '$(srcdir)/'`collision_cylinder_trimesh.cpp
+
+libode_a-collision_cylinder_trimesh.obj: collision_cylinder_trimesh.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_cylinder_trimesh.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_cylinder_trimesh.Tpo -c -o libode_a-collision_cylinder_trimesh.obj `if test -f 'collision_cylinder_trimesh.cpp'; then $(CYGPATH_W) 'collision_cylinder_trimesh.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_trimesh.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_cylinder_trimesh.Tpo $(DEPDIR)/libode_a-collision_cylinder_trimesh.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_cylinder_trimesh.cpp' object='libode_a-collision_cylinder_trimesh.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_cylinder_trimesh.obj `if test -f 'collision_cylinder_trimesh.cpp'; then $(CYGPATH_W) 'collision_cylinder_trimesh.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_cylinder_trimesh.cpp'; fi`
+
+libode_a-collision_trimesh_plane.o: collision_trimesh_plane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_plane.o -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_plane.Tpo -c -o libode_a-collision_trimesh_plane.o `test -f 'collision_trimesh_plane.cpp' || echo '$(srcdir)/'`collision_trimesh_plane.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_plane.Tpo $(DEPDIR)/libode_a-collision_trimesh_plane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_plane.cpp' object='libode_a-collision_trimesh_plane.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_plane.o `test -f 'collision_trimesh_plane.cpp' || echo '$(srcdir)/'`collision_trimesh_plane.cpp
+
+libode_a-collision_trimesh_plane.obj: collision_trimesh_plane.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libode_a-collision_trimesh_plane.obj -MD -MP -MF $(DEPDIR)/libode_a-collision_trimesh_plane.Tpo -c -o libode_a-collision_trimesh_plane.obj `if test -f 'collision_trimesh_plane.cpp'; then $(CYGPATH_W) 'collision_trimesh_plane.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_plane.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libode_a-collision_trimesh_plane.Tpo $(DEPDIR)/libode_a-collision_trimesh_plane.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='collision_trimesh_plane.cpp' object='libode_a-collision_trimesh_plane.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libode_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libode_a-collision_trimesh_plane.obj `if test -f 'collision_trimesh_plane.cpp'; then $(CYGPATH_W) 'collision_trimesh_plane.cpp'; else $(CYGPATH_W) '$(srcdir)/collision_trimesh_plane.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(traplibdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \
+	clean-traplibPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-traplibPROGRAMS
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLIBRARIES uninstall-traplibPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLIBRARIES clean-noinstLIBRARIES clean-traplibPROGRAMS \
+	ctags distclean distclean-compile distclean-generic \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am \
+	install-libLIBRARIES install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip install-traplibPROGRAMS \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-libLIBRARIES uninstall-traplibPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/ode/src/array.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/array.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/array.cpp	(revision 216)
@@ -0,0 +1,80 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/memory.h>
+#include <ode/error.h>
+#include "array.h"
+
+
+static inline int roundUpToPowerOfTwo (int x)
+{
+  int i = 1;
+  while (i < x) i <<= 1;
+  return i;
+}
+
+
+void dArrayBase::_freeAll (int sizeofT)
+{
+  if (_data) {
+    if (_data == this+1) return;	// if constructLocalArray() was called
+    dFree (_data,_anum * sizeofT);
+  }
+}
+
+
+void dArrayBase::_setSize (int newsize, int sizeofT)
+{
+  if (newsize < 0) return;
+  if (newsize > _anum) {
+    if (_data == this+1) {
+      // this is a no-no, because constructLocalArray() was called
+      dDebug (0,"setSize() out of space in LOCAL array");
+    }
+    int newanum = roundUpToPowerOfTwo (newsize);
+    if (_data) _data = dRealloc (_data, _anum*sizeofT, newanum*sizeofT);
+    else _data = dAlloc (newanum*sizeofT);
+    _anum = newanum;
+  }
+  _size = newsize;
+}
+
+
+void * dArrayBase::operator new (size_t size)
+{
+  return dAlloc (size);
+}
+
+
+void dArrayBase::operator delete (void *ptr, size_t size)
+{
+  dFree (ptr,size);
+}
+
+
+void dArrayBase::constructLocalArray (int __anum)
+{
+  _size = 0;
+  _anum = __anum;
+  _data = this+1;
+}
Index: /code/branches/ode/ode-0.9/ode/src/array.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/array.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/array.h	(revision 216)
@@ -0,0 +1,135 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* this comes from the `reuse' library. copy any changes back to the source.
+ *
+ * Variable sized array template. The array is always stored in a contiguous
+ * chunk. The array can be resized. A size increase will cause more memory
+ * to be allocated, and may result in relocation of the array memory.
+ * A size decrease has no effect on the memory allocation.
+ *
+ * Array elements with constructors or destructors are not supported!
+ * But if you must have such elements, here's what to know/do:
+ *   - Bitwise copy is used when copying whole arrays.
+ *   - When copying individual items (via push(), insert() etc) the `='
+ *     (equals) operator is used. Thus you should define this operator to do
+ *     a bitwise copy. You should probably also define the copy constructor.
+ */
+
+
+#ifndef _ODE_ARRAY_H_
+#define _ODE_ARRAY_H_
+
+#include <ode/config.h>
+
+
+// this base class has no constructors or destructor, for your convenience.
+
+class dArrayBase {
+protected:
+  int _size;		// number of elements in `data'
+  int _anum;		// allocated number of elements in `data'
+  void *_data;		// array data
+
+  void _freeAll (int sizeofT);
+  void _setSize (int newsize, int sizeofT);
+  // set the array size to `newsize', allocating more memory if necessary.
+  // if newsize>_anum and is a power of two then this is guaranteed to
+  // set _size and _anum to newsize.
+
+public:
+  // not: dArrayBase () { _size=0; _anum=0; _data=0; }
+
+  int size() const { return _size; }
+  int allocatedSize() const { return _anum; }
+  void * operator new (size_t size);
+  void operator delete (void *ptr, size_t size);
+
+  void constructor() { _size=0; _anum=0; _data=0; }
+  // if this structure is allocated with malloc() instead of new, you can
+  // call this to set it up.
+
+  void constructLocalArray (int __anum);
+  // this helper function allows non-reallocating arrays to be constructed
+  // on the stack (or in the heap if necessary). this is something of a
+  // kludge and should be used with extreme care. this function acts like
+  // a constructor - it is called on uninitialized memory that will hold the
+  // Array structure and the data. __anum is the number of elements that
+  // are allocated. the memory MUST be allocated with size:
+  //   sizeof(ArrayBase) + __anum*sizeof(T)
+  // arrays allocated this way will never try to reallocate or free the
+  // memory - that's your job.
+};
+
+
+template <class T> class dArray : public dArrayBase {
+public:
+  void equals (const dArray<T> &x) {
+    setSize (x.size());
+    memcpy (_data,x._data,x._size * sizeof(T));
+  }
+
+  dArray () { constructor(); }
+  dArray (const dArray<T> &x) { constructor(); equals (x); }
+  ~dArray () { _freeAll(sizeof(T)); }
+  void setSize (int newsize) { _setSize (newsize,sizeof(T)); }
+  T *data() const { return (T*) _data; }
+  T & operator[] (int i) const { return ((T*)_data)[i]; }
+  void operator = (const dArray<T> &x) { equals (x); }
+
+  void push (const T item) {
+    if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T));
+    memcpy (&(((T*)_data)[_size-1]), &item, sizeof(T));
+  }
+
+  void swap (dArray<T> &x) {
+    int tmp1;
+    void *tmp2;
+    tmp1=_size; _size=x._size; x._size=tmp1;
+    tmp1=_anum; _anum=x._anum; x._anum=tmp1;
+    tmp2=_data; _data=x._data; x._data=tmp2;
+  }
+
+  // insert the item at the position `i'. if i<0 then add the item to the
+  // start, if i >= size then add the item to the end of the array.
+  void insert (int i, const T item) {
+    if (_size < _anum) _size++; else _setSize (_size+1,sizeof(T));
+    if (i >= (_size-1)) i = _size-1;	// add to end
+    else {
+      if (i < 0) i=0;			// add to start
+      int n = _size-1-i;
+      if (n>0) memmove (((T*)_data) + i+1, ((T*)_data) + i, n*sizeof(T));
+    }
+    ((T*)_data)[i] = item;
+  }
+
+  void remove (int i) {
+    if (i >= 0 && i < _size) {	// passing this test guarantees size>0
+      int n = _size-1-i;
+      if (n>0) memmove (((T*)_data) + i, ((T*)_data) + i+1, n*sizeof(T));
+      _size--;
+    }
+  }
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/box.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/box.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/box.cpp	(revision 216)
@@ -0,0 +1,847 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+standard ODE geometry primitives: public API and pairwise collision functions.
+
+the rule is that only the low level primitive collision functions should set
+dContactGeom::g1 and dContactGeom::g2.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// box public API
+
+dxBox::dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz) : dxGeom (space,1)
+{
+  dAASSERT (lx >= 0 && ly >= 0 && lz >= 0);
+  type = dBoxClass;
+  side[0] = lx;
+  side[1] = ly;
+  side[2] = lz;
+}
+
+
+void dxBox::computeAABB()
+{
+  const dMatrix3& R = final_posr->R;
+  const dVector3& pos = final_posr->pos;
+  
+  dReal xrange = REAL(0.5) * (dFabs (R[0] * side[0]) +
+    dFabs (R[1] * side[1]) + dFabs (R[2] * side[2]));
+  dReal yrange = REAL(0.5) * (dFabs (R[4] * side[0]) +
+    dFabs (R[5] * side[1]) + dFabs (R[6] * side[2]));
+  dReal zrange = REAL(0.5) * (dFabs (R[8] * side[0]) +
+    dFabs (R[9] * side[1]) + dFabs (R[10] * side[2]));
+  aabb[0] = pos[0] - xrange;
+  aabb[1] = pos[0] + xrange;
+  aabb[2] = pos[1] - yrange;
+  aabb[3] = pos[1] + yrange;
+  aabb[4] = pos[2] - zrange;
+  aabb[5] = pos[2] + zrange;
+}
+
+
+dGeomID dCreateBox (dSpaceID space, dReal lx, dReal ly, dReal lz)
+{
+  return new dxBox (space,lx,ly,lz);
+}
+
+
+void dGeomBoxSetLengths (dGeomID g, dReal lx, dReal ly, dReal lz)
+{
+  dUASSERT (g && g->type == dBoxClass,"argument not a box");
+  dAASSERT (lx > 0 && ly > 0 && lz > 0);
+  dxBox *b = (dxBox*) g;
+  b->side[0] = lx;
+  b->side[1] = ly;
+  b->side[2] = lz;
+  dGeomMoved (g);
+}
+
+
+void dGeomBoxGetLengths (dGeomID g, dVector3 result)
+{
+  dUASSERT (g && g->type == dBoxClass,"argument not a box");
+  dxBox *b = (dxBox*) g;
+  result[0] = b->side[0];
+  result[1] = b->side[1];
+  result[2] = b->side[2];
+}
+
+
+dReal dGeomBoxPointDepth (dGeomID g, dReal x, dReal y, dReal z)
+{
+  dUASSERT (g && g->type == dBoxClass,"argument not a box");
+  g->recomputePosr();
+  dxBox *b = (dxBox*) g;
+
+  // Set p = (x,y,z) relative to box center
+  //
+  // This will be (0,0,0) if the point is at (side[0]/2,side[1]/2,side[2]/2)
+
+  dVector3 p,q;
+
+  p[0] = x - b->final_posr->pos[0];
+  p[1] = y - b->final_posr->pos[1];
+  p[2] = z - b->final_posr->pos[2];
+
+  // Rotate p into box's coordinate frame, so we can
+  // treat the OBB as an AABB
+
+  dMULTIPLY1_331 (q,b->final_posr->R,p);
+
+  // Record distance from point to each successive box side, and see
+  // if the point is inside all six sides
+
+  dReal dist[6];
+  int   i;
+
+  bool inside = true;
+
+  for (i=0; i < 3; i++) {
+    dReal side = b->side[i] * REAL(0.5);
+
+    dist[i  ] = side - q[i];
+    dist[i+3] = side + q[i];
+
+    if ((dist[i] < 0) || (dist[i+3] < 0)) {
+      inside = false;
+    }
+  }
+
+  // If point is inside the box, the depth is the smallest positive distance
+  // to any side
+
+  if (inside) {
+    dReal smallest_dist = (dReal) (unsigned) -1;
+
+    for (i=0; i < 6; i++) {
+      if (dist[i] < smallest_dist) smallest_dist = dist[i];
+    }
+
+    return smallest_dist;
+  }
+
+  // Otherwise, if point is outside the box, the depth is the largest
+  // distance to any side.  This is an approximation to the 'proper'
+  // solution (the proper solution may be larger in some cases).
+
+  dReal largest_dist = 0;
+
+  for (i=0; i < 6; i++) {
+    if (dist[i] > largest_dist) largest_dist = dist[i];
+  }
+
+  return -largest_dist;
+}
+
+//****************************************************************************
+// box-box collision utility
+
+
+// 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 intersectRectQuad (dReal h[2], dReal p[8], dReal ret[16])
+{
+  // q (and r) contain nq (and nr) coordinate points for the current (and
+  // chopped) polygons
+  int nq=4,nr;
+  dReal buffer[16];
+  dReal *q = p;
+  dReal *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]
+      dReal *pq = q;
+      dReal *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;
+	  }
+	}
+	dReal *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(dReal));
+  return nr;
+}
+
+
+// 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 cullPoints (int n, dReal p[], int m, int i0, int iret[])
+{
+  // compute the centroid of the polygon in cx,cy
+  int i,j;
+  dReal a,cx,cy,q;
+  if (n==1) {
+    cx = p[0];
+    cy = p[1];
+  }
+  else if (n==2) {
+    cx = REAL(0.5)*(p[0] + p[2]);
+    cy = REAL(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 = dRecip(REAL(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
+  dReal A[8];
+  for (i=0; i<n; i++) A[i] = dAtan2(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 = dReal(j)*(2*M_PI/m) + A[i0];
+    if (a > M_PI) a -= 2*M_PI;
+    dReal maxdiff=1e9,diff;
+#ifndef dNODEBUG
+    *iret = i0;			// iret is not allowed to keep this value
+#endif
+    for (i=0; i<n; i++) {
+      if (avail[i]) {
+	diff = dFabs (A[i]-a);
+	if (diff > M_PI) diff = 2*M_PI - diff;
+	if (diff < maxdiff) {
+	  maxdiff = diff;
+	  *iret = i;
+	}
+      }
+    }
+#ifndef dNODEBUG
+    dIASSERT (*iret != i0);	// ensure iret got set
+#endif
+    avail[*iret] = 0;
+    iret++;
+  }
+}
+
+
+// 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.
+
+
+int dBoxBox (const dVector3 p1, const dMatrix3 R1,
+	     const dVector3 side1, const dVector3 p2,
+	     const dMatrix3 R2, const dVector3 side2,
+	     dVector3 normal, dReal *depth, int *return_code,
+	     int flags, dContactGeom *contact, int skip)
+{
+  const dReal fudge_factor = REAL(1.05);
+  dVector3 p,pp,normalC;
+  const dReal *normalR = 0;
+  dReal 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,expr1_val;
+  int i,j,invert_normal,code;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p[0] = p2[0] - p1[0];
+  p[1] = p2[1] - p1[1];
+  p[2] = p2[2] - p1[2];
+  dMULTIPLY1_331 (pp,R1,p);		// get pp = p relative to body 1
+
+  // get side lengths / 2
+  A[0] = side1[0]*REAL(0.5);
+  A[1] = side1[1]*REAL(0.5);
+  A[2] = side1[2]*REAL(0.5);
+  B[0] = side2[0]*REAL(0.5);
+  B[1] = side2[1]*REAL(0.5);
+  B[2] = side2[2]*REAL(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 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13);
+  Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23);
+  Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(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.
+
+  do {
+#define TST(expr1,expr2,norm,cc) \
+    expr1_val = (expr1); /* Avoid duplicate evaluation of expr1 */ \
+    s2 = dFabs(expr1_val) - (expr2); \
+    if (s2 > 0) return 0; \
+    if (s2 > s) { \
+      s = s2; \
+      normalR = norm; \
+      invert_normal = ((expr1_val) < 0); \
+      code = (cc); \
+	  if (flags & CONTACTS_UNIMPORTANT) break; \
+	}
+
+    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) \
+    expr1_val = (expr1); /* Avoid duplicate evaluation of expr1 */ \
+    s2 = dFabs(expr1_val) - (expr2); \
+    if (s2 > 0) return 0; \
+    l = dSqrt ((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_val) < 0); \
+        code = (cc); \
+        if (flags & CONTACTS_UNIMPORTANT) break; \
+	  } \
+	}
+
+    // 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
+  } while (0);
+
+  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
+    dVector3 pa;
+    dReal sign;
+    for (i=0; i<3; i++) pa[i] = p1[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R1+j) > 0) ? REAL(1.0) : REAL(-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
+    dVector3 pb;
+    for (i=0; i<3; i++) pb[i] = p2[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R2+j) > 0) ? REAL(-1.0) : REAL(1.0);
+      for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+    }
+
+    dReal alpha,beta;
+    dVector3 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;
+
+    for (i=0; i<3; i++) contact[0].pos[i] = REAL(0.5)*(pa[i]+pb[i]);
+    contact[0].depth = *depth;
+    *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 dReal *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.
+  dVector3 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] = dFabs (nr[0]);
+  anr[1] = dFabs (nr[1]);
+  anr[2] = dFabs (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
+  dVector3 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
+  dReal quad[8];	// 2D coordinate of incident face (x,y pairs)
+  dReal 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);
+  {
+    dReal k1 = m11*Sb[a1];
+    dReal k2 = m21*Sb[a1];
+    dReal k3 = m12*Sb[a2];
+    dReal 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
+  dReal rect[2];
+  rect[0] = Sa[code1];
+  rect[1] = Sa[code2];
+
+  // intersect the incident and reference faces
+  dReal ret[16];
+  int n = intersectRectQuad (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.
+  dReal point[3*8];		// penetrating contact points
+  dReal dep[8];			// depths for those points
+  dReal det1 = dRecip(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++) {
+    dReal k1 =  m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+    dReal 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 | CONTACTS_UNIMPORTANT) == (flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+		  break;
+	  }
+    }
+  }
+  if (cnum < 1) { 
+	  return 0;	// this should not happen, yet does at times (demo_plane2d single precision).
+  }
+
+  // we can't generate more contacts than we actually have
+  int maxc = flags & NUMC_MASK;
+  if (maxc > cnum) maxc = cnum;
+  if (maxc < 1) maxc = 1;	// Even though max count must not be zero this check is kept for backward compatibility as this is a public function
+
+  if (cnum <= maxc) {
+    // we have less contacts than we need, so we use them all
+    for (j=0; j < cnum; j++) {
+      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];
+    }
+  }
+  else {
+    dIASSERT(!(flags & CONTACTS_UNIMPORTANT)); // cnum should be generated not greater than maxc so that "then" clause is executed
+    // 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;
+    dReal maxdepth = dep[0];
+    for (i=1; i<cnum; i++) {
+      if (dep[i] > maxdepth) {
+	maxdepth = dep[i];
+	i1 = i;
+      }
+    }
+
+    int iret[8];
+    cullPoints (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]];
+    }
+    cnum = maxc;
+  }
+
+  *return_code = code;
+  return cnum;
+}
+
+
+
+int dCollideBoxBox (dxGeom *o1, dxGeom *o2, int flags,
+		    dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dBoxClass);
+  dIASSERT (o2->type == dBoxClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dVector3 normal;
+  dReal depth;
+  int code;
+  dxBox *b1 = (dxBox*) o1;
+  dxBox *b2 = (dxBox*) o2;
+  int num = dBoxBox (o1->final_posr->pos,o1->final_posr->R,b1->side, o2->final_posr->pos,o2->final_posr->R,b2->side,
+		     normal,&depth,&code,flags,contact,skip);
+  for (int i=0; i<num; i++) {
+    CONTACT(contact,i*skip)->normal[0] = -normal[0];
+    CONTACT(contact,i*skip)->normal[1] = -normal[1];
+    CONTACT(contact,i*skip)->normal[2] = -normal[2];
+    CONTACT(contact,i*skip)->g1 = o1;
+    CONTACT(contact,i*skip)->g2 = o2;
+  }
+  return num;
+}
+
+
+int dCollideBoxPlane (dxGeom *o1, dxGeom *o2,
+		      int flags, dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dBoxClass);
+  dIASSERT (o2->type == dPlaneClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxBox *box = (dxBox*) o1;
+  dxPlane *plane = (dxPlane*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+  int ret = 0;
+
+  //@@@ problem: using 4-vector (plane->p) as 3-vector (normal).
+  const dReal *R = o1->final_posr->R;		// rotation of box
+  const dReal *n = plane->p;		// normal vector
+
+  // project sides lengths along normal vector, get absolute values
+  dReal Q1 = dDOT14(n,R+0);
+  dReal Q2 = dDOT14(n,R+1);
+  dReal Q3 = dDOT14(n,R+2);
+  dReal A1 = box->side[0] * Q1;
+  dReal A2 = box->side[1] * Q2;
+  dReal A3 = box->side[2] * Q3;
+  dReal B1 = dFabs(A1);
+  dReal B2 = dFabs(A2);
+  dReal B3 = dFabs(A3);
+
+  // early exit test
+  dReal depth = plane->p[3] + REAL(0.5)*(B1+B2+B3) - dDOT(n,o1->final_posr->pos);
+  if (depth < 0) return 0;
+
+  // find number of contacts requested
+  int maxc = flags & NUMC_MASK;
+  // if (maxc < 1) maxc = 1; // an assertion is made on entry
+  if (maxc > 3) maxc = 3;	// not more than 3 contacts per box allowed
+
+  // find deepest point
+  dVector3 p;
+  p[0] = o1->final_posr->pos[0];
+  p[1] = o1->final_posr->pos[1];
+  p[2] = o1->final_posr->pos[2];
+#define FOO(i,op) \
+  p[0] op REAL(0.5)*box->side[i] * R[0+i]; \
+  p[1] op REAL(0.5)*box->side[i] * R[4+i]; \
+  p[2] op REAL(0.5)*box->side[i] * R[8+i];
+#define BAR(i,iinc) if (A ## iinc > 0) { FOO(i,-=) } else { FOO(i,+=) }
+  BAR(0,1);
+  BAR(1,2);
+  BAR(2,3);
+#undef FOO
+#undef BAR
+
+  // the deepest point is the first contact point
+  contact->pos[0] = p[0];
+  contact->pos[1] = p[1];
+  contact->pos[2] = p[2];
+  contact->normal[0] = n[0];
+  contact->normal[1] = n[1];
+  contact->normal[2] = n[2];
+  contact->depth = depth;
+  ret = 1;		// ret is number of contact points found so far
+  if (maxc == 1) goto done;
+
+  // get the second and third contact points by starting from `p' and going
+  // along the two sides with the smallest projected length.
+
+#define FOO(i,j,op) \
+  CONTACT(contact,i*skip)->pos[0] = p[0] op box->side[j] * R[0+j]; \
+  CONTACT(contact,i*skip)->pos[1] = p[1] op box->side[j] * R[4+j]; \
+  CONTACT(contact,i*skip)->pos[2] = p[2] op box->side[j] * R[8+j];
+#define BAR(ctact,side,sideinc) \
+  depth -= B ## sideinc; \
+  if (depth < 0) goto done; \
+  if (A ## sideinc > 0) { FOO(ctact,side,+); } else { FOO(ctact,side,-); } \
+  CONTACT(contact,ctact*skip)->depth = depth; \
+  ret++;
+
+  CONTACT(contact,skip)->normal[0] = n[0];
+  CONTACT(contact,skip)->normal[1] = n[1];
+  CONTACT(contact,skip)->normal[2] = n[2];
+  if (maxc == 3) {
+    CONTACT(contact,2*skip)->normal[0] = n[0];
+    CONTACT(contact,2*skip)->normal[1] = n[1];
+    CONTACT(contact,2*skip)->normal[2] = n[2];
+  }
+
+  if (B1 < B2) {
+    if (B3 < B1) goto use_side_3; else {
+      BAR(1,0,1);	// use side 1
+      if (maxc == 2) goto done;
+      if (B2 < B3) goto contact2_2; else goto contact2_3;
+    }
+  }
+  else {
+    if (B3 < B2) {
+      use_side_3:	// use side 3
+      BAR(1,2,3);
+      if (maxc == 2) goto done;
+      if (B1 < B2) goto contact2_1; else goto contact2_2;
+    }
+    else {
+      BAR(1,1,2);	// use side 2
+      if (maxc == 2) goto done;
+      if (B1 < B3) goto contact2_1; else goto contact2_3;
+    }
+  }
+
+  contact2_1: BAR(2,0,1); goto done;
+  contact2_2: BAR(2,1,2); goto done;
+  contact2_3: BAR(2,2,3); goto done;
+#undef FOO
+#undef BAR
+
+ done:
+  for (int i=0; i<ret; i++) {
+    CONTACT(contact,i*skip)->g1 = o1;
+    CONTACT(contact,i*skip)->g2 = o2;
+  }
+  return ret;
+}
Index: /code/branches/ode/ode-0.9/ode/src/capsule.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/capsule.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/capsule.cpp	(revision 216)
@@ -0,0 +1,369 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+standard ODE geometry primitives: public API and pairwise collision functions.
+
+the rule is that only the low level primitive collision functions should set
+dContactGeom::g1 and dContactGeom::g2.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// capped cylinder public API
+
+dxCapsule::dxCapsule (dSpaceID space, dReal _radius, dReal _length) :
+  dxGeom (space,1)
+{
+  dAASSERT (_radius > 0 && _length > 0);
+  type = dCapsuleClass;
+  radius = _radius;
+  lz = _length;
+}
+
+
+void dxCapsule::computeAABB()
+{
+  const dMatrix3& R = final_posr->R;
+  const dVector3& pos = final_posr->pos;
+  
+  dReal xrange = dFabs(R[2]  * lz) * REAL(0.5) + radius;
+  dReal yrange = dFabs(R[6]  * lz) * REAL(0.5) + radius;
+  dReal zrange = dFabs(R[10] * lz) * REAL(0.5) + radius;
+  aabb[0] = pos[0] - xrange;
+  aabb[1] = pos[0] + xrange;
+  aabb[2] = pos[1] - yrange;
+  aabb[3] = pos[1] + yrange;
+  aabb[4] = pos[2] - zrange;
+  aabb[5] = pos[2] + zrange;
+}
+
+
+dGeomID dCreateCapsule (dSpaceID space, dReal radius, dReal length)
+{
+  return new dxCapsule (space,radius,length);
+}
+
+
+void dGeomCapsuleSetParams (dGeomID g, dReal radius, dReal length)
+{
+  dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder");
+  dAASSERT (radius > 0 && length > 0);
+  dxCapsule *c = (dxCapsule*) g;
+  c->radius = radius;
+  c->lz = length;
+  dGeomMoved (g);
+}
+
+
+void dGeomCapsuleGetParams (dGeomID g, dReal *radius, dReal *length)
+{
+  dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder");
+  dxCapsule *c = (dxCapsule*) g;
+  *radius = c->radius;
+  *length = c->lz;
+}
+
+
+dReal dGeomCapsulePointDepth (dGeomID g, dReal x, dReal y, dReal z)
+{
+  dUASSERT (g && g->type == dCapsuleClass,"argument not a ccylinder");
+  g->recomputePosr();
+  dxCapsule *c = (dxCapsule*) g;
+
+  const dReal* R = g->final_posr->R;
+  const dReal* pos = g->final_posr->pos;
+  
+  dVector3 a;
+  a[0] = x - pos[0];
+  a[1] = y - pos[1];
+  a[2] = z - pos[2];
+  dReal beta = dDOT14(a,R+2);
+  dReal lz2 = c->lz*REAL(0.5);
+  if (beta < -lz2) beta = -lz2;
+  else if (beta > lz2) beta = lz2;
+  a[0] = c->final_posr->pos[0] + beta*R[0*4+2];
+  a[1] = c->final_posr->pos[1] + beta*R[1*4+2];
+  a[2] = c->final_posr->pos[2] + beta*R[2*4+2];
+  return c->radius -
+    dSqrt ((x-a[0])*(x-a[0]) + (y-a[1])*(y-a[1]) + (z-a[2])*(z-a[2]));
+}
+
+
+
+int dCollideCapsuleSphere (dxGeom *o1, dxGeom *o2, int flags,
+			     dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dCapsuleClass);
+  dIASSERT (o2->type == dSphereClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+  
+  dxCapsule *ccyl = (dxCapsule*) o1;
+  dxSphere *sphere = (dxSphere*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+
+  // find the point on the cylinder axis that is closest to the sphere
+  dReal alpha = 
+    o1->final_posr->R[2]  * (o2->final_posr->pos[0] - o1->final_posr->pos[0]) +
+    o1->final_posr->R[6]  * (o2->final_posr->pos[1] - o1->final_posr->pos[1]) +
+    o1->final_posr->R[10] * (o2->final_posr->pos[2] - o1->final_posr->pos[2]);
+  dReal lz2 = ccyl->lz * REAL(0.5);
+  if (alpha > lz2) alpha = lz2;
+  if (alpha < -lz2) alpha = -lz2;
+
+  // collide the spheres
+  dVector3 p;
+  p[0] = o1->final_posr->pos[0] + alpha * o1->final_posr->R[2];
+  p[1] = o1->final_posr->pos[1] + alpha * o1->final_posr->R[6];
+  p[2] = o1->final_posr->pos[2] + alpha * o1->final_posr->R[10];
+  return dCollideSpheres (p,ccyl->radius,o2->final_posr->pos,sphere->radius,contact);
+}
+
+
+int dCollideCapsuleBox (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dCapsuleClass);
+  dIASSERT (o2->type == dBoxClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxCapsule *cyl = (dxCapsule*) o1;
+  dxBox *box = (dxBox*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+
+  // get p1,p2 = cylinder axis endpoints, get radius
+  dVector3 p1,p2;
+  dReal clen = cyl->lz * REAL(0.5);
+  p1[0] = o1->final_posr->pos[0] + clen * o1->final_posr->R[2];
+  p1[1] = o1->final_posr->pos[1] + clen * o1->final_posr->R[6];
+  p1[2] = o1->final_posr->pos[2] + clen * o1->final_posr->R[10];
+  p2[0] = o1->final_posr->pos[0] - clen * o1->final_posr->R[2];
+  p2[1] = o1->final_posr->pos[1] - clen * o1->final_posr->R[6];
+  p2[2] = o1->final_posr->pos[2] - clen * o1->final_posr->R[10];
+  dReal radius = cyl->radius;
+
+  // copy out box center, rotation matrix, and side array
+  dReal *c = o2->final_posr->pos;
+  dReal *R = o2->final_posr->R;
+  const dReal *side = box->side;
+
+  // get the closest point between the cylinder axis and the box
+  dVector3 pl,pb;
+  dClosestLineBoxPoints (p1,p2,c,R,side,pl,pb);
+
+  // generate contact point
+  return dCollideSpheres (pl,radius,pb,0,contact);
+}
+
+
+int dCollideCapsuleCapsule (dxGeom *o1, dxGeom *o2,
+				int flags, dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dCapsuleClass);
+  dIASSERT (o2->type == dCapsuleClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  int i;
+  const dReal tolerance = REAL(1e-5);
+
+  dxCapsule *cyl1 = (dxCapsule*) o1;
+  dxCapsule *cyl2 = (dxCapsule*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+
+  // copy out some variables, for convenience
+  dReal lz1 = cyl1->lz * REAL(0.5);
+  dReal lz2 = cyl2->lz * REAL(0.5);
+  dReal *pos1 = o1->final_posr->pos;
+  dReal *pos2 = o2->final_posr->pos;
+  dReal axis1[3],axis2[3];
+  axis1[0] = o1->final_posr->R[2];
+  axis1[1] = o1->final_posr->R[6];
+  axis1[2] = o1->final_posr->R[10];
+  axis2[0] = o2->final_posr->R[2];
+  axis2[1] = o2->final_posr->R[6];
+  axis2[2] = o2->final_posr->R[10];
+
+  // if the cylinder axes are close to parallel, we'll try to detect up to
+  // two contact points along the body of the cylinder. if we can't find any
+  // points then we'll fall back to the closest-points algorithm. note that
+  // we are not treating this special case for reasons of degeneracy, but
+  // because we want two contact points in some situations. the closet-points
+  // algorithm is robust in all casts, but it can return only one contact.
+
+  dVector3 sphere1,sphere2;
+  dReal a1a2 = dDOT (axis1,axis2);
+  dReal det = REAL(1.0)-a1a2*a1a2;
+  if (det < tolerance) {
+    // the cylinder axes (almost) parallel, so we will generate up to two
+    // contacts. alpha1 and alpha2 (line position parameters) are related by:
+    //       alpha2 =   alpha1 + (pos1-pos2)'*axis1   (if axis1==axis2)
+    //    or alpha2 = -(alpha1 + (pos1-pos2)'*axis1)  (if axis1==-axis2)
+    // first compute where the two cylinders overlap in alpha1 space:
+    if (a1a2 < 0) {
+      axis2[0] = -axis2[0];
+      axis2[1] = -axis2[1];
+      axis2[2] = -axis2[2];
+    }
+    dReal q[3];
+    for (i=0; i<3; i++) q[i] = pos1[i]-pos2[i];
+    dReal k = dDOT (axis1,q);
+    dReal a1lo = -lz1;
+    dReal a1hi = lz1;
+    dReal a2lo = -lz2 - k;
+    dReal a2hi = lz2 - k;
+    dReal lo = (a1lo > a2lo) ? a1lo : a2lo;
+    dReal hi = (a1hi < a2hi) ? a1hi : a2hi;
+    if (lo <= hi) {
+      int num_contacts = flags & NUMC_MASK;
+      if (num_contacts >= 2 && lo < hi) {
+	// generate up to two contacts. if one of those contacts is
+	// not made, fall back on the one-contact strategy.
+	for (i=0; i<3; i++) sphere1[i] = pos1[i] + lo*axis1[i];
+	for (i=0; i<3; i++) sphere2[i] = pos2[i] + (lo+k)*axis2[i];
+	int n1 = dCollideSpheres (sphere1,cyl1->radius,
+				  sphere2,cyl2->radius,contact);
+	if (n1) {
+	  for (i=0; i<3; i++) sphere1[i] = pos1[i] + hi*axis1[i];
+	  for (i=0; i<3; i++) sphere2[i] = pos2[i] + (hi+k)*axis2[i];
+	  dContactGeom *c2 = CONTACT(contact,skip);
+	  int n2 = dCollideSpheres (sphere1,cyl1->radius,
+				    sphere2,cyl2->radius, c2);
+	  if (n2) {
+	    c2->g1 = o1;
+	    c2->g2 = o2;
+	    return 2;
+	  }
+	}
+      }
+
+      // just one contact to generate, so put it in the middle of
+      // the range
+      dReal alpha1 = (lo + hi) * REAL(0.5);
+      dReal alpha2 = alpha1 + k;
+      for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
+      for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
+      return dCollideSpheres (sphere1,cyl1->radius,
+			      sphere2,cyl2->radius,contact);
+    }
+  }
+	  
+  // use the closest point algorithm
+  dVector3 a1,a2,b1,b2;
+  a1[0] = o1->final_posr->pos[0] + axis1[0]*lz1;
+  a1[1] = o1->final_posr->pos[1] + axis1[1]*lz1;
+  a1[2] = o1->final_posr->pos[2] + axis1[2]*lz1;
+  a2[0] = o1->final_posr->pos[0] - axis1[0]*lz1;
+  a2[1] = o1->final_posr->pos[1] - axis1[1]*lz1;
+  a2[2] = o1->final_posr->pos[2] - axis1[2]*lz1;
+  b1[0] = o2->final_posr->pos[0] + axis2[0]*lz2;
+  b1[1] = o2->final_posr->pos[1] + axis2[1]*lz2;
+  b1[2] = o2->final_posr->pos[2] + axis2[2]*lz2;
+  b2[0] = o2->final_posr->pos[0] - axis2[0]*lz2;
+  b2[1] = o2->final_posr->pos[1] - axis2[1]*lz2;
+  b2[2] = o2->final_posr->pos[2] - axis2[2]*lz2;
+
+  dClosestLineSegmentPoints (a1,a2,b1,b2,sphere1,sphere2);
+  return dCollideSpheres (sphere1,cyl1->radius,sphere2,cyl2->radius,contact);
+}
+
+
+int dCollideCapsulePlane (dxGeom *o1, dxGeom *o2, int flags,
+			    dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dCapsuleClass);
+  dIASSERT (o2->type == dPlaneClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxCapsule *ccyl = (dxCapsule*) o1;
+  dxPlane *plane = (dxPlane*) o2;
+
+  // collide the deepest capping sphere with the plane
+  dReal sign = (dDOT14 (plane->p,o1->final_posr->R+2) > 0) ? REAL(-1.0) : REAL(1.0);
+  dVector3 p;
+  p[0] = o1->final_posr->pos[0] + o1->final_posr->R[2]  * ccyl->lz * REAL(0.5) * sign;
+  p[1] = o1->final_posr->pos[1] + o1->final_posr->R[6]  * ccyl->lz * REAL(0.5) * sign;
+  p[2] = o1->final_posr->pos[2] + o1->final_posr->R[10] * ccyl->lz * REAL(0.5) * sign;
+
+  dReal k = dDOT (p,plane->p);
+  dReal depth = plane->p[3] - k + ccyl->radius;
+  if (depth < 0) return 0;
+  contact->normal[0] = plane->p[0];
+  contact->normal[1] = plane->p[1];
+  contact->normal[2] = plane->p[2];
+  contact->pos[0] = p[0] - plane->p[0] * ccyl->radius;
+  contact->pos[1] = p[1] - plane->p[1] * ccyl->radius;
+  contact->pos[2] = p[2] - plane->p[2] * ccyl->radius;
+  contact->depth = depth;
+
+  int ncontacts = 1;
+  if ((flags & NUMC_MASK) >= 2) {
+    // collide the other capping sphere with the plane
+    p[0] = o1->final_posr->pos[0] - o1->final_posr->R[2]  * ccyl->lz * REAL(0.5) * sign;
+    p[1] = o1->final_posr->pos[1] - o1->final_posr->R[6]  * ccyl->lz * REAL(0.5) * sign;
+    p[2] = o1->final_posr->pos[2] - o1->final_posr->R[10] * ccyl->lz * REAL(0.5) * sign;
+
+    k = dDOT (p,plane->p);
+    depth = plane->p[3] - k + ccyl->radius;
+    if (depth >= 0) {
+      dContactGeom *c2 = CONTACT(contact,skip);
+      c2->normal[0] = plane->p[0];
+      c2->normal[1] = plane->p[1];
+      c2->normal[2] = plane->p[2];
+      c2->pos[0] = p[0] - plane->p[0] * ccyl->radius;
+      c2->pos[1] = p[1] - plane->p[1] * ccyl->radius;
+      c2->pos[2] = p[2] - plane->p[2] * ccyl->radius;
+      c2->depth = depth;
+      ncontacts = 2;
+    }
+  }
+
+  for (int i=0; i < ncontacts; i++) {
+    CONTACT(contact,i*skip)->g1 = o1;
+    CONTACT(contact,i*skip)->g2 = o2;
+  }
+  return ncontacts;
+}
+
Index: /code/branches/ode/ode-0.9/ode/src/collision_cylinder_box.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_cylinder_box.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_cylinder_box.cpp	(revision 216)
@@ -0,0 +1,1007 @@
+/*************************************************************************
+*                                                                       *
+* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+*                                                                       *
+* This library is free software; you can redistribute it and/or         *
+* modify it under the terms of EITHER:                                  *
+*   (1) The GNU Lesser General Public License as published by the Free  *
+*       Software Foundation; either version 2.1 of the License, or (at  *
+*       your option) any later version. The text of the GNU Lesser      *
+*       General Public License is included with this library in the     *
+*       file LICENSE.TXT.                                               *
+*   (2) The BSD-style license that is included with this library in     *
+*       the file LICENSE-BSD.TXT.                                       *
+*                                                                       *
+* This library is distributed in the hope that it will be useful,       *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+*                                                                       *
+*************************************************************************/
+
+/*
+ *	Cylinder-box collider by Alen Ladavac
+ *  Ported to ODE by Nguyen Binh
+ */
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+
+static const int MAX_CYLBOX_CLIP_POINTS  = 16;
+static const int nCYLINDER_AXIS			 = 2;
+// Number of segment of cylinder base circle.
+// Must be divisible by 4.
+static const int nCYLINDER_SEGMENT		 = 8;
+
+#define MAX_FLOAT	dInfinity
+
+// Data that passed through the collider's functions
+typedef struct _sCylinderBoxData
+{
+	// cylinder parameters
+	dMatrix3			mCylinderRot;
+	dVector3			vCylinderPos;
+	dVector3			vCylinderAxis;
+	dReal				fCylinderRadius;
+	dReal				fCylinderSize;
+	dVector3			avCylinderNormals[nCYLINDER_SEGMENT];
+	
+	// box parameters
+
+	dMatrix3			mBoxRot;
+	dVector3			vBoxPos;
+	dVector3			vBoxHalfSize;
+	// box vertices array : 8 vertices
+	dVector3			avBoxVertices[8];
+
+	// global collider data
+	dVector3			vDiff;			
+	dVector3			vNormal;
+	dReal				fBestDepth;
+	dReal				fBestrb;
+	dReal				fBestrc;
+	int					iBestAxis;
+
+	// contact data
+	dVector3			vEp0, vEp1;
+	dReal				fDepth0, fDepth1;
+
+	// ODE stuff
+	dGeomID				gBox;
+	dGeomID				gCylinder;
+	dContactGeom*		gContact;
+	int					iFlags;
+	int					iSkip;
+	int					nContacts;
+	
+} sCylinderBoxData;
+
+
+// initialize collision data
+void _cldInitCylinderBox(sCylinderBoxData& cData) 
+{
+	// get cylinder position, orientation
+	const dReal* pRotCyc = dGeomGetRotation(cData.gCylinder); 
+	dMatrix3Copy(pRotCyc,cData.mCylinderRot);
+
+	const dVector3* pPosCyc = (const dVector3*)dGeomGetPosition(cData.gCylinder);
+	dVector3Copy(*pPosCyc,cData.vCylinderPos);
+
+	dMat3GetCol(cData.mCylinderRot,nCYLINDER_AXIS,cData.vCylinderAxis);
+	
+	// get cylinder radius and size
+	dGeomCylinderGetParams(cData.gCylinder,&cData.fCylinderRadius,&cData.fCylinderSize);
+
+	// get box position, orientation, size
+	const dReal* pRotBox = dGeomGetRotation(cData.gBox);
+	dMatrix3Copy(pRotBox,cData.mBoxRot);
+	const dVector3* pPosBox  = (const dVector3*)dGeomGetPosition(cData.gBox);
+	dVector3Copy(*pPosBox,cData.vBoxPos);
+
+	dGeomBoxGetLengths(cData.gBox, cData.vBoxHalfSize);
+	cData.vBoxHalfSize[0] *= REAL(0.5);
+	cData.vBoxHalfSize[1] *= REAL(0.5);
+	cData.vBoxHalfSize[2] *= REAL(0.5);
+
+	// vertex 0
+	cData.avBoxVertices[0][0] = -cData.vBoxHalfSize[0];
+	cData.avBoxVertices[0][1] =  cData.vBoxHalfSize[1];
+	cData.avBoxVertices[0][2] = -cData.vBoxHalfSize[2];
+
+	// vertex 1
+	cData.avBoxVertices[1][0] =  cData.vBoxHalfSize[0];
+	cData.avBoxVertices[1][1] =  cData.vBoxHalfSize[1];
+	cData.avBoxVertices[1][2] = -cData.vBoxHalfSize[2];
+
+	// vertex 2
+	cData.avBoxVertices[2][0] = -cData.vBoxHalfSize[0];
+	cData.avBoxVertices[2][1] = -cData.vBoxHalfSize[1];
+	cData.avBoxVertices[2][2] = -cData.vBoxHalfSize[2];
+
+	// vertex 3
+	cData.avBoxVertices[3][0] =  cData.vBoxHalfSize[0];
+	cData.avBoxVertices[3][1] = -cData.vBoxHalfSize[1];
+	cData.avBoxVertices[3][2] = -cData.vBoxHalfSize[2];
+
+	// vertex 4
+	cData.avBoxVertices[4][0] =  cData.vBoxHalfSize[0];
+	cData.avBoxVertices[4][1] =  cData.vBoxHalfSize[1];
+	cData.avBoxVertices[4][2] =  cData.vBoxHalfSize[2];
+
+	// vertex 5
+	cData.avBoxVertices[5][0] =  cData.vBoxHalfSize[0];
+	cData.avBoxVertices[5][1] = -cData.vBoxHalfSize[1];
+	cData.avBoxVertices[5][2] =  cData.vBoxHalfSize[2];
+
+	// vertex 6
+	cData.avBoxVertices[6][0] = -cData.vBoxHalfSize[0];
+	cData.avBoxVertices[6][1] = -cData.vBoxHalfSize[1];
+	cData.avBoxVertices[6][2] =  cData.vBoxHalfSize[2];
+
+	// vertex 7
+	cData.avBoxVertices[7][0] = -cData.vBoxHalfSize[0];
+	cData.avBoxVertices[7][1] =  cData.vBoxHalfSize[1];
+	cData.avBoxVertices[7][2] =  cData.vBoxHalfSize[2];
+
+	// temp index
+	int i = 0;
+	dVector3	vTempBoxVertices[8];
+	// transform vertices in absolute space
+	for(i=0; i < 8; i++) 
+	{
+		dMultiplyMat3Vec3(cData.mBoxRot,cData.avBoxVertices[i], vTempBoxVertices[i]);
+		dVector3Add(vTempBoxVertices[i], cData.vBoxPos, cData.avBoxVertices[i]);
+	}
+
+	// find relative position
+	dVector3Subtract(cData.vCylinderPos,cData.vBoxPos,cData.vDiff);
+	cData.fBestDepth = MAX_FLOAT;
+	cData.vNormal[0] = REAL(0.0);
+	cData.vNormal[1] = REAL(0.0);
+	cData.vNormal[2] = REAL(0.0);
+
+	// calculate basic angle for nCYLINDER_SEGMENT-gon
+	dReal fAngle = M_PI/nCYLINDER_SEGMENT;
+
+	// calculate angle increment
+	dReal fAngleIncrement = fAngle * REAL(2.0); 
+
+	// calculate nCYLINDER_SEGMENT-gon points
+	for(i = 0; i < nCYLINDER_SEGMENT; i++) 
+	{
+		cData.avCylinderNormals[i][0] = -dCos(fAngle);
+		cData.avCylinderNormals[i][1] = -dSin(fAngle);
+		cData.avCylinderNormals[i][2] = 0;
+
+		fAngle += fAngleIncrement;
+	}
+
+	cData.fBestrb		= 0;
+	cData.fBestrc		= 0;
+	cData.iBestAxis		= 0;
+	cData.nContacts		= 0;
+
+}
+
+// test for given separating axis
+int _cldTestAxis(sCylinderBoxData& cData, dVector3& vInputNormal, int iAxis ) 
+{
+	// check length of input normal
+	dReal fL = dVector3Length(vInputNormal);
+	// if not long enough
+	if ( fL < REAL(1e-5) ) 
+	{
+		// do nothing
+		return 1;
+	}
+
+	// otherwise make it unit for sure
+	dNormalize3(vInputNormal);
+
+	// project box and Cylinder on mAxis
+	dReal fdot1 = dVector3Dot(cData.vCylinderAxis, vInputNormal);
+
+	dReal frc;
+
+	if (fdot1 > REAL(1.0)) 
+	{
+		fdot1 = REAL(1.0);
+		frc = dFabs(cData.fCylinderSize*REAL(0.5));
+	}
+
+	// project box and capsule on iAxis
+	frc = dFabs( fdot1 * (cData.fCylinderSize*REAL(0.5))) + cData.fCylinderRadius * dSqrt(REAL(1.0)-(fdot1*fdot1));
+
+	dVector3	vTemp1;
+	dReal frb = REAL(0.0);
+
+	dMat3GetCol(cData.mBoxRot,0,vTemp1);
+	frb = dFabs(dVector3Dot(vTemp1,vInputNormal))*cData.vBoxHalfSize[0];
+
+	dMat3GetCol(cData.mBoxRot,1,vTemp1);
+	frb += dFabs(dVector3Dot(vTemp1,vInputNormal))*cData.vBoxHalfSize[1];
+
+	dMat3GetCol(cData.mBoxRot,2,vTemp1);
+	frb += dFabs(dVector3Dot(vTemp1,vInputNormal))*cData.vBoxHalfSize[2];
+	
+	// project their distance on separating axis
+	dReal fd  = dVector3Dot(cData.vDiff,vInputNormal);
+
+	// if they do not overlap exit, we have no intersection
+	if ( dFabs(fd) > frc+frb )
+	{ 
+		return 0; 
+	} 
+
+	// get depth
+	dReal fDepth = - dFabs(fd) + (frc+frb);
+
+	// get maximum depth
+	if ( fDepth < cData.fBestDepth ) 
+	{
+		cData.fBestDepth = fDepth;
+		dVector3Copy(vInputNormal,cData.vNormal);
+		cData.iBestAxis  = iAxis;
+		cData.fBestrb    = frb;
+		cData.fBestrc    = frc;
+
+		// flip normal if interval is wrong faced
+		if (fd > 0) 
+		{ 
+			dVector3Inv(cData.vNormal);
+		}
+	}
+
+	return 1;
+}
+
+
+// check for separation between box edge and cylinder circle edge
+int _cldTestEdgeCircleAxis( sCylinderBoxData& cData,
+							const dVector3 &vCenterPoint, 
+							const dVector3 &vVx0, const dVector3 &vVx1, 
+							int iAxis ) 
+{
+	// calculate direction of edge
+	dVector3 vDirEdge;
+	dVector3Subtract(vVx1,vVx0,vDirEdge);
+	dNormalize3(vDirEdge);
+	// starting point of edge 
+	dVector3 vEStart;
+	dVector3Copy(vVx0,vEStart);;
+
+	// calculate angle cosine between cylinder axis and edge
+	dReal fdot2 = dVector3Dot (vDirEdge,cData.vCylinderAxis);
+
+	// if edge is perpendicular to cylinder axis
+	if(dFabs(fdot2) < REAL(1e-5)) 
+	{
+		// this can't be separating axis, because edge is parallel to circle plane
+		return 1;
+	}
+
+	// find point of intersection between edge line and circle plane
+	dVector3 vTemp1;
+	dVector3Subtract(vCenterPoint,vEStart,vTemp1);
+	dReal fdot1 = dVector3Dot(vTemp1,cData.vCylinderAxis);
+	dVector3 vpnt;
+	vpnt[0]= vEStart[0] + vDirEdge[0] * (fdot1/fdot2);
+	vpnt[1]= vEStart[1] + vDirEdge[1] * (fdot1/fdot2);
+	vpnt[2]= vEStart[2] + vDirEdge[2] * (fdot1/fdot2);
+
+	// find tangent vector on circle with same center (vCenterPoint) that
+	// touches point of intersection (vpnt)
+	dVector3 vTangent;
+	dVector3Subtract(vCenterPoint,vpnt,vTemp1);
+	dVector3Cross(vTemp1,cData.vCylinderAxis,vTangent);
+	
+	// find vector orthogonal both to tangent and edge direction
+	dVector3 vAxis;
+	dVector3Cross(vTangent,vDirEdge,vAxis);
+
+	// use that vector as separating axis
+	return _cldTestAxis( cData, vAxis, iAxis );
+}
+
+// Test separating axis for collision
+int _cldTestSeparatingAxes(sCylinderBoxData& cData) 
+{
+	// reset best axis
+	cData.fBestDepth = MAX_FLOAT;
+	cData.iBestAxis = 0;
+	cData.fBestrb = 0;
+	cData.fBestrc = 0;
+	cData.nContacts = 0;
+
+	dVector3  vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)};
+
+	// Epsilon value for checking axis vector length 
+	const dReal fEpsilon = REAL(1e-6);
+
+	// axis A0
+	dMat3GetCol(cData.mBoxRot, 0 , vAxis);
+	if (!_cldTestAxis( cData, vAxis, 1 )) 
+	{
+		return 0;
+	}
+
+	// axis A1
+	dMat3GetCol(cData.mBoxRot, 1 , vAxis);
+	if (!_cldTestAxis( cData, vAxis, 2 )) 
+	{
+		return 0;
+	}
+
+	// axis A2
+	dMat3GetCol(cData.mBoxRot, 2 , vAxis);
+	if (!_cldTestAxis( cData, vAxis, 3 )) 
+	{
+		return 0;
+	}
+
+	// axis C - Cylinder Axis
+	//vAxis = vCylinderAxis;
+	dVector3Copy(cData.vCylinderAxis , vAxis);
+	if (!_cldTestAxis( cData, vAxis, 4 )) 
+	{
+		return 0;
+	}
+
+	// axis CxA0
+	//vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 0 ));
+	dVector3CrossMat3Col(cData.mBoxRot, 0 ,cData.vCylinderAxis, vAxis);
+	if(dVector3Length2( vAxis ) > fEpsilon ) 
+	{
+		if (!_cldTestAxis( cData, vAxis, 5 ))
+		{
+			return 0;
+		}
+	}
+
+	// axis CxA1
+	//vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 1 ));
+	dVector3CrossMat3Col(cData.mBoxRot, 1 ,cData.vCylinderAxis, vAxis);
+	if(dVector3Length2( vAxis ) > fEpsilon ) 
+	{
+		if (!_cldTestAxis( cData, vAxis, 6 )) 
+		{
+			return 0;
+		}
+	}
+
+	// axis CxA2
+	//vAxis = ( vCylinderAxis cross mthGetColM33f( mBoxRot, 2 ));
+	dVector3CrossMat3Col(cData.mBoxRot, 2 ,cData.vCylinderAxis, vAxis);
+	if(dVector3Length2( vAxis ) > fEpsilon ) 
+	{
+		if (!_cldTestAxis( cData, vAxis, 7 ))
+		{
+			return 0;
+		}
+	}
+
+	int i = 0;
+	dVector3	vTemp1;
+	dVector3	vTemp2;
+	// here we check box's vertices axis
+	for(i=0; i< 8; i++) 
+	{
+		//vAxis = ( vCylinderAxis cross (cData.avBoxVertices[i] - vCylinderPos));
+		dVector3Subtract(cData.avBoxVertices[i],cData.vCylinderPos,vTemp1);
+		dVector3Cross(cData.vCylinderAxis,vTemp1,vTemp2);
+		//vAxis = ( vCylinderAxis cross vAxis );
+		dVector3Cross(cData.vCylinderAxis,vTemp2,vAxis);
+		if(dVector3Length2( vAxis ) > fEpsilon ) 
+		{
+			if (!_cldTestAxis( cData, vAxis, 8 + i ))
+			{
+				return 0;
+			}
+		}
+	}
+
+	// ************************************
+	// this is defined for first 12 axes
+	// normal of plane that contains top circle of cylinder
+	// center of top circle of cylinder
+	dVector3 vcc;
+	vcc[0] = (cData.vCylinderPos)[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+	vcc[1] = (cData.vCylinderPos)[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+	vcc[2] = (cData.vCylinderPos)[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+	// ************************************
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[0], 16)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[3], 17)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[3], 18))
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[0], 19)) 
+	{
+		return 0;
+	}
+
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[1], 20))
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[7], 21))
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[0], cData.avBoxVertices[7], 22)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[3], 23)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[6], 24)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[6], 25)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[5], 26)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[6], cData.avBoxVertices[7], 27)) 
+	{
+		return 0;
+	}
+
+	// ************************************
+	// this is defined for second 12 axes
+	// normal of plane that contains bottom circle of cylinder
+	// center of bottom circle of cylinder
+	//	vcc = vCylinderPos - vCylinderAxis*(fCylinderSize*REAL(0.5));
+	vcc[0] = (cData.vCylinderPos)[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+	vcc[1] = (cData.vCylinderPos)[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+	vcc[2] = (cData.vCylinderPos)[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+	// ************************************
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[0], 28)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[1], cData.avBoxVertices[3], 29)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[3], 30)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[0], 31)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[1], 32)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[7], 33)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[0], cData.avBoxVertices[7], 34)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[3], 35)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[5], cData.avBoxVertices[6], 36)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[2], cData.avBoxVertices[6], 37)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[4], cData.avBoxVertices[5], 38)) 
+	{
+		return 0;
+	}
+
+	if (!_cldTestEdgeCircleAxis( cData, vcc, cData.avBoxVertices[6], cData.avBoxVertices[7], 39)) 
+	{
+		return 0;
+	}
+
+	return 1;
+}
+
+int _cldClipCylinderToBox(sCylinderBoxData& cData)
+{
+	dIASSERT(cData.nContacts != (cData.iFlags & NUMC_MASK));
+
+	// calculate that vector perpendicular to cylinder axis which closes lowest angle with collision normal
+	dVector3 vN;
+	dReal fTemp1 = dVector3Dot(cData.vCylinderAxis,cData.vNormal);
+	vN[0]	=	cData.vNormal[0] - cData.vCylinderAxis[0]*fTemp1;
+	vN[1]	=	cData.vNormal[1] - cData.vCylinderAxis[1]*fTemp1;
+	vN[2]	=	cData.vNormal[2] - cData.vCylinderAxis[2]*fTemp1;
+
+	// normalize that vector
+	dNormalize3(vN);
+
+	// translate cylinder end points by the vector
+	dVector3 vCposTrans;
+	vCposTrans[0] = cData.vCylinderPos[0] + vN[0] * cData.fCylinderRadius;
+	vCposTrans[1] = cData.vCylinderPos[1] + vN[1] * cData.fCylinderRadius;
+	vCposTrans[2] = cData.vCylinderPos[2] + vN[2] * cData.fCylinderRadius;
+
+	cData.vEp0[0]  = vCposTrans[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+	cData.vEp0[1]  = vCposTrans[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+	cData.vEp0[2]  = vCposTrans[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+
+	cData.vEp1[0]  = vCposTrans[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+	cData.vEp1[1]  = vCposTrans[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+	cData.vEp1[2]  = vCposTrans[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+
+	// transform edge points in box space
+	cData.vEp0[0] -= cData.vBoxPos[0];
+	cData.vEp0[1] -= cData.vBoxPos[1];
+	cData.vEp0[2] -= cData.vBoxPos[2];
+
+	cData.vEp1[0] -= cData.vBoxPos[0];
+	cData.vEp1[1] -= cData.vBoxPos[1];
+	cData.vEp1[2] -= cData.vBoxPos[2];
+
+	dVector3 vTemp1;
+	// clip the edge to box 
+	dVector4 plPlane;
+	// plane 0 +x
+	dMat3GetCol(cData.mBoxRot,0,vTemp1);
+	dConstructPlane(vTemp1,cData.vBoxHalfSize[0],plPlane);
+	if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane )) 
+	{ 
+		return 0; 
+	}
+
+	// plane 1 +y
+	dMat3GetCol(cData.mBoxRot,1,vTemp1);
+	dConstructPlane(vTemp1,cData.vBoxHalfSize[1],plPlane);
+	if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane )) 
+	{ 
+		return 0; 
+	}
+
+	// plane 2 +z
+	dMat3GetCol(cData.mBoxRot,2,vTemp1);
+	dConstructPlane(vTemp1,cData.vBoxHalfSize[2],plPlane);
+	if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane )) 
+	{ 
+		return 0; 
+	}
+
+	// plane 3 -x
+	dMat3GetCol(cData.mBoxRot,0,vTemp1);
+	dVector3Inv(vTemp1);
+	dConstructPlane(vTemp1,cData.vBoxHalfSize[0],plPlane);
+	if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane )) 
+	{ 
+		return 0; 
+	}
+
+	// plane 4 -y
+	dMat3GetCol(cData.mBoxRot,1,vTemp1);
+	dVector3Inv(vTemp1);
+	dConstructPlane(vTemp1,cData.vBoxHalfSize[1],plPlane);
+	if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane )) 
+	{ 
+		return 0; 
+	}
+
+	// plane 5 -z
+	dMat3GetCol(cData.mBoxRot,2,vTemp1);
+	dVector3Inv(vTemp1);
+	dConstructPlane(vTemp1,cData.vBoxHalfSize[2],plPlane);
+	if(!dClipEdgeToPlane( cData.vEp0, cData.vEp1, plPlane )) 
+	{ 
+		return 0; 
+	}
+
+	// calculate depths for both contact points
+	cData.fDepth0 = cData.fBestrb + dVector3Dot(cData.vEp0, cData.vNormal);
+	cData.fDepth1 = cData.fBestrb + dVector3Dot(cData.vEp1, cData.vNormal);
+
+	// clamp depths to 0
+	if(cData.fDepth0<0) 
+	{
+		cData.fDepth0 = REAL(0.0);
+	}
+
+	if(cData.fDepth1<0) 
+	{
+		cData.fDepth1 = REAL(0.0);
+	}
+
+	// back transform edge points from box to absolute space
+	cData.vEp0[0] += cData.vBoxPos[0];
+	cData.vEp0[1] += cData.vBoxPos[1];
+	cData.vEp0[2] += cData.vBoxPos[2];
+
+	cData.vEp1[0] += cData.vBoxPos[0];
+	cData.vEp1[1] += cData.vBoxPos[1];
+	cData.vEp1[2] += cData.vBoxPos[2];
+
+	dContactGeom* Contact0 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
+	Contact0->depth = cData.fDepth0;
+	dVector3Copy(cData.vNormal,Contact0->normal);
+	dVector3Copy(cData.vEp0,Contact0->pos);
+	Contact0->g1 = cData.gCylinder;
+	Contact0->g2 = cData.gBox;
+	dVector3Inv(Contact0->normal);
+	cData.nContacts++;
+	
+	if (cData.nContacts != (cData.iFlags & NUMC_MASK))
+	{
+		dContactGeom* Contact1 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
+		Contact1->depth = cData.fDepth1;
+		dVector3Copy(cData.vNormal,Contact1->normal);
+		dVector3Copy(cData.vEp1,Contact1->pos);
+		Contact1->g1 = cData.gCylinder;
+		Contact1->g2 = cData.gBox;
+		dVector3Inv(Contact1->normal);
+		cData.nContacts++;
+	}
+
+	return 1;
+}
+
+
+void _cldClipBoxToCylinder(sCylinderBoxData& cData ) 
+{
+	dIASSERT(cData.nContacts != (cData.iFlags & NUMC_MASK));
+	
+	dVector3 vCylinderCirclePos, vCylinderCircleNormal_Rel;
+	// check which circle from cylinder we take for clipping
+	if ( dVector3Dot(cData.vCylinderAxis, cData.vNormal) > REAL(0.0) ) 
+	{
+		// get top circle
+		vCylinderCirclePos[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+
+		vCylinderCircleNormal_Rel[0] = REAL(0.0);
+		vCylinderCircleNormal_Rel[1] = REAL(0.0);
+		vCylinderCircleNormal_Rel[2] = REAL(0.0);
+		vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(-1.0);
+	}
+	else 
+	{
+		// get bottom circle
+		vCylinderCirclePos[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+
+		vCylinderCircleNormal_Rel[0] = REAL(0.0);
+		vCylinderCircleNormal_Rel[1] = REAL(0.0);
+		vCylinderCircleNormal_Rel[2] = REAL(0.0);
+		vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(1.0);
+	}
+
+	// vNr is normal in Box frame, pointing from Cylinder to Box
+	dVector3 vNr;
+	dMatrix3 mBoxInv;
+
+	// Find a way to use quaternion
+	dMatrix3Inv(cData.mBoxRot,mBoxInv);
+	dMultiplyMat3Vec3(mBoxInv,cData.vNormal,vNr);
+
+	dVector3 vAbsNormal;
+
+	vAbsNormal[0] = dFabs( vNr[0] );
+	vAbsNormal[1] = dFabs( vNr[1] );
+	vAbsNormal[2] = dFabs( vNr[2] );
+
+	// find which face in box is closest to cylinder
+	int iB0, iB1, iB2;
+
+	// Different from Croteam's code
+	if (vAbsNormal[1] > vAbsNormal[0]) 
+	{
+		// 1 > 0
+		if (vAbsNormal[0]> vAbsNormal[2]) 
+		{
+			// 0 > 2 -> 1 > 0 >2
+			iB0 = 1; iB1 = 0; iB2 = 2;
+		} 
+		else 
+		{
+			// 2 > 0-> Must compare 1 and 2
+			if (vAbsNormal[1] > vAbsNormal[2])
+			{
+				// 1 > 2 -> 1 > 2 > 0
+				iB0 = 1; iB1 = 2; iB2 = 0;
+			}
+			else
+			{
+				// 2 > 1 -> 2 > 1 > 0;
+				iB0 = 2; iB1 = 1; iB2 = 0;
+			}			
+		}
+	} 
+	else 
+	{
+		// 0 > 1
+		if (vAbsNormal[1] > vAbsNormal[2]) 
+		{
+			// 1 > 2 -> 0 > 1 > 2
+			iB0 = 0; iB1 = 1; iB2 = 2;
+		}
+		else 
+		{
+			// 2 > 1 -> Must compare 0 and 2
+			if (vAbsNormal[0] > vAbsNormal[2])
+			{
+				// 0 > 2 -> 0 > 2 > 1;
+				iB0 = 0; iB1 = 2; iB2 = 1;
+			}
+			else
+			{
+				// 2 > 0 -> 2 > 0 > 1;
+				iB0 = 2; iB1 = 0; iB2 = 1;
+			}		
+		}
+	}
+
+	dVector3 vCenter;
+	// find center of box polygon
+	dVector3 vTemp;
+	if (vNr[iB0] > 0) 
+	{
+		dMat3GetCol(cData.mBoxRot,iB0,vTemp);
+		vCenter[0] = cData.vBoxPos[0] - cData.vBoxHalfSize[iB0]*vTemp[0];
+		vCenter[1] = cData.vBoxPos[1] - cData.vBoxHalfSize[iB0]*vTemp[1];
+		vCenter[2] = cData.vBoxPos[2] - cData.vBoxHalfSize[iB0]*vTemp[2];
+	}
+	else 
+	{
+		dMat3GetCol(cData.mBoxRot,iB0,vTemp);
+		vCenter[0] = cData.vBoxPos[0] + cData.vBoxHalfSize[iB0]*vTemp[0];
+		vCenter[1] = cData.vBoxPos[1] + cData.vBoxHalfSize[iB0]*vTemp[1];
+		vCenter[2] = cData.vBoxPos[2] + cData.vBoxHalfSize[iB0]*vTemp[2];
+	}
+
+	// find the vertices of box polygon
+	dVector3 avPoints[4];
+	dVector3 avTempArray1[MAX_CYLBOX_CLIP_POINTS];
+	dVector3 avTempArray2[MAX_CYLBOX_CLIP_POINTS];
+
+	int i=0;
+	for(i=0; i<MAX_CYLBOX_CLIP_POINTS; i++) 
+	{
+		avTempArray1[i][0] = REAL(0.0);
+		avTempArray1[i][1] = REAL(0.0);
+		avTempArray1[i][2] = REAL(0.0);
+
+		avTempArray2[i][0] = REAL(0.0);
+		avTempArray2[i][1] = REAL(0.0);
+		avTempArray2[i][2] = REAL(0.0);
+	}
+
+	dVector3 vAxis1, vAxis2;
+
+	dMat3GetCol(cData.mBoxRot,iB1,vAxis1);
+	dMat3GetCol(cData.mBoxRot,iB2,vAxis2);
+
+	avPoints[0][0] = vCenter[0] + cData.vBoxHalfSize[iB1] * vAxis1[0] - cData.vBoxHalfSize[iB2] * vAxis2[0];
+	avPoints[0][1] = vCenter[1] + cData.vBoxHalfSize[iB1] * vAxis1[1] - cData.vBoxHalfSize[iB2] * vAxis2[1];
+	avPoints[0][2] = vCenter[2] + cData.vBoxHalfSize[iB1] * vAxis1[2] - cData.vBoxHalfSize[iB2] * vAxis2[2];
+
+	avPoints[1][0] = vCenter[0] - cData.vBoxHalfSize[iB1] * vAxis1[0] - cData.vBoxHalfSize[iB2] * vAxis2[0];
+	avPoints[1][1] = vCenter[1] - cData.vBoxHalfSize[iB1] * vAxis1[1] - cData.vBoxHalfSize[iB2] * vAxis2[1];
+	avPoints[1][2] = vCenter[2] - cData.vBoxHalfSize[iB1] * vAxis1[2] - cData.vBoxHalfSize[iB2] * vAxis2[2];
+
+	avPoints[2][0] = vCenter[0] - cData.vBoxHalfSize[iB1] * vAxis1[0] + cData.vBoxHalfSize[iB2] * vAxis2[0];
+	avPoints[2][1] = vCenter[1] - cData.vBoxHalfSize[iB1] * vAxis1[1] + cData.vBoxHalfSize[iB2] * vAxis2[1];
+	avPoints[2][2] = vCenter[2] - cData.vBoxHalfSize[iB1] * vAxis1[2] + cData.vBoxHalfSize[iB2] * vAxis2[2];
+
+	avPoints[3][0] = vCenter[0] + cData.vBoxHalfSize[iB1] * vAxis1[0] + cData.vBoxHalfSize[iB2] * vAxis2[0];
+	avPoints[3][1] = vCenter[1] + cData.vBoxHalfSize[iB1] * vAxis1[1] + cData.vBoxHalfSize[iB2] * vAxis2[1];
+	avPoints[3][2] = vCenter[2] + cData.vBoxHalfSize[iB1] * vAxis1[2] + cData.vBoxHalfSize[iB2] * vAxis2[2];
+
+	// transform box points to space of cylinder circle
+	dMatrix3 mCylinderInv;
+	dMatrix3Inv(cData.mCylinderRot,mCylinderInv);
+
+	for(i=0; i<4; i++) 
+	{
+		dVector3Subtract(avPoints[i],vCylinderCirclePos,vTemp);
+		dMultiplyMat3Vec3(mCylinderInv,vTemp,avPoints[i]);
+	}
+
+	int iTmpCounter1 = 0;
+	int iTmpCounter2 = 0;
+	dVector4 plPlane;
+
+	// plane of cylinder that contains circle for intersection
+	dConstructPlane(vCylinderCircleNormal_Rel,REAL(0.0),plPlane);
+	dClipPolyToPlane(avPoints, 4, avTempArray1, iTmpCounter1, plPlane);
+
+
+	// Body of base circle of Cylinder
+	int nCircleSegment = 0;
+	for (nCircleSegment = 0; nCircleSegment < nCYLINDER_SEGMENT; nCircleSegment++)
+	{
+		dConstructPlane(cData.avCylinderNormals[nCircleSegment],cData.fCylinderRadius,plPlane);
+
+		if (0 == (nCircleSegment % 2))
+		{
+			dClipPolyToPlane( avTempArray1 , iTmpCounter1 , avTempArray2, iTmpCounter2, plPlane);
+		}
+		else
+		{
+			dClipPolyToPlane( avTempArray2, iTmpCounter2, avTempArray1 , iTmpCounter1 , plPlane );
+		}
+
+		dIASSERT( iTmpCounter1 >= 0 && iTmpCounter1 <= MAX_CYLBOX_CLIP_POINTS );
+		dIASSERT( iTmpCounter2 >= 0 && iTmpCounter2 <= MAX_CYLBOX_CLIP_POINTS );
+	}
+	
+	// back transform clipped points to absolute space
+	dReal ftmpdot;	
+	dReal fTempDepth;
+	dVector3 vPoint;
+
+	if (nCircleSegment % 2)
+	{
+		for( i=0; i<iTmpCounter2; i++)
+		{
+			dMULTIPLY0_331(vPoint,cData.mCylinderRot,avTempArray2[i]);
+			vPoint[0] += vCylinderCirclePos[0];
+			vPoint[1] += vCylinderCirclePos[1];
+			vPoint[2] += vCylinderCirclePos[2];
+
+			dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
+			ftmpdot	 = dVector3Dot(vTemp, cData.vNormal);
+			fTempDepth = cData.fBestrc - ftmpdot;
+			// Depth must be positive
+			if (fTempDepth > REAL(0.0))
+			{
+				// generate contacts
+				dContactGeom* Contact0 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
+				Contact0->depth = fTempDepth;
+				dVector3Copy(cData.vNormal,Contact0->normal);
+				dVector3Copy(vPoint,Contact0->pos);
+				Contact0->g1 = cData.gCylinder;
+				Contact0->g2 = cData.gBox;
+				dVector3Inv(Contact0->normal);
+				cData.nContacts++;
+				
+				if (cData.nContacts == (cData.iFlags & NUMC_MASK))
+				{
+					break;
+				}
+			}
+		}
+	}
+	else
+	{
+		for( i=0; i<iTmpCounter1; i++)
+		{
+			dMULTIPLY0_331(vPoint,cData.mCylinderRot,avTempArray1[i]);
+			vPoint[0] += vCylinderCirclePos[0];
+			vPoint[1] += vCylinderCirclePos[1];
+			vPoint[2] += vCylinderCirclePos[2];
+
+			dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
+			ftmpdot	 = dVector3Dot(vTemp, cData.vNormal);
+			fTempDepth = cData.fBestrc - ftmpdot;
+			// Depth must be positive
+			if (fTempDepth > REAL(0.0))
+			{
+				// generate contacts
+				dContactGeom* Contact0 = SAFECONTACT(cData.iFlags, cData.gContact, cData.nContacts, cData.iSkip);
+				Contact0->depth = fTempDepth;
+				dVector3Copy(cData.vNormal,Contact0->normal);
+				dVector3Copy(vPoint,Contact0->pos);
+				Contact0->g1 = cData.gCylinder;
+				Contact0->g2 = cData.gBox;
+				dVector3Inv(Contact0->normal);
+				cData.nContacts++;
+				
+				if (cData.nContacts == (cData.iFlags & NUMC_MASK))
+				{
+					break;
+				}
+			}
+		}
+	}
+}
+
+
+// Cylinder - Box by CroTeam
+// Ported by Nguyen Binh
+int dCollideCylinderBox(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dCylinderClass);
+	dIASSERT (o2->type == dBoxClass);
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	sCylinderBoxData	cData;
+
+	// Assign ODE stuff
+	cData.gCylinder = o1;
+	cData.gBox		= o2;
+	cData.iFlags	= flags;
+	cData.iSkip		= skip;
+	cData.gContact	= contact;
+
+	// initialize collider
+	_cldInitCylinderBox( cData );
+
+	// do intersection test and find best separating axis
+	if(!_cldTestSeparatingAxes( cData ) ) 
+	{
+		// if not found do nothing
+		return 0;
+	}
+
+	// if best separation axis is not found
+	if ( cData.iBestAxis == 0 ) 
+	{
+		// this should not happen (we should already exit in that case)
+		dIASSERT(0);
+		// do nothing
+		return 0;
+	}
+
+	dReal fdot = dVector3Dot(cData.vNormal,cData.vCylinderAxis);
+	// choose which clipping method are we going to apply
+	if (dFabs(fdot) < REAL(0.9) ) 
+	{
+		// clip cylinder over box
+		if(!_cldClipCylinderToBox(cData)) 
+		{
+			return 0;
+		}
+	} 
+	else 
+	{
+		_cldClipBoxToCylinder(cData);  
+	}
+
+	return cData.nContacts;
+}
+
Index: /code/branches/ode/ode-0.9/ode/src/collision_cylinder_plane.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_cylinder_plane.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_cylinder_plane.cpp	(revision 216)
@@ -0,0 +1,254 @@
+/*************************************************************************
+*                                                                       *
+* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+*                                                                       *
+* This library is free software; you can redistribute it and/or         *
+* modify it under the terms of EITHER:                                  *
+*   (1) The GNU Lesser General Public License as published by the Free  *
+*       Software Foundation; either version 2.1 of the License, or (at  *
+*       your option) any later version. The text of the GNU Lesser      *
+*       General Public License is included with this library in the     *
+*       file LICENSE.TXT.                                               *
+*   (2) The BSD-style license that is included with this library in     *
+*       the file LICENSE-BSD.TXT.                                       *
+*                                                                       *
+* This library is distributed in the hope that it will be useful,       *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+*                                                                       *
+*************************************************************************/
+
+
+/*
+ * Cylinder-Plane collider by Christoph Beyer ( boernerb@web.de )
+ *
+ * This testing basically comes down to testing the intersection
+ * of the cylinder caps (discs) with the plane.
+ * 
+ */
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include <ode/objects.h>
+
+#include "collision_kernel.h"	// for dxGeom
+#include "collision_util.h"
+
+
+int dCollideCylinderPlane(dxGeom *Cylinder, dxGeom *Plane, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (Cylinder->type == dCylinderClass);
+	dIASSERT (Plane->type == dPlaneClass);
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	int GeomCount = 0; // count of used contactgeoms
+
+#ifdef dSINGLE
+	const dReal toleranz = REAL(0.0001);
+#endif
+#ifdef dDOUBLE
+	const dReal toleranz = REAL(0.0000001);
+#endif
+
+	// Get the properties of the cylinder (length+radius)
+	dReal radius, length;
+	dGeomCylinderGetParams(Cylinder, &radius, &length);
+	dVector3 &cylpos = Cylinder->final_posr->pos;
+	// and the plane
+	dVector4 planevec;
+	dGeomPlaneGetParams(Plane, planevec);
+	dVector3 PlaneNormal = {planevec[0],planevec[1],planevec[2]};
+	dVector3 PlanePos = {planevec[0] * planevec[3],planevec[1] * planevec[3],planevec[2] * planevec[3]};
+
+	dVector3 G1Pos1, G1Pos2, vDir1;
+	vDir1[0] = Cylinder->final_posr->R[2];
+	vDir1[1] = Cylinder->final_posr->R[6];
+	vDir1[2] = Cylinder->final_posr->R[10];
+
+	dReal s;
+	s = length * REAL(0.5);
+	G1Pos2[0] = vDir1[0] * s + cylpos[0];
+	G1Pos2[1] = vDir1[1] * s + cylpos[1];
+	G1Pos2[2] = vDir1[2] * s + cylpos[2];
+
+	G1Pos1[0] = vDir1[0] * -s + cylpos[0];
+	G1Pos1[1] = vDir1[1] * -s + cylpos[1];
+	G1Pos1[2] = vDir1[2] * -s + cylpos[2];
+
+	dVector3 C;
+
+	// parallel-check
+	s = vDir1[0] * PlaneNormal[0] + vDir1[1] * PlaneNormal[1] + vDir1[2] * PlaneNormal[2];
+	if(s < 0)
+		s += REAL(1.0); // is ca. 0, if vDir1 and PlaneNormal are parallel
+	else
+		s -= REAL(1.0); // is ca. 0, if vDir1 and PlaneNormal are parallel
+	if(s < toleranz && s > (-toleranz))
+	{
+		// discs are parallel to the plane
+
+		// 1.compute if, and where contacts are
+		dVector3 P;
+		s = planevec[3] - dVector3Dot(planevec, G1Pos1);
+		dReal t;
+		t = planevec[3] - dVector3Dot(planevec, G1Pos2);
+		if(s >= t) // s == t does never happen, 
+		{
+			if(s >= 0)
+			{
+				// 1. Disc
+				dVector3Copy(G1Pos1, P);
+			}
+			else
+				return GeomCount; // no contacts
+		}
+		else
+		{
+			if(t >= 0)
+			{
+				// 2. Disc
+				dVector3Copy(G1Pos2, P);
+			}
+			else
+				return GeomCount; // no contacts
+		}
+
+		// 2. generate a coordinate-system on the disc
+		dVector3 V1, V2;
+		if(vDir1[0] < toleranz && vDir1[0] > (-toleranz))
+		{
+			// not x-axis
+			V1[0] = vDir1[0] + REAL(1.0); // random value
+			V1[1] = vDir1[1];
+			V1[2] = vDir1[2];
+		}
+		else
+		{
+			// maybe x-axis
+			V1[0] = vDir1[0];
+			V1[1] = vDir1[1] + REAL(1.0); // random value
+			V1[2] = vDir1[2];
+		}
+		// V1 is now another direction than vDir1
+		// Cross-product
+	    dVector3Cross(V1, vDir1, V2);
+		// make unit V2
+		t = dVector3Length(V2);
+		t = radius / t;
+		dVector3Scale(V2, t);
+		// cross again
+		dVector3Cross(V2, vDir1, V1);
+		// |V2| is 'radius' and vDir1 unit, so |V1| is 'radius'
+		// V1 = first axis
+		// V2 = second axis
+
+		// 3. generate contactpoints
+
+		// Potential contact 1
+		dVector3Add(P, V1, contact->pos);
+		contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
+		if(contact->depth > 0)
+		{
+			dVector3Copy(PlaneNormal, contact->normal);
+			contact->g1 = Cylinder;
+			contact->g2 = Plane;
+			GeomCount++;
+			if( GeomCount >= (flags & NUMC_MASK))
+				return GeomCount; // enough contactgeoms
+			contact = (dContactGeom *)((char *)contact + skip);
+		}
+
+		// Potential contact 2
+		dVector3Subtract(P, V1, contact->pos);
+		contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
+		if(contact->depth > 0)
+		{
+			dVector3Copy(PlaneNormal, contact->normal);
+			contact->g1 = Cylinder;
+			contact->g2 = Plane;
+			GeomCount++;
+			if( GeomCount >= (flags & NUMC_MASK))
+				return GeomCount; // enough contactgeoms
+			contact = (dContactGeom *)((char *)contact + skip);
+		}
+
+		// Potential contact 3
+		dVector3Add(P, V2, contact->pos);
+		contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
+		if(contact->depth > 0)
+		{
+			dVector3Copy(PlaneNormal, contact->normal);
+			contact->g1 = Cylinder;
+			contact->g2 = Plane;
+			GeomCount++;
+			if( GeomCount >= (flags & NUMC_MASK))
+				return GeomCount; // enough contactgeoms
+			contact = (dContactGeom *)((char *)contact + skip);
+		}
+
+		// Potential contact 4
+		dVector3Subtract(P, V2, contact->pos);
+		contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
+		if(contact->depth > 0)
+		{
+			dVector3Copy(PlaneNormal, contact->normal);
+			contact->g1 = Cylinder;
+			contact->g2 = Plane;
+			GeomCount++;
+			if( GeomCount >= (flags & NUMC_MASK))
+				return GeomCount; // enough contactgeoms
+			contact = (dContactGeom *)((char *)contact + skip);
+		}
+	}
+	else
+	{
+		dReal t = dVector3Dot(PlaneNormal, vDir1);
+		C[0] = vDir1[0] * t - PlaneNormal[0];
+		C[1] = vDir1[1] * t - PlaneNormal[1];
+		C[2] = vDir1[2] * t - PlaneNormal[2];
+		s = dVector3Length(C);
+		// move C onto the circle
+		s = radius / s;
+		dVector3Scale(C, s);
+
+		// deepest point of disc 1
+		dVector3Add(C, G1Pos1, contact->pos);
+
+		// depth of the deepest point
+		contact->depth = planevec[3] - dVector3Dot(planevec, contact->pos);
+		if(contact->depth >= 0)
+		{
+			dVector3Copy(PlaneNormal, contact->normal);
+			contact->g1 = Cylinder;
+			contact->g2 = Plane;
+			GeomCount++;
+			if( GeomCount >= (flags & NUMC_MASK))
+				return GeomCount; // enough contactgeoms
+			contact = (dContactGeom *)((char *)contact + skip);
+		}
+
+		// C is still computed
+
+		// deepest point of disc 2
+		dVector3Add(C, G1Pos2, contact->pos);
+
+		// depth of the deepest point
+		contact->depth = planevec[3] - planevec[0] * contact->pos[0] - planevec[1] * contact->pos[1] - planevec[2] * contact->pos[2];
+		if(contact->depth >= 0)
+		{
+			dVector3Copy(PlaneNormal, contact->normal);
+			contact->g1 = Cylinder;
+			contact->g2 = Plane;
+			GeomCount++;
+			if( GeomCount >= (flags & NUMC_MASK))
+				return GeomCount; // enough contactgeoms
+			contact = (dContactGeom *)((char *)contact + skip);
+		}
+	}
+	return GeomCount;
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_cylinder_sphere.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_cylinder_sphere.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_cylinder_sphere.cpp	(revision 216)
@@ -0,0 +1,264 @@
+/*************************************************************************
+*                                                                       *
+* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+*                                                                       *
+* This library is free software; you can redistribute it and/or         *
+* modify it under the terms of EITHER:                                  *
+*   (1) The GNU Lesser General Public License as published by the Free  *
+*       Software Foundation; either version 2.1 of the License, or (at  *
+*       your option) any later version. The text of the GNU Lesser      *
+*       General Public License is included with this library in the     *
+*       file LICENSE.TXT.                                               *
+*   (2) The BSD-style license that is included with this library in     *
+*       the file LICENSE-BSD.TXT.                                       *
+*                                                                       *
+* This library is distributed in the hope that it will be useful,       *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+*                                                                       *
+*************************************************************************/
+
+
+/*******************************************************************
+ *                                                                 *
+ * cylinder-sphere collider by Christoph Beyer (boernerb@web.de)   *
+ *                                                                 *
+ * In Cylinder/Sphere-collisions, there are three possibilies:     *
+ * 1. collision with the cylinder's nappe                          *
+ * 2. collision with one of the cylinder's disc                    *
+ * 3. collision with one of the disc's border                      *
+ *                                                                 *
+ * This collider computes two distances (s, t) and based on them,  *
+ * it decides, which collision we have.                            *
+ * This collider always generates 1 (or 0, if we have no collison) *
+ * contacts.                                                       *
+ * It is able to "separate" cylinder and sphere in all             *
+ * configurations, but it never pays attention to velocity.        *
+ * So, in extrem situations, "tunneling-effect" is possible.       *
+ *                                                                 *
+ *******************************************************************/
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include <ode/objects.h>
+#include "collision_kernel.h"	// for dxGeom
+#include "collision_util.h"
+
+int dCollideCylinderSphere(dxGeom* Cylinder, dxGeom* Sphere, 
+                           int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (Cylinder->type == dCylinderClass);
+	dIASSERT (Sphere->type == dSphereClass);
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	unsigned char* pContactData = (unsigned char*)contact;
+	int GeomCount = 0; // count of used contacts
+
+#ifdef dSINGLE
+	const dReal toleranz = REAL(0.0001);
+#endif
+#ifdef dDOUBLE
+	const dReal toleranz = REAL(0.0000001);
+#endif
+
+	// get the data from the geoms
+	dReal radius, length;
+	dGeomCylinderGetParams(Cylinder, &radius, &length);
+    dVector3 &cylpos = Cylinder->final_posr->pos;
+	const dReal* pfRot1 = dGeomGetRotation(Cylinder);
+
+	dReal radius2;
+	radius2 = dGeomSphereGetRadius(Sphere);
+	const dReal* SpherePos = dGeomGetPosition(Sphere);
+
+	// G1Pos1 is the middle of the first disc
+	// G1Pos2 is the middle of the second disc
+	// vDir1 is the unit direction of the cylinderaxis
+	dVector3 G1Pos1, G1Pos2, vDir1;
+	vDir1[0] = Cylinder->final_posr->R[2];
+	vDir1[1] = Cylinder->final_posr->R[6];
+	vDir1[2] = Cylinder->final_posr->R[10];
+
+	dReal s;
+	s = length * REAL(0.5); // just a precomputed factor
+	G1Pos2[0] = vDir1[0] * s + cylpos[0];
+	G1Pos2[1] = vDir1[1] * s + cylpos[1];
+	G1Pos2[2] = vDir1[2] * s + cylpos[2];
+
+	G1Pos1[0] = vDir1[0] * -s + cylpos[0];
+	G1Pos1[1] = vDir1[1] * -s + cylpos[1];
+	G1Pos1[2] = vDir1[2] * -s + cylpos[2];
+
+	dVector3 C;
+	dReal t;
+	// Step 1: compute the two distances 's' and 't'
+	// 's' is the distance from the first disc (in vDir1-/Zylinderaxis-direction), the disc with G1Pos1 in the middle
+	s = (SpherePos[0] - G1Pos1[0]) * vDir1[0] - (G1Pos1[1] - SpherePos[1]) * vDir1[1] - (G1Pos1[2] - SpherePos[2]) * vDir1[2];
+	if(s < (-radius2) || s > (length + radius2) )
+	{
+		// Sphere is too far away from the discs
+		// no collision
+		return 0;
+	}
+
+	// C is the direction from Sphere-middle to the cylinder-axis (vDir1); C is orthogonal to the cylinder-axis
+	C[0] = s * vDir1[0] + G1Pos1[0] - SpherePos[0];
+	C[1] = s * vDir1[1] + G1Pos1[1] - SpherePos[1];
+	C[2] = s * vDir1[2] + G1Pos1[2] - SpherePos[2];
+	// t is the distance from the Sphere-middle to the cylinder-axis!
+	t = dVector3Length(C);
+	if(t > (radius + radius2) )
+	{
+		// Sphere is too far away from the cylinder axis!
+		// no collision
+		return 0;
+	}
+
+	// decide which kind of collision we have:
+	if(t > radius && (s < 0 || s > length) )
+	{
+		// 3. collision
+		if(s <= 0)
+		{
+			contact->depth = radius2 - dSqrt( (s) * (s) + (t - radius) * (t - radius) );
+			if(contact->depth < 0)
+			{
+				// no collision!
+				return 0;
+			}
+			contact->pos[0] = C[0] / t * -radius + G1Pos1[0];
+			contact->pos[1] = C[1] / t * -radius + G1Pos1[1];
+			contact->pos[2] = C[2] / t * -radius + G1Pos1[2];
+			contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
+			contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
+			contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
+			contact->g1 = Cylinder;
+			contact->g2 = Sphere;
+			GeomCount++;
+			return GeomCount;
+		}
+		else
+		{
+			// now s is bigger than length here!
+			contact->depth = radius2 - dSqrt( (s - length) * (s - length) + (t - radius) * (t - radius) );
+			if(contact->depth < 0)
+			{
+				// no collision!
+				return 0;
+			}
+			contact->pos[0] = C[0] / t * -radius + G1Pos2[0];
+			contact->pos[1] = C[1] / t * -radius + G1Pos2[1];
+			contact->pos[2] = C[2] / t * -radius + G1Pos2[2];
+			contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
+			contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
+			contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
+			contact->g1 = Cylinder;
+			contact->g2 = Sphere;
+			GeomCount++;
+			return GeomCount;
+		}
+	}
+	else if( (radius - t) <= s && (radius - t) <= (length - s) )
+	{
+		// 1. collsision
+		if(t > (radius2 + toleranz))
+		{
+			// cylinder-axis is outside the sphere
+			contact->depth = (radius2 + radius) - t;
+			if(contact->depth < 0)
+			{
+				// should never happen, but just for safeness
+				return 0;
+			}
+			else
+			{
+				C[0] /= t;
+				C[1] /= t;
+				C[2] /= t;
+				contact->pos[0] = C[0] * radius2 + SpherePos[0];
+				contact->pos[1] = C[1] * radius2 + SpherePos[1];
+				contact->pos[2] = C[2] * radius2 + SpherePos[2];
+				contact->normal[0] = C[0];
+				contact->normal[1] = C[1];
+				contact->normal[2] = C[2];
+				contact->g1 = Cylinder;
+				contact->g2 = Sphere;
+				GeomCount++;
+				return GeomCount;
+			}
+		}
+		else
+		{
+			// cylinder-axis is outside of the sphere
+			contact->depth = (radius2 + radius) - t;
+			if(contact->depth < 0)
+			{
+				// should never happen, but just for safeness
+				return 0;
+			}
+			else
+			{
+				contact->pos[0] = C[0] + SpherePos[0];
+				contact->pos[1] = C[1] + SpherePos[1];
+				contact->pos[2] = C[2] + SpherePos[2];
+				contact->normal[0] = C[0] / t;
+				contact->normal[1] = C[1] / t;
+				contact->normal[2] = C[2] / t;
+				contact->g1 = Cylinder;
+				contact->g2 = Sphere;
+				GeomCount++;
+				return GeomCount;
+			}
+		}
+	}
+	else
+	{
+		// 2. collision
+		if(s <= (length * REAL(0.5)) )
+		{
+			// collsision with the first disc
+			contact->depth = s + radius2;
+			if(contact->depth < 0)
+			{
+				// should never happen, but just for safeness
+				return 0;
+			}
+			contact->pos[0] = radius2 * vDir1[0] + SpherePos[0];
+			contact->pos[1] = radius2 * vDir1[1] + SpherePos[1];
+			contact->pos[2] = radius2 * vDir1[2] + SpherePos[2];
+			contact->normal[0] = vDir1[0];
+			contact->normal[1] = vDir1[1];
+			contact->normal[2] = vDir1[2];
+			contact->g1 = Cylinder;
+			contact->g2 = Sphere;
+			GeomCount++;
+			return GeomCount;
+		}
+		else
+		{
+			// collsision with the second disc
+			contact->depth = (radius2 + length - s);
+			if(contact->depth < 0)
+			{
+				// should never happen, but just for safeness
+				return 0;
+			}
+			contact->pos[0] = radius2 * -vDir1[0] + SpherePos[0];
+			contact->pos[1] = radius2 * -vDir1[1] + SpherePos[1];
+			contact->pos[2] = radius2 * -vDir1[2] + SpherePos[2];
+			contact->normal[0] = -vDir1[0];
+			contact->normal[1] = -vDir1[1];
+			contact->normal[2] = -vDir1[2];
+			contact->g1 = Cylinder;
+			contact->g2 = Sphere;
+			GeomCount++;
+			return GeomCount;
+		}
+	}
+	return GeomCount;
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_cylinder_trimesh.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_cylinder_trimesh.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_cylinder_trimesh.cpp	(revision 216)
@@ -0,0 +1,1145 @@
+/*************************************************************************
+*                                                                       *
+* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+*                                                                       *
+* This library is free software; you can redistribute it and/or         *
+* modify it under the terms of EITHER:                                  *
+*   (1) The GNU Lesser General Public License as published by the Free  *
+*       Software Foundation; either version 2.1 of the License, or (at  *
+*       your option) any later version. The text of the GNU Lesser      *
+*       General Public License is included with this library in the     *
+*       file LICENSE.TXT.                                               *
+*   (2) The BSD-style license that is included with this library in     *
+*       the file LICENSE-BSD.TXT.                                       *
+*                                                                       *
+* This library is distributed in the hope that it will be useful,       *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+*                                                                       *
+*************************************************************************/
+
+/*
+ *	Cylinder-trimesh collider by Alen Ladavac
+ *   Ported to ODE by Nguyen Binh
+ */
+
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#define MAX_REAL	dInfinity
+static const int	nCYLINDER_AXIS				= 2;
+static const int    nCYLINDER_CIRCLE_SEGMENTS	= 8;
+static const int    nMAX_CYLINDER_TRIANGLE_CLIP_POINTS	= 12;
+
+#define OPTIMIZE_CONTACTS 1
+
+// Local contacts data
+typedef struct _sLocalContactData
+{
+	dVector3	vPos;
+	dVector3	vNormal;
+	dReal		fDepth;
+	int			triIndex;
+	int			nFlags; // 0 = filtered out, 1 = OK
+}sLocalContactData;
+
+typedef struct _sCylinderTrimeshColliderData
+{
+	// cylinder data
+	dMatrix3	mCylinderRot;
+	dQuaternion	qCylinderRot;
+	dQuaternion	qInvCylinderRot;
+	dVector3	vCylinderPos;
+	dVector3	vCylinderAxis;
+	dReal		fCylinderRadius;
+	dReal		fCylinderSize;
+	dVector3	avCylinderNormals[nCYLINDER_CIRCLE_SEGMENTS];
+
+	// mesh data
+	dQuaternion	qTrimeshRot;
+	dQuaternion	qInvTrimeshRot;
+	dMatrix3	mTrimeshRot;
+	dVector3	vTrimeshPos;
+
+	// global collider data
+	dVector3	vBestPoint;
+	dReal		fBestDepth;
+	dReal		fBestCenter;
+	dReal		fBestrt;
+	int			iBestAxis;
+	dVector3	vContactNormal;
+	dVector3	vNormal;
+	dVector3	vE0;
+	dVector3	vE1;
+	dVector3	vE2;
+
+	// ODE stuff
+	dGeomID				gCylinder;
+	dxTriMesh*			gTrimesh;
+	dContactGeom*		gContact;
+	int					iFlags;
+	int					iSkip;
+	int					nContacts;// = 0;
+	sLocalContactData*	gLocalContacts;
+} sCylinderTrimeshColliderData;
+
+// Short type name
+typedef  sCylinderTrimeshColliderData sData;
+
+// Use to classify contacts to be "near" in position
+static const dReal fSameContactPositionEpsilon = REAL(0.0001); // 1e-4
+// Use to classify contacts to be "near" in normal direction
+static const dReal fSameContactNormalEpsilon = REAL(0.0001); // 1e-4
+
+// If this two contact can be classified as "near"
+inline int _IsNearContacts(sLocalContactData& c1,sLocalContactData& c2)
+{
+	int bPosNear = 0;
+	int bSameDir = 0;
+	dVector3	vDiff;
+
+	// First check if they are "near" in position
+	dVector3Subtract(c1.vPos,c2.vPos,vDiff);
+	if (  (dFabs(vDiff[0]) < fSameContactPositionEpsilon)
+		&&(dFabs(vDiff[1]) < fSameContactPositionEpsilon)
+		&&(dFabs(vDiff[2]) < fSameContactPositionEpsilon))
+	{
+		bPosNear = 1;
+	}
+
+	// Second check if they are "near" in normal direction
+	dVector3Subtract(c1.vNormal,c2.vNormal,vDiff);
+	if (  (dFabs(vDiff[0]) < fSameContactNormalEpsilon)
+		&&(dFabs(vDiff[1]) < fSameContactNormalEpsilon)
+		&&(dFabs(vDiff[2]) < fSameContactNormalEpsilon) )
+	{
+		bSameDir = 1;
+	}
+
+	// Will be "near" if position and normal direction are "near"
+	return (bPosNear && bSameDir);
+}
+
+inline int _IsBetter(sLocalContactData& c1,sLocalContactData& c2)
+{
+	// The not better will be throw away
+	// You can change the selection criteria here
+	return (c1.fDepth > c2.fDepth);
+}
+
+// iterate through gLocalContacts and filtered out "near contact"
+inline void	_OptimizeLocalContacts(sData& cData)
+{
+	int nContacts = cData.nContacts;
+
+	for (int i = 0; i < nContacts-1; i++)
+	{
+		for (int j = i+1; j < nContacts; j++)
+		{
+			if (_IsNearContacts(cData.gLocalContacts[i],cData.gLocalContacts[j]))
+			{
+				// If they are seem to be the same then filtered 
+				// out the least penetrate one
+				if (_IsBetter(cData.gLocalContacts[j],cData.gLocalContacts[i]))
+				{
+					cData.gLocalContacts[i].nFlags = 0; // filtered 1st contact
+				}
+				else
+				{
+					cData.gLocalContacts[j].nFlags = 0; // filtered 2nd contact
+				}
+
+				// NOTE
+				// There is other way is to add two depth together but
+				// it not work so well. Why???
+			}
+		}
+	}
+}
+
+inline int	_ProcessLocalContacts(sData& cData)
+{
+	if (cData.nContacts == 0)
+	{
+		return 0;
+	}
+
+#ifdef OPTIMIZE_CONTACTS
+	if (cData.nContacts > 1 && !(cData.iFlags & CONTACTS_UNIMPORTANT))
+	{
+		// Can be optimized...
+		_OptimizeLocalContacts(cData);
+	}
+#endif		
+
+	int iContact = 0;
+	dContactGeom* Contact = 0;
+
+	int nFinalContact = 0;
+
+	for (iContact = 0; iContact < cData.nContacts; iContact ++)
+	{
+		if (1 == cData.gLocalContacts[iContact].nFlags)
+		{
+			Contact = SAFECONTACT(cData.iFlags, cData.gContact, nFinalContact, cData.iSkip);
+			Contact->depth = cData.gLocalContacts[iContact].fDepth;
+			dVector3Copy(cData.gLocalContacts[iContact].vNormal,Contact->normal);
+			dVector3Copy(cData.gLocalContacts[iContact].vPos,Contact->pos);
+			Contact->g1 = cData.gCylinder;
+			Contact->g2 = cData.gTrimesh;
+			Contact->side2 = cData.gLocalContacts[iContact].triIndex;
+			dVector3Inv(Contact->normal);
+
+			nFinalContact++;
+		}
+	}
+	// debug
+	//if (nFinalContact != cData.nContacts)
+	//{
+	//	printf("[Info] %d contacts generated,%d  filtered.\n",cData.nContacts,cData.nContacts-nFinalContact);
+	//}
+
+	return nFinalContact;
+}
+
+
+bool _cldTestAxis(sData& cData,
+				  const dVector3 &v0,
+				  const dVector3 &v1,
+				  const dVector3 &v2, 
+                  dVector3& vAxis, 
+				  int iAxis,
+				  bool bNoFlip = false)
+{
+  
+	// calculate length of separating axis vector
+	dReal fL = dVector3Length(vAxis);
+	// if not long enough
+	if ( fL < REAL(1e-5) )
+	{
+		// do nothing
+		return true;
+	}
+
+	// otherwise normalize it
+	vAxis[0] /= fL;
+	vAxis[1] /= fL;
+	vAxis[2] /= fL;
+
+	dReal fdot1 = dVector3Dot(cData.vCylinderAxis,vAxis);
+	// project capsule on vAxis
+	dReal frc;
+
+	if (dFabs(fdot1) > REAL(1.0) ) 
+	{
+//		fdot1 = REAL(1.0);
+		frc = dFabs(cData.fCylinderSize* REAL(0.5));
+	}
+	else
+	{
+		frc = dFabs((cData.fCylinderSize* REAL(0.5)) * fdot1)
+			+ cData.fCylinderRadius * dSqrt(REAL(1.0)-(fdot1*fdot1));
+	}
+  
+	dVector3 vV0;
+	dVector3Subtract(v0,cData.vCylinderPos,vV0);
+	dVector3 vV1;
+	dVector3Subtract(v1,cData.vCylinderPos,vV1);
+	dVector3 vV2;
+	dVector3Subtract(v2,cData.vCylinderPos,vV2);
+
+	// project triangle on vAxis
+	dReal afv[3];
+	afv[0] = dVector3Dot( vV0 , vAxis );
+	afv[1] = dVector3Dot( vV1 , vAxis );
+	afv[2] = dVector3Dot( vV2 , vAxis );
+
+	dReal fMin = MAX_REAL;
+	dReal fMax = -MAX_REAL;
+
+	// for each vertex 
+	for(int i = 0; i < 3; i++) 
+	{
+		// find minimum
+		if (afv[i]<fMin) 
+		{
+			fMin = afv[i];
+		}
+		// find maximum
+		if (afv[i]>fMax) 
+		{
+			fMax = afv[i];
+		}
+	}
+
+	// find capsule's center of interval on axis
+	dReal fCenter = (fMin+fMax)* REAL(0.5);
+	// calculate triangles halfinterval 
+	dReal fTriangleRadius = (fMax-fMin)*REAL(0.5);
+
+	// if they do not overlap, 
+	if( dFabs(fCenter) > (frc+fTriangleRadius) ) 
+	{ 
+		// exit, we have no intersection
+		return false; 
+	}
+
+	// calculate depth 
+	dReal fDepth = -(dFabs(fCenter) - (frc + fTriangleRadius ) );
+
+	// if greater then best found so far
+	if ( fDepth < cData.fBestDepth ) 
+	{
+		// remember depth
+		cData.fBestDepth			= fDepth;
+		cData.fBestCenter		    = fCenter;
+		cData.fBestrt				= frc;
+		dVector3Copy(vAxis,cData.vContactNormal);
+		cData.iBestAxis				= iAxis;
+	  
+		// flip normal if interval is wrong faced
+		if ( fCenter< REAL(0.0) && !bNoFlip) 
+		{ 
+			dVector3Inv(cData.vContactNormal);
+			cData.fBestCenter = -fCenter;
+		}
+	}
+  
+	return true;
+}
+
+// intersection test between edge and circle
+bool _cldTestCircleToEdgeAxis(sData& cData,
+							  const dVector3 &v0, const dVector3 &v1, const dVector3 &v2,
+                              const dVector3 &vCenterPoint, const dVector3 &vCylinderAxis1,
+                              const dVector3 &vVx0, const dVector3 &vVx1, int iAxis) 
+{
+	// calculate direction of edge
+	dVector3 vkl;
+	dVector3Subtract( vVx1 , vVx0 , vkl);
+	dNormalize3(vkl);
+	// starting point of edge 
+	dVector3 vol;
+	dVector3Copy(vVx0,vol);
+
+	// calculate angle cosine between cylinder axis and edge
+	dReal fdot2 = dVector3Dot(vkl , vCylinderAxis1);
+
+	// if edge is perpendicular to cylinder axis
+	if(dFabs(fdot2)<REAL(1e-5))
+	{
+		// this can't be separating axis, because edge is parallel to circle plane
+		return true;
+	}
+    
+	// find point of intersection between edge line and circle plane
+	dVector3 vTemp;
+	dVector3Subtract(vCenterPoint,vol,vTemp);
+	dReal fdot1 = dVector3Dot(vTemp,vCylinderAxis1);
+	dVector3 vpnt;// = vol + vkl * (fdot1/fdot2);
+	vpnt[0] = vol[0] + vkl[0] * fdot1/fdot2;
+	vpnt[1] = vol[1] + vkl[1] * fdot1/fdot2;
+	vpnt[2] = vol[2] + vkl[2] * fdot1/fdot2;
+
+	// find tangent vector on circle with same center (vCenterPoint) that touches point of intersection (vpnt)
+	dVector3 vTangent;
+	dVector3Subtract(vCenterPoint,vpnt,vTemp);
+	dVector3Cross(vTemp,vCylinderAxis1,vTangent);
+  
+	// find vector orthogonal both to tangent and edge direction
+	dVector3 vAxis;
+	dVector3Cross(vTangent,vkl,vAxis);
+
+	// use that vector as separating axis
+	return _cldTestAxis( cData ,v0, v1, v2, vAxis, iAxis );
+}
+
+// helper for less key strokes
+// r = ( (v1 - v2) cross v3 ) cross v3
+inline void _CalculateAxis(const dVector3& v1,
+						   const dVector3& v2,
+						   const dVector3& v3,
+						   dVector3& r)
+{
+	dVector3 t1;
+	dVector3 t2;
+
+	dVector3Subtract(v1,v2,t1);
+	dVector3Cross(t1,v3,t2);
+	dVector3Cross(t2,v3,r);
+}
+
+bool _cldTestSeparatingAxes(sData& cData,
+							const dVector3 &v0,
+							const dVector3 &v1,
+							const dVector3 &v2) 
+{
+
+	// calculate edge vectors
+	dVector3Subtract(v1 ,v0 , cData.vE0);
+	// cData.vE1 has been calculated before -> so save some cycles here
+	dVector3Subtract(v0 ,v2 , cData.vE2);
+
+	// calculate caps centers in absolute space
+	dVector3 vCp0;
+	vCp0[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize* REAL(0.5));
+	vCp0[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize* REAL(0.5));
+	vCp0[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize* REAL(0.5));
+
+	dVector3 vCp1;
+	vCp1[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize* REAL(0.5));
+	vCp1[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize* REAL(0.5));
+	vCp1[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize* REAL(0.5));
+
+	// reset best axis
+	cData.iBestAxis = 0;
+	dVector3 vAxis;
+
+	// axis cData.vNormal
+	//vAxis = -cData.vNormal;
+	vAxis[0] = -cData.vNormal[0];
+	vAxis[1] = -cData.vNormal[1];
+	vAxis[2] = -cData.vNormal[2];
+	if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 1, true)) 
+	{ 
+		return false; 
+	}
+
+	// axis CxE0
+	// vAxis = ( cData.vCylinderAxis cross cData.vE0 );
+	dVector3Cross(cData.vCylinderAxis, cData.vE0,vAxis);
+	if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 2)) 
+	{ 
+		return false; 
+	}
+
+	// axis CxE1
+	// vAxis = ( cData.vCylinderAxis cross cData.vE1 );
+	dVector3Cross(cData.vCylinderAxis, cData.vE1,vAxis);
+	if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 3)) 
+	{ 
+		return false; 
+	}
+
+	// axis CxE2
+	// vAxis = ( cData.vCylinderAxis cross cData.vE2 );
+	dVector3Cross(cData.vCylinderAxis, cData.vE2,vAxis);
+	if (!_cldTestAxis( cData ,v0, v1, v2, vAxis, 4)) 
+	{ 
+		return false; 
+	}
+
+	// first vertex on triangle
+	// axis ((V0-Cp0) x C) x C
+	//vAxis = ( ( v0-vCp0 ) cross cData.vCylinderAxis ) cross cData.vCylinderAxis;
+	_CalculateAxis(v0 , vCp0 , cData.vCylinderAxis , vAxis);
+	if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 11)) 
+	{ 
+		return false; 
+	}
+
+	// second vertex on triangle
+	// axis ((V1-Cp0) x C) x C
+	// vAxis = ( ( v1-vCp0 ) cross cData.vCylinderAxis ) cross cData.vCylinderAxis;
+	_CalculateAxis(v1 , vCp0 , cData.vCylinderAxis , vAxis);
+	if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 12)) 
+	{ 
+		return false; 
+	}
+
+	// third vertex on triangle
+	// axis ((V2-Cp0) x C) x C
+	//vAxis = ( ( v2-vCp0 ) cross cData.vCylinderAxis ) cross cData.vCylinderAxis;
+	_CalculateAxis(v2 , vCp0 , cData.vCylinderAxis , vAxis);
+	if (!_cldTestAxis(cData, v0, v1, v2, vAxis, 13))
+	{ 
+		return false; 
+	}
+
+	// test cylinder axis
+	// vAxis = cData.vCylinderAxis;
+	dVector3Copy(cData.vCylinderAxis , vAxis);
+	if (!_cldTestAxis(cData , v0, v1, v2, vAxis, 14)) 
+	{ 
+		return false; 
+	}
+
+	// Test top and bottom circle ring of cylinder for separation
+	dVector3 vccATop;
+	vccATop[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize * REAL(0.5));
+	vccATop[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize * REAL(0.5));
+	vccATop[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize * REAL(0.5));
+
+	dVector3 vccABottom;
+	vccABottom[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize * REAL(0.5));
+	vccABottom[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize * REAL(0.5));
+	vccABottom[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize * REAL(0.5));
+
+
+  if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccATop, cData.vCylinderAxis, v0, v1, 15)) 
+  {
+    return false;
+  }
+
+  if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccATop, cData.vCylinderAxis, v1, v2, 16)) 
+  {
+    return false;
+  }
+
+  if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccATop, cData.vCylinderAxis, v0, v2, 17)) 
+  {
+    return false;
+  }
+
+  if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccABottom, cData.vCylinderAxis, v0, v1, 18)) 
+  {
+    return false;
+  }
+
+  if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccABottom, cData.vCylinderAxis, v1, v2, 19)) 
+  {
+    return false;
+  }
+
+  if (!_cldTestCircleToEdgeAxis(cData, v0, v1, v2, vccABottom, cData.vCylinderAxis, v0, v2, 20)) 
+  {
+    return false;
+  }
+
+  return true;
+}
+
+bool _cldClipCylinderEdgeToTriangle(sData& cData, const dVector3 &v0, const dVector3 &v1, const dVector3 &v2)
+{
+	// translate cylinder
+	dReal fTemp = dVector3Dot(cData.vCylinderAxis , cData.vContactNormal);
+	dVector3 vN2;
+	vN2[0] = cData.vContactNormal[0] - cData.vCylinderAxis[0]*fTemp;
+	vN2[1] = cData.vContactNormal[1] - cData.vCylinderAxis[1]*fTemp;
+	vN2[2] = cData.vContactNormal[2] - cData.vCylinderAxis[2]*fTemp;
+
+	fTemp = dVector3Length(vN2);
+	if (fTemp < REAL(1e-5))
+	{
+		return false;
+	}
+
+	// Normalize it
+	vN2[0] /= fTemp;
+	vN2[1] /= fTemp;
+	vN2[2] /= fTemp;
+
+	// calculate caps centers in absolute space
+	dVector3 vCposTrans;
+	vCposTrans[0] = cData.vCylinderPos[0] + vN2[0]*cData.fCylinderRadius;
+	vCposTrans[1] = cData.vCylinderPos[1] + vN2[1]*cData.fCylinderRadius;
+	vCposTrans[2] = cData.vCylinderPos[2] + vN2[2]*cData.fCylinderRadius;
+	  
+	dVector3 vCEdgePoint0;
+	vCEdgePoint0[0]  = vCposTrans[0] + cData.vCylinderAxis[0] * (cData.fCylinderSize* REAL(0.5));
+	vCEdgePoint0[1]  = vCposTrans[1] + cData.vCylinderAxis[1] * (cData.fCylinderSize* REAL(0.5));
+	vCEdgePoint0[2]  = vCposTrans[2] + cData.vCylinderAxis[2] * (cData.fCylinderSize* REAL(0.5));
+
+	dVector3 vCEdgePoint1;
+	vCEdgePoint1[0]  = vCposTrans[0] - cData.vCylinderAxis[0] * (cData.fCylinderSize* REAL(0.5));
+	vCEdgePoint1[1]  = vCposTrans[1] - cData.vCylinderAxis[1] * (cData.fCylinderSize* REAL(0.5));
+	vCEdgePoint1[2]  = vCposTrans[2] - cData.vCylinderAxis[2] * (cData.fCylinderSize* REAL(0.5));
+
+	// transform cylinder edge points into triangle space
+	vCEdgePoint0[0] -= v0[0];
+	vCEdgePoint0[1] -= v0[1];
+	vCEdgePoint0[2] -= v0[2];
+
+	vCEdgePoint1[0] -= v0[0];
+	vCEdgePoint1[1] -= v0[1];
+	vCEdgePoint1[2] -= v0[2];
+
+	dVector4 plPlane;
+	dVector3 vPlaneNormal;
+
+	// triangle plane
+	//plPlane = Plane4f( -cData.vNormal, 0);
+	vPlaneNormal[0] = -cData.vNormal[0];
+	vPlaneNormal[1] = -cData.vNormal[1];
+	vPlaneNormal[2] = -cData.vNormal[2];
+	dConstructPlane(vPlaneNormal,REAL(0.0),plPlane);
+	if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
+	{ 
+		return false; 
+	}
+
+	// plane with edge 0
+	//plPlane = Plane4f( ( cData.vNormal cross cData.vE0 ), REAL(1e-5));
+	dVector3Cross(cData.vNormal,cData.vE0,vPlaneNormal);
+	dConstructPlane(vPlaneNormal,REAL(1e-5),plPlane);
+	if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
+	{ 
+		return false; 
+	}
+  
+	// plane with edge 1
+	//dVector3 vTemp = ( cData.vNormal cross cData.vE1 );
+	dVector3Cross(cData.vNormal,cData.vE1,vPlaneNormal);
+	fTemp = dVector3Dot(cData.vE0 , vPlaneNormal) - REAL(1e-5);
+	//plPlane = Plane4f( vTemp, -(( cData.vE0 dot vTemp )-REAL(1e-5)));
+	dConstructPlane(vPlaneNormal,-fTemp,plPlane);
+	if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
+	{
+		return false;
+	}
+
+	// plane with edge 2
+	// plPlane = Plane4f( ( cData.vNormal cross cData.vE2 ), REAL(1e-5));
+	dVector3Cross(cData.vNormal,cData.vE2,vPlaneNormal);
+	dConstructPlane(vPlaneNormal,REAL(1e-5),plPlane);
+	if(!dClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
+	{ 
+		return false; 
+	}
+
+	// return capsule edge points into absolute space
+	vCEdgePoint0[0] += v0[0];
+	vCEdgePoint0[1] += v0[1];
+	vCEdgePoint0[2] += v0[2];
+
+	vCEdgePoint1[0] += v0[0];
+	vCEdgePoint1[1] += v0[1];
+	vCEdgePoint1[2] += v0[2];
+
+	// calculate depths for both contact points
+	dVector3 vTemp;
+	dVector3Subtract(vCEdgePoint0,cData.vCylinderPos, vTemp);
+	dReal fRestDepth0 = -dVector3Dot(vTemp,cData.vContactNormal) + cData.fBestrt;
+	dVector3Subtract(vCEdgePoint1,cData.vCylinderPos, vTemp);
+	dReal fRestDepth1 = -dVector3Dot(vTemp,cData.vContactNormal) + cData.fBestrt;
+	
+	dReal fDepth0 = cData.fBestDepth - (fRestDepth0);
+	dReal fDepth1 = cData.fBestDepth - (fRestDepth1);
+		  
+	// clamp depths to zero
+	if(fDepth0 < REAL(0.0) ) 
+	{
+		fDepth0 = REAL(0.0);
+	}
+
+	if(fDepth1<REAL(0.0)) 
+	{
+		fDepth1 = REAL(0.0);
+	}
+
+	// Generate contact 0
+	{
+		cData.gLocalContacts[cData.nContacts].fDepth = fDepth0;
+		dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
+		dVector3Copy(vCEdgePoint0,cData.gLocalContacts[cData.nContacts].vPos);
+		cData.gLocalContacts[cData.nContacts].nFlags = 1;
+		cData.nContacts++;
+		if(cData.nContacts >= (cData.iFlags & NUMC_MASK)) 
+			return true;
+	}
+
+	// Generate contact 1
+	{
+		// generate contacts
+		cData.gLocalContacts[cData.nContacts].fDepth = fDepth1;
+		dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
+		dVector3Copy(vCEdgePoint1,cData.gLocalContacts[cData.nContacts].vPos);
+		cData.gLocalContacts[cData.nContacts].nFlags = 1;
+		cData.nContacts++;		
+	}
+
+	return true;
+}
+
+void _cldClipCylinderToTriangle(sData& cData,const dVector3 &v0, const dVector3 &v1, const dVector3 &v2)
+{
+	int i = 0;
+	dVector3 avPoints[3];
+	dVector3 avTempArray1[nMAX_CYLINDER_TRIANGLE_CLIP_POINTS];
+	dVector3 avTempArray2[nMAX_CYLINDER_TRIANGLE_CLIP_POINTS];
+
+	dSetZero(&avTempArray1[0][0],nMAX_CYLINDER_TRIANGLE_CLIP_POINTS * 4);
+	dSetZero(&avTempArray2[0][0],nMAX_CYLINDER_TRIANGLE_CLIP_POINTS * 4);
+
+	// setup array of triangle vertices
+	dVector3Copy(v0,avPoints[0]);
+	dVector3Copy(v1,avPoints[1]);
+	dVector3Copy(v2,avPoints[2]);
+
+	dVector3 vCylinderCirclePos, vCylinderCircleNormal_Rel;
+	dSetZero(vCylinderCircleNormal_Rel,4);
+	// check which circle from cylinder we take for clipping
+	if ( dVector3Dot(cData.vCylinderAxis , cData.vContactNormal) > REAL(0.0)) 
+	{
+		// get top circle
+		vCylinderCirclePos[0] = cData.vCylinderPos[0] + cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[1] = cData.vCylinderPos[1] + cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[2] = cData.vCylinderPos[2] + cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+
+		vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(-1.0);
+	} 
+	else 
+	{
+		// get bottom circle
+		vCylinderCirclePos[0] = cData.vCylinderPos[0] - cData.vCylinderAxis[0]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[1] = cData.vCylinderPos[1] - cData.vCylinderAxis[1]*(cData.fCylinderSize*REAL(0.5));
+		vCylinderCirclePos[2] = cData.vCylinderPos[2] - cData.vCylinderAxis[2]*(cData.fCylinderSize*REAL(0.5));
+
+		vCylinderCircleNormal_Rel[nCYLINDER_AXIS] = REAL(1.0);
+	}
+
+	dVector3 vTemp;
+	dQuatInv(cData.qCylinderRot , cData.qInvCylinderRot);
+	// transform triangle points to space of cylinder circle
+	for(i=0; i<3; i++) 
+	{
+		dVector3Subtract(avPoints[i] , vCylinderCirclePos , vTemp);
+		dQuatTransform(cData.qInvCylinderRot,vTemp,avPoints[i]);
+	}
+
+	int iTmpCounter1 = 0;
+	int iTmpCounter2 = 0;
+	dVector4 plPlane;
+
+	// plane of cylinder that contains circle for intersection
+	//plPlane = Plane4f( vCylinderCircleNormal_Rel, 0.0f );
+	dConstructPlane(vCylinderCircleNormal_Rel,REAL(0.0),plPlane);
+	dClipPolyToPlane(avPoints, 3, avTempArray1, iTmpCounter1, plPlane);
+
+	// Body of base circle of Cylinder
+	int nCircleSegment = 0;
+	for (nCircleSegment = 0; nCircleSegment < nCYLINDER_CIRCLE_SEGMENTS; nCircleSegment++)
+	{
+		dConstructPlane(cData.avCylinderNormals[nCircleSegment],cData.fCylinderRadius,plPlane);
+
+		if (0 == (nCircleSegment % 2))
+		{
+			dClipPolyToPlane( avTempArray1 , iTmpCounter1 , avTempArray2, iTmpCounter2, plPlane);
+		}
+		else
+		{
+			dClipPolyToPlane( avTempArray2, iTmpCounter2, avTempArray1 , iTmpCounter1 , plPlane );
+		}
+
+		dIASSERT( iTmpCounter1 >= 0 && iTmpCounter1 <= nMAX_CYLINDER_TRIANGLE_CLIP_POINTS );
+		dIASSERT( iTmpCounter2 >= 0 && iTmpCounter2 <= nMAX_CYLINDER_TRIANGLE_CLIP_POINTS );
+	}
+
+	// back transform clipped points to absolute space
+	dReal ftmpdot;	
+	dReal fTempDepth;
+	dVector3 vPoint;
+
+	if (nCircleSegment %2)
+	{
+		for( i=0; i<iTmpCounter2; i++)
+		{
+			dQuatTransform(cData.qCylinderRot,avTempArray2[i], vPoint);
+			vPoint[0] += vCylinderCirclePos[0];
+			vPoint[1] += vCylinderCirclePos[1];
+			vPoint[2] += vCylinderCirclePos[2];
+
+			dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
+			ftmpdot	 = dFabs(dVector3Dot(vTemp, cData.vContactNormal));
+			fTempDepth = cData.fBestrt - ftmpdot;
+			// Depth must be positive
+			if (fTempDepth > REAL(0.0))
+			{
+				cData.gLocalContacts[cData.nContacts].fDepth = fTempDepth;
+				dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
+				dVector3Copy(vPoint,cData.gLocalContacts[cData.nContacts].vPos);
+				cData.gLocalContacts[cData.nContacts].nFlags = 1;
+				cData.nContacts++;
+				if(cData.nContacts >= (cData.iFlags & NUMC_MASK)) 
+					return;;
+			}
+		}
+	}
+	else
+	{
+		for( i=0; i<iTmpCounter1; i++)
+		{
+			dQuatTransform(cData.qCylinderRot,avTempArray1[i], vPoint);
+			vPoint[0] += vCylinderCirclePos[0];
+			vPoint[1] += vCylinderCirclePos[1];
+			vPoint[2] += vCylinderCirclePos[2];
+
+			dVector3Subtract(vPoint,cData.vCylinderPos,vTemp);
+			ftmpdot	 = dFabs(dVector3Dot(vTemp, cData.vContactNormal));
+			fTempDepth = cData.fBestrt - ftmpdot;
+			// Depth must be positive
+			if (fTempDepth > REAL(0.0))
+			{
+				cData.gLocalContacts[cData.nContacts].fDepth = fTempDepth;
+				dVector3Copy(cData.vContactNormal,cData.gLocalContacts[cData.nContacts].vNormal);
+				dVector3Copy(vPoint,cData.gLocalContacts[cData.nContacts].vPos);
+				cData.gLocalContacts[cData.nContacts].nFlags = 1;
+				cData.nContacts++;
+				if(cData.nContacts >= (cData.iFlags & NUMC_MASK)) 
+					return;;
+			}
+		}
+	}
+}
+
+void TestOneTriangleVsCylinder(   sData& cData, 
+								  const dVector3 &v0, 
+                                  const dVector3 &v1, 
+                                  const dVector3 &v2, 
+                                  const bool bDoubleSided)
+{
+
+	// calculate triangle normal
+	dVector3Subtract( v2 , v1 ,cData.vE1);
+	dVector3 vTemp;
+	dVector3Subtract( v0 , v1 ,vTemp);
+	dVector3Cross(cData.vE1 , vTemp , cData.vNormal );
+
+	dNormalize3( cData.vNormal);
+
+	// create plane from triangle
+	//Plane4f plTrianglePlane = Plane4f( vPolyNormal, v0 ); 
+	dReal plDistance = -dVector3Dot(v0, cData.vNormal);
+	dVector4 plTrianglePlane;
+	dConstructPlane( cData.vNormal,plDistance,plTrianglePlane);
+
+	 // calculate sphere distance to plane
+	dReal fDistanceCylinderCenterToPlane = dPointPlaneDistance(cData.vCylinderPos , plTrianglePlane);
+
+	// Sphere must be over positive side of triangle
+	if(fDistanceCylinderCenterToPlane < 0 && !bDoubleSided) 
+	{
+		// if not don't generate contacts
+		return;
+	 }
+
+	dVector3 vPnt0;
+	dVector3 vPnt1;
+	dVector3 vPnt2;
+
+	if (fDistanceCylinderCenterToPlane < REAL(0.0) )
+	{
+		// flip it
+		dVector3Copy(v0 , vPnt0);
+		dVector3Copy(v1 , vPnt2);
+		dVector3Copy(v2 , vPnt1);
+	}
+	else
+	{
+		dVector3Copy(v0 , vPnt0);
+		dVector3Copy(v1 , vPnt1);
+		dVector3Copy(v2 , vPnt2);
+	}
+
+	cData.fBestDepth = MAX_REAL;
+
+	// do intersection test and find best separating axis
+	if(!_cldTestSeparatingAxes(cData , vPnt0, vPnt1, vPnt2) ) 
+	{
+		// if not found do nothing
+		return;
+	}
+
+	// if best separation axis is not found
+	if ( cData.iBestAxis == 0 ) 
+	{
+		// this should not happen (we should already exit in that case)
+		dIASSERT(false);
+		// do nothing
+		return;
+	}
+
+	dReal fdot = dVector3Dot( cData.vContactNormal , cData.vCylinderAxis );
+
+	// choose which clipping method are we going to apply
+	if (dFabs(fdot) < REAL(0.9) ) 
+	{
+		if (!_cldClipCylinderEdgeToTriangle(cData ,vPnt0, vPnt1, vPnt2)) 
+		{
+			return;
+		}
+	}
+	else 
+	{
+		_cldClipCylinderToTriangle(cData ,vPnt0, vPnt1, vPnt2);
+	}
+
+}
+
+void _InitCylinderTrimeshData(sData& cData)
+{
+	// get cylinder information
+	// Rotation
+	const dReal* pRotCyc = dGeomGetRotation(cData.gCylinder); 
+	dMatrix3Copy(pRotCyc,cData.mCylinderRot);
+	dGeomGetQuaternion(cData.gCylinder,cData.qCylinderRot);
+	
+	// Position
+	const dVector3* pPosCyc = (const dVector3*)dGeomGetPosition(cData.gCylinder);
+	dVector3Copy(*pPosCyc,cData.vCylinderPos);
+	// Cylinder axis
+	dMat3GetCol(cData.mCylinderRot,nCYLINDER_AXIS,cData.vCylinderAxis);
+	// get cylinder radius and size
+	dGeomCylinderGetParams(cData.gCylinder,&cData.fCylinderRadius,&cData.fCylinderSize);
+	
+	// get trimesh position and orientation
+	const dReal* pRotTris = dGeomGetRotation(cData.gTrimesh); 
+	dMatrix3Copy(pRotTris,cData.mTrimeshRot);
+	dGeomGetQuaternion(cData.gTrimesh,cData.qTrimeshRot);
+	
+	// Position
+	const dVector3* pPosTris = (const dVector3*)dGeomGetPosition(cData.gTrimesh);
+	dVector3Copy(*pPosTris,cData.vTrimeshPos);
+
+
+	// calculate basic angle for 8-gon
+	dReal fAngle = M_PI / nCYLINDER_CIRCLE_SEGMENTS;
+	// calculate angle increment
+	dReal fAngleIncrement = fAngle*REAL(2.0); 
+
+	// calculate plane normals
+	// axis dependant code
+	for(int i=0; i<nCYLINDER_CIRCLE_SEGMENTS; i++) 
+	{
+		cData.avCylinderNormals[i][0] = -dCos(fAngle);
+		cData.avCylinderNormals[i][1] = -dSin(fAngle);
+		cData.avCylinderNormals[i][2] = REAL(0.0);
+
+		fAngle += fAngleIncrement;
+	}
+
+	dSetZero(cData.vBestPoint,4);
+	// reset best depth
+	cData.fBestCenter = REAL(0.0);	
+}
+
+#if dTRIMESH_ENABLED
+
+// OPCODE version of cylinder to mesh collider
+#if dTRIMESH_OPCODE
+int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT( skip >= (int)sizeof( dContactGeom ) );
+	dIASSERT( o1->type == dCylinderClass );
+	dIASSERT( o2->type == dTriMeshClass );
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	// Main data holder
+	sData cData;
+
+	// Assign ODE stuff
+	cData.gCylinder	 = o1;
+	cData.gTrimesh	 = (dxTriMesh*)o2;
+	cData.iFlags	 = flags;
+	cData.iSkip		 = skip;
+	cData.gContact	 = contact;
+	cData.nContacts  = 0;
+
+	_InitCylinderTrimeshData(cData);
+
+	OBBCollider& Collider = cData.gTrimesh->_OBBCollider;
+
+	Point cCenter(cData.vCylinderPos[0],cData.vCylinderPos[1],cData.vCylinderPos[2]);
+
+	Point cExtents(cData.fCylinderRadius,cData.fCylinderRadius,cData.fCylinderRadius);
+	cExtents[nCYLINDER_AXIS] = cData.fCylinderSize * REAL(0.5);
+
+	Matrix3x3 obbRot;
+
+	// It is a potential issue to explicitly cast to float 
+	// if custom width floating point type is introduced in OPCODE.
+	// It is necessary to make a typedef and cast to it
+	// (e.g. typedef float opc_float;)
+	// However I'm not sure in what header it should be added.
+
+	obbRot[0][0] = /*(float)*/cData.mCylinderRot[0];
+	obbRot[1][0] = /*(float)*/cData.mCylinderRot[1];
+	obbRot[2][0] = /*(float)*/cData.mCylinderRot[2];
+
+	obbRot[0][1] = /*(float)*/cData.mCylinderRot[4];
+	obbRot[1][1] = /*(float)*/cData.mCylinderRot[5];
+	obbRot[2][1] = /*(float)*/cData.mCylinderRot[6];
+
+	obbRot[0][2] = /*(float)*/cData.mCylinderRot[8];
+	obbRot[1][2] = /*(float)*/cData.mCylinderRot[9];
+	obbRot[2][2] = /*(float)*/cData.mCylinderRot[10];
+
+	OBB obbCapsule(cCenter,cExtents,obbRot);
+
+	Matrix4x4 CapsuleMatrix;
+	MakeMatrix(cData.vCylinderPos, cData.mCylinderRot, CapsuleMatrix);
+
+	Matrix4x4 MeshMatrix;
+	MakeMatrix(cData.vTrimeshPos, cData.mTrimeshRot, MeshMatrix);
+
+	// TC results
+	if (cData.gTrimesh->doBoxTC) 
+	{
+		dxTriMesh::BoxTC* BoxTC = 0;
+		for (int i = 0; i < cData.gTrimesh->BoxTCCache.size(); i++)
+		{
+			if (cData.gTrimesh->BoxTCCache[i].Geom == cData.gCylinder)
+			{
+				BoxTC = &cData.gTrimesh->BoxTCCache[i];
+				break;
+			}
+		}
+		if (!BoxTC)
+		{
+			cData.gTrimesh->BoxTCCache.push(dxTriMesh::BoxTC());
+
+			BoxTC = &cData.gTrimesh->BoxTCCache[cData.gTrimesh->BoxTCCache.size() - 1];
+			BoxTC->Geom = cData.gCylinder;
+			BoxTC->FatCoeff = REAL(1.0);
+		}
+
+		// Intersect
+		Collider.SetTemporalCoherence(true);
+		Collider.Collide(*BoxTC, obbCapsule, cData.gTrimesh->Data->BVTree, null, &MeshMatrix);
+	}
+	else 
+	{
+		Collider.SetTemporalCoherence(false);
+		Collider.Collide(dxTriMesh::defaultBoxCache, obbCapsule, cData.gTrimesh->Data->BVTree, null,&MeshMatrix);
+	}
+
+	// Retrieve data
+	int TriCount = Collider.GetNbTouchedPrimitives();
+	const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
+
+
+	if (TriCount != 0)
+	{
+		if (cData.gTrimesh->ArrayCallback != null)
+		{
+			cData.gTrimesh->ArrayCallback(cData.gTrimesh, cData.gCylinder, Triangles, TriCount);
+		}
+
+		// allocate buffer for local contacts on stack
+		cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK));
+
+	    int ctContacts0 = 0;
+
+		// loop through all intersecting triangles
+		for (int i = 0; i < TriCount; i++)
+		{
+			const int Triint = Triangles[i];
+			if (!Callback(cData.gTrimesh, cData.gCylinder, Triint)) continue;
+
+
+			dVector3 dv[3];
+			FetchTriangle(cData.gTrimesh, Triint, cData.vTrimeshPos, cData.mTrimeshRot, dv);
+			
+			// test this triangle
+			TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false);
+
+			// fill-in tri index for generated contacts
+			for (; ctContacts0<cData.nContacts; ctContacts0++)
+				cData.gLocalContacts[ctContacts0].triIndex = Triint;
+
+			// Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
+			if(cData.nContacts	>= (cData.iFlags & NUMC_MASK))
+			{
+				break;
+			}
+		}
+	}
+
+	return _ProcessLocalContacts(cData);
+}
+#endif
+
+// GIMPACT version of cylinder to mesh collider
+#if dTRIMESH_GIMPACT
+int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT( skip >= (int)sizeof( dContactGeom ) );
+	dIASSERT( o1->type == dCylinderClass );
+	dIASSERT( o2->type == dTriMeshClass );
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+	
+	// Main data holder
+	sData cData;
+
+	// Assign ODE stuff
+	cData.gCylinder	 = o1;
+	cData.gTrimesh	 = (dxTriMesh*)o2;
+	cData.iFlags	 = flags;
+	cData.iSkip		 = skip;
+	cData.gContact	 = contact;
+	cData.nContacts  = 0;
+
+	_InitCylinderTrimeshData(cData);
+
+//*****at first , collide box aabb******//
+
+	aabb3f test_aabb;
+
+	test_aabb.minX = o1->aabb[0];
+	test_aabb.maxX = o1->aabb[1];
+	test_aabb.minY = o1->aabb[2];
+	test_aabb.maxY = o1->aabb[3];
+	test_aabb.minZ = o1->aabb[4];
+	test_aabb.maxZ = o1->aabb[5];
+
+
+	GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_BOXQUERY_LIST(collision_result);
+
+	gim_aabbset_box_collision(&test_aabb, &cData.gTrimesh->m_collision_trimesh.m_aabbset , &collision_result);
+
+	if(collision_result.m_size==0)
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	    return 0;
+	}
+//*****Set globals for box collision******//
+
+	int ctContacts0 = 0;
+	cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK));
+
+	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
+	GIM_TRIMESH * ptrimesh = &cData.gTrimesh->m_collision_trimesh;
+
+	gim_trimesh_locks_work_data(ptrimesh);
+
+
+	for(unsigned int i=0;i<collision_result.m_size;i++)
+	{
+		const int Triint = boxesresult[i];
+		
+		dVector3 dv[3];
+		gim_trimesh_get_triangle_vertices(ptrimesh, Triint,dv[0],dv[1],dv[2]);
+        // test this triangle
+        TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false);
+
+        // fill-in triangle index for generated contacts
+        for (; ctContacts0<cData.nContacts; ctContacts0++)
+            cData.gLocalContacts[ctContacts0].triIndex =  Triint;
+
+		// Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
+		if(cData.nContacts	>= (cData.iFlags & NUMC_MASK))
+        {
+            break;
+        }
+	}
+
+	gim_trimesh_unlocks_work_data(ptrimesh);
+	GIM_DYNARRAY_DESTROY(collision_result);
+
+	return _ProcessLocalContacts(cData);
+}
+#endif
+
+#endif // dTRIMESH_ENABLED
+
+
Index: /code/branches/ode/ode-0.9/ode/src/collision_kernel.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_kernel.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_kernel.cpp	(revision 216)
@@ -0,0 +1,1103 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+core collision functions and data structures, plus part of the public API
+for geometry objects
+
+*/
+
+#include <ode/common.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/objects.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_util.h"
+#include "collision_std.h"
+#include "collision_transform.h"
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_GIMPACT
+#include <GIMPACT/gimpact.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// helper functions for dCollide()ing a space with another geom
+
+// this struct records the parameters passed to dCollideSpaceGeom()
+
+// Allocate and free posr - we cache a single posr to avoid thrashing
+static dxPosR* s_cachedPosR = 0;
+
+dxPosR* dAllocPosr()
+{
+	dxPosR* retPosR;
+	if (s_cachedPosR)
+	{
+		retPosR = s_cachedPosR;
+		s_cachedPosR = 0;
+	}
+	else
+	{
+		retPosR = (dxPosR*) dAlloc (sizeof(dxPosR));
+	}
+	return retPosR;
+}
+
+void dFreePosr(dxPosR* oldPosR)
+{
+	if (oldPosR)
+	{
+		if (s_cachedPosR)
+		{
+			dFree(s_cachedPosR, sizeof(dxPosR));
+		}
+		s_cachedPosR = oldPosR;
+	}
+}
+
+void dClearPosrCache(void)
+{
+	if (s_cachedPosR)
+	{
+		dFree(s_cachedPosR, sizeof(dxPosR));
+		s_cachedPosR = 0;
+	}
+}
+
+struct SpaceGeomColliderData {
+  int flags;			// space left in contacts array
+  dContactGeom *contact;
+  int skip;
+};
+
+
+static void space_geom_collider (void *data, dxGeom *o1, dxGeom *o2)
+{
+  SpaceGeomColliderData *d = (SpaceGeomColliderData*) data;
+  if (d->flags & NUMC_MASK) {
+    int n = dCollide (o1,o2,d->flags,d->contact,d->skip);
+    d->contact = CONTACT (d->contact,d->skip*n);
+    d->flags -= n;
+  }
+}
+
+
+static int dCollideSpaceGeom (dxGeom *o1, dxGeom *o2, int flags,
+			      dContactGeom *contact, int skip)
+{
+  SpaceGeomColliderData data;
+  data.flags = flags;
+  data.contact = contact;
+  data.skip = skip;
+  dSpaceCollide2 (o1,o2,&data,&space_geom_collider);
+  return (flags & NUMC_MASK) - (data.flags & NUMC_MASK);
+}
+
+//****************************************************************************
+// dispatcher for the N^2 collider functions
+
+// function pointers and modes for n^2 class collider functions
+
+struct dColliderEntry {
+  dColliderFn *fn;	// collider function, 0 = no function available
+  int reverse;		// 1 = reverse o1 and o2
+};
+static dColliderEntry colliders[dGeomNumClasses][dGeomNumClasses];
+static int colliders_initialized = 0;
+
+
+// setCollider() will refuse to write over a collider entry once it has
+// been written.
+
+static void setCollider (int i, int j, dColliderFn *fn)
+{
+  if (colliders[i][j].fn == 0) {
+    colliders[i][j].fn = fn;
+    colliders[i][j].reverse = 0;
+  }
+  if (colliders[j][i].fn == 0) {
+    colliders[j][i].fn = fn;
+    colliders[j][i].reverse = 1;
+  }
+}
+
+
+static void setAllColliders (int i, dColliderFn *fn)
+{
+  for (int j=0; j<dGeomNumClasses; j++) setCollider (i,j,fn);
+}
+
+
+static void initColliders()
+{
+  int i,j;
+
+  if (colliders_initialized) return;
+  colliders_initialized = 1;
+
+  memset (colliders,0,sizeof(colliders));
+
+  // setup space colliders
+  for (i=dFirstSpaceClass; i <= dLastSpaceClass; i++) {
+    for (j=0; j < dGeomNumClasses; j++) {
+      setCollider (i,j,&dCollideSpaceGeom);
+    }
+  }
+
+  setCollider (dSphereClass,dSphereClass,&dCollideSphereSphere);
+  setCollider (dSphereClass,dBoxClass,&dCollideSphereBox);
+  setCollider (dSphereClass,dPlaneClass,&dCollideSpherePlane);
+  setCollider (dBoxClass,dBoxClass,&dCollideBoxBox);
+  setCollider (dBoxClass,dPlaneClass,&dCollideBoxPlane);
+  setCollider (dCapsuleClass,dSphereClass,&dCollideCapsuleSphere);
+  setCollider (dCapsuleClass,dBoxClass,&dCollideCapsuleBox);
+  setCollider (dCapsuleClass,dCapsuleClass,&dCollideCapsuleCapsule);
+  setCollider (dCapsuleClass,dPlaneClass,&dCollideCapsulePlane);
+  setCollider (dRayClass,dSphereClass,&dCollideRaySphere);
+  setCollider (dRayClass,dBoxClass,&dCollideRayBox);
+  setCollider (dRayClass,dCapsuleClass,&dCollideRayCapsule);
+  setCollider (dRayClass,dPlaneClass,&dCollideRayPlane);
+  setCollider (dRayClass,dCylinderClass,&dCollideRayCylinder);
+#if dTRIMESH_ENABLED
+  setCollider (dTriMeshClass,dSphereClass,&dCollideSTL);
+  setCollider (dTriMeshClass,dBoxClass,&dCollideBTL);
+  setCollider (dTriMeshClass,dRayClass,&dCollideRTL);
+  setCollider (dTriMeshClass,dTriMeshClass,&dCollideTTL);
+  setCollider (dTriMeshClass,dCapsuleClass,&dCollideCCTL);
+  setCollider (dTriMeshClass,dPlaneClass,&dCollideTrimeshPlane);
+  setCollider (dCylinderClass,dTriMeshClass,&dCollideCylinderTrimesh);
+#endif
+  setCollider (dCylinderClass,dBoxClass,&dCollideCylinderBox);
+  setCollider (dCylinderClass,dSphereClass,&dCollideCylinderSphere);
+  setCollider (dCylinderClass,dPlaneClass,&dCollideCylinderPlane);
+  //setCollider (dCylinderClass,dCylinderClass,&dCollideCylinderCylinder);
+
+//--> Convex Collision
+  setCollider (dConvexClass,dPlaneClass,&dCollideConvexPlane);
+  setCollider (dSphereClass,dConvexClass,&dCollideSphereConvex);
+  setCollider (dConvexClass,dBoxClass,&dCollideConvexBox);
+  setCollider (dConvexClass,dCapsuleClass,&dCollideConvexCapsule);
+  setCollider (dConvexClass,dConvexClass,&dCollideConvexConvex);
+  setCollider (dRayClass,dConvexClass,&dCollideRayConvex);
+//<-- Convex Collision
+
+//--> dHeightfield Collision
+  setCollider (dHeightfieldClass,dRayClass,&dCollideHeightfield);
+  setCollider (dHeightfieldClass,dSphereClass,&dCollideHeightfield);
+  setCollider (dHeightfieldClass,dBoxClass,&dCollideHeightfield);
+  setCollider (dHeightfieldClass,dCapsuleClass,&dCollideHeightfield);
+  setCollider (dHeightfieldClass,dCylinderClass,&dCollideHeightfield);
+  setCollider (dHeightfieldClass,dConvexClass,&dCollideHeightfield);
+#if dTRIMESH_ENABLED
+  setCollider (dHeightfieldClass,dTriMeshClass,&dCollideHeightfield);
+#endif
+//<-- dHeightfield Collision
+
+  setAllColliders (dGeomTransformClass,&dCollideTransform);
+}
+
+
+/*
+ *	NOTE!
+ *	If it is necessary to add special processing mode without contact generation
+ *	use NULL contact parameter value as indicator, not zero in flags.
+ */
+int dCollide (dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact,
+	      int skip)
+{
+  dAASSERT(o1 && o2 && contact);
+  dUASSERT(colliders_initialized,"colliders array not initialized");
+  dUASSERT(o1->type >= 0 && o1->type < dGeomNumClasses,"bad o1 class number");
+  dUASSERT(o2->type >= 0 && o2->type < dGeomNumClasses,"bad o2 class number");
+  // Even though comparison for greater or equal to one is used in all the 
+  // other places, here it is more logical to check for greater than zero
+  // because function does not require any specific number of contact slots - 
+  // it must be just a positive.
+  dUASSERT((flags & NUMC_MASK) > 0, "no contacts requested"); 
+
+  // Extra precaution for zero contact count in parameters
+  if ((flags & NUMC_MASK) == 0) return 0;
+  // no contacts if both geoms are the same
+  if (o1 == o2) return 0;
+
+  // no contacts if both geoms on the same body, and the body is not 0
+  if (o1->body == o2->body && o1->body) return 0;
+
+  o1->recomputePosr();
+  o2->recomputePosr();
+
+  dColliderEntry *ce = &colliders[o1->type][o2->type];
+  int count = 0;
+  if (ce->fn) {
+    if (ce->reverse) {
+      count = (*ce->fn) (o2,o1,flags,contact,skip);
+      for (int i=0; i<count; i++) {
+	dContactGeom *c = CONTACT(contact,skip*i);
+	c->normal[0] = -c->normal[0];
+	c->normal[1] = -c->normal[1];
+	c->normal[2] = -c->normal[2];
+	dxGeom *tmp = c->g1;
+	c->g1 = c->g2;
+	c->g2 = tmp;
+	int tmpint = c->side1;
+	c->side1 = c->side2;
+	c->side2 = tmpint;
+      }
+    }
+    else {
+      count = (*ce->fn) (o1,o2,flags,contact,skip);
+    }
+  }
+  return count;
+}
+
+//****************************************************************************
+// dxGeom
+
+dxGeom::dxGeom (dSpaceID _space, int is_placeable)
+{
+  initColliders();
+
+  // setup body vars. invalid type of -1 must be changed by the constructor.
+  type = -1;
+  gflags = GEOM_DIRTY | GEOM_AABB_BAD | GEOM_ENABLED;
+  if (is_placeable) gflags |= GEOM_PLACEABLE;
+  data = 0;
+  body = 0;
+  body_next = 0;
+  if (is_placeable) {
+	final_posr = dAllocPosr();
+    dSetZero (final_posr->pos,4);
+    dRSetIdentity (final_posr->R);
+  }
+  else {
+    final_posr = 0;
+  }
+  offset_posr = 0;
+
+  // setup space vars
+  next = 0;
+  tome = 0;
+  parent_space = 0;
+  dSetZero (aabb,6);
+  category_bits = ~0;
+  collide_bits = ~0;
+
+  // put this geom in a space if required
+  if (_space) dSpaceAdd (_space,this);
+}
+
+
+dxGeom::~dxGeom()
+{
+   if (parent_space) dSpaceRemove (parent_space,this);
+   if ((gflags & GEOM_PLACEABLE) && (!body || (body && offset_posr)))
+     dFreePosr(final_posr);
+   if (offset_posr) dFreePosr(offset_posr);
+   bodyRemove();
+}
+
+
+int dxGeom::AABBTest (dxGeom *o, dReal aabb[6])
+{
+  return 1;
+}
+
+
+void dxGeom::bodyRemove()
+{
+  if (body) {
+    // delete this geom from body list
+    dxGeom **last = &body->geom, *g = body->geom;
+    while (g) {
+      if (g == this) {
+	*last = g->body_next;
+	break;
+      }
+      last = &g->body_next;
+      g = g->body_next;
+    }
+    body = 0;
+    body_next = 0;
+  }
+}
+
+inline void myswap(dReal& a, dReal& b) { dReal t=b; b=a; a=t; }
+
+
+inline void matrixInvert(const dMatrix3& inMat, dMatrix3& outMat)
+{
+	memcpy(outMat, inMat, sizeof(dMatrix3));
+	// swap _12 and _21
+	myswap(outMat[0 + 4*1], outMat[1 + 4*0]);
+	// swap _31 and _13
+	myswap(outMat[2 + 4*0], outMat[0 + 4*2]);
+	// swap _23 and _32
+	myswap(outMat[1 + 4*2], outMat[2 + 4*1]);
+}
+
+void getBodyPosr(const dxPosR& offset_posr, const dxPosR& final_posr, dxPosR& body_posr)
+{
+	dMatrix3 inv_offset;
+	matrixInvert(offset_posr.R, inv_offset);
+
+	dMULTIPLY0_333(body_posr.R, final_posr.R, inv_offset);
+	dVector3 world_offset;
+	dMULTIPLY0_331(world_offset, body_posr.R, offset_posr.pos);
+	body_posr.pos[0] = final_posr.pos[0] - world_offset[0];
+	body_posr.pos[1] = final_posr.pos[1] - world_offset[1];
+	body_posr.pos[2] = final_posr.pos[2] - world_offset[2];
+}
+
+void getWorldOffsetPosr(const dxPosR& body_posr, const dxPosR& world_posr, dxPosR& offset_posr)
+{
+	dMatrix3 inv_body;
+	matrixInvert(body_posr.R, inv_body);
+
+	dMULTIPLY0_333(offset_posr.R, inv_body, world_posr.R);
+	dVector3 world_offset;
+	world_offset[0] = world_posr.pos[0] - body_posr.pos[0];
+	world_offset[1] = world_posr.pos[1] - body_posr.pos[1];
+	world_offset[2] = world_posr.pos[2] - body_posr.pos[2];
+	dMULTIPLY0_331(offset_posr.pos, inv_body, world_offset);
+}
+
+void dxGeom::computePosr()
+{
+  // should only be recalced if we need to - ie offset from a body
+  dIASSERT(offset_posr);  
+  dIASSERT(body);
+  
+  dMULTIPLY0_331 (final_posr->pos,body->posr.R,offset_posr->pos);
+  final_posr->pos[0] += body->posr.pos[0];
+  final_posr->pos[1] += body->posr.pos[1];
+  final_posr->pos[2] += body->posr.pos[2];
+  dMULTIPLY0_333 (final_posr->R,body->posr.R,offset_posr->R);
+}
+
+//****************************************************************************
+// misc
+
+dxGeom *dGeomGetBodyNext (dxGeom *geom)
+{
+  return geom->body_next;
+}
+
+//****************************************************************************
+// public API for geometry objects
+
+#define CHECK_NOT_LOCKED(space) \
+  dUASSERT (!(space && space->lock_count), \
+	    "invalid operation for geom in locked space");
+
+
+void dGeomDestroy (dxGeom *g)
+{
+  dAASSERT (g);
+  delete g;
+}
+
+
+void dGeomSetData (dxGeom *g, void *data)
+{
+  dAASSERT (g);
+  g->data = data;
+}
+
+
+void *dGeomGetData (dxGeom *g)
+{
+  dAASSERT (g);
+  return g->data;
+}
+
+
+void dGeomSetBody (dxGeom *g, dxBody *b)
+{
+  dAASSERT (g);
+  dUASSERT (b == NULL || (g->gflags & GEOM_PLACEABLE),"geom must be placeable");
+  CHECK_NOT_LOCKED (g->parent_space);
+
+  if (b) {
+    if (!g->body) dFreePosr(g->final_posr);
+    if (g->body != b) {
+      if (g->offset_posr) {
+        dFreePosr(g->offset_posr);
+        g->offset_posr = 0;
+      }
+      g->final_posr = &b->posr;
+      g->bodyRemove();
+      g->bodyAdd (b);
+    }
+    dGeomMoved (g);
+  }
+  else {
+    if (g->body) {
+      if (g->offset_posr)
+      {
+        // if we're offset, we already have our own final position, make sure its updated
+        g->recomputePosr();
+        dFreePosr(g->offset_posr);
+        g->offset_posr = 0;
+      }
+      else
+      {
+        g->final_posr = dAllocPosr();
+        memcpy (g->final_posr->pos,g->body->posr.pos,sizeof(dVector3));
+        memcpy (g->final_posr->R,g->body->posr.R,sizeof(dMatrix3));
+      }
+      g->bodyRemove();
+    }
+    // dGeomMoved() should not be called if the body is being set to 0, as the
+    // new position of the geom is set to the old position of the body, so the
+    // effective position of the geom remains unchanged.
+  }
+}
+
+
+dBodyID dGeomGetBody (dxGeom *g)
+{
+  dAASSERT (g);
+  return g->body;
+}
+
+
+void dGeomSetPosition (dxGeom *g, dReal x, dReal y, dReal z)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (g->offset_posr) {
+    // move body such that body+offset = position
+	dVector3 world_offset;
+	dMULTIPLY0_331(world_offset, g->body->posr.R, g->offset_posr->pos);
+	dBodySetPosition(g->body,
+	    x - world_offset[0],
+	    y - world_offset[1],
+	    z - world_offset[2]);
+  }
+  else if (g->body) {
+    // this will call dGeomMoved (g), so we don't have to
+    dBodySetPosition (g->body,x,y,z);
+  }
+  else {
+    g->final_posr->pos[0] = x;
+    g->final_posr->pos[1] = y;
+    g->final_posr->pos[2] = z;
+    dGeomMoved (g);
+  }
+}
+
+
+void dGeomSetRotation (dxGeom *g, const dMatrix3 R)
+{
+  dAASSERT (g && R);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (g->offset_posr) {
+    g->recomputePosr();
+    // move body such that body+offset = rotation
+    dxPosR new_final_posr;
+    dxPosR new_body_posr;
+    memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
+    memcpy(new_final_posr.R, R, sizeof(dMatrix3));
+    getBodyPosr(*g->offset_posr, new_final_posr, new_body_posr);
+    dBodySetRotation(g->body, new_body_posr.R);
+    dBodySetPosition(g->body, new_body_posr.pos[0], new_body_posr.pos[1], new_body_posr.pos[2]);
+  }
+  else if (g->body) {
+    // this will call dGeomMoved (g), so we don't have to
+    dBodySetRotation (g->body,R);
+  }
+  else {
+    memcpy (g->final_posr->R,R,sizeof(dMatrix3));
+    dGeomMoved (g);
+  }
+}
+
+
+void dGeomSetQuaternion (dxGeom *g, const dQuaternion quat)
+{
+  dAASSERT (g && quat);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (g->offset_posr) {
+    g->recomputePosr();
+    // move body such that body+offset = rotation
+    dxPosR new_final_posr;
+    dxPosR new_body_posr;
+    dQtoR (quat, new_final_posr.R);
+    memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
+    
+    getBodyPosr(*g->offset_posr, new_final_posr, new_body_posr);
+    dBodySetRotation(g->body, new_body_posr.R);
+    dBodySetPosition(g->body, new_body_posr.pos[0], new_body_posr.pos[1], new_body_posr.pos[2]);
+  }
+  if (g->body) {
+    // this will call dGeomMoved (g), so we don't have to
+    dBodySetQuaternion (g->body,quat);
+  }
+  else {
+    dQtoR (quat, g->final_posr->R);
+    dGeomMoved (g);
+  }
+}
+
+
+const dReal * dGeomGetPosition (dxGeom *g)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  g->recomputePosr();
+  return g->final_posr->pos;
+}
+
+
+void dGeomCopyPosition(dxGeom *g, dVector3 pos)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  g->recomputePosr();
+  const dReal* src = g->final_posr->pos;
+  pos[0] = src[0];
+  pos[1] = src[1];
+  pos[2] = src[2];
+}
+
+
+const dReal * dGeomGetRotation (dxGeom *g)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  g->recomputePosr();
+  return g->final_posr->R;
+}
+
+
+void dGeomCopyRotation(dxGeom *g, dMatrix3 R)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  g->recomputePosr();
+  const dReal* src = g->final_posr->R;
+  R[0]  = src[0];
+  R[1]  = src[1];
+  R[2]  = src[2];
+  R[4]  = src[4];
+  R[5]  = src[5];
+  R[6]  = src[6];
+  R[8]  = src[8];
+  R[9]  = src[9];
+  R[10] = src[10];
+}
+
+
+void dGeomGetQuaternion (dxGeom *g, dQuaternion quat)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  if (g->body && !g->offset_posr) {
+    const dReal * body_quat = dBodyGetQuaternion (g->body);
+    quat[0] = body_quat[0];
+    quat[1] = body_quat[1];
+    quat[2] = body_quat[2];
+    quat[3] = body_quat[3];
+  }
+  else {
+    g->recomputePosr();
+    dRtoQ (g->final_posr->R, quat);
+  }
+}
+
+
+void dGeomGetAABB (dxGeom *g, dReal aabb[6])
+{
+  dAASSERT (g);
+  dAASSERT (aabb);
+  g->recomputeAABB();
+  memcpy (aabb,g->aabb,6 * sizeof(dReal));
+}
+
+
+int dGeomIsSpace (dxGeom *g)
+{
+  dAASSERT (g);
+  return IS_SPACE(g);
+}
+
+
+dSpaceID dGeomGetSpace (dxGeom *g)
+{
+  dAASSERT (g);
+  return g->parent_space;
+}
+
+
+int dGeomGetClass (dxGeom *g)
+{
+  dAASSERT (g);
+  return g->type;
+}
+
+
+void dGeomSetCategoryBits (dxGeom *g, unsigned long bits)
+{
+  dAASSERT (g);
+  CHECK_NOT_LOCKED (g->parent_space);
+  g->category_bits = bits;
+}
+
+
+void dGeomSetCollideBits (dxGeom *g, unsigned long bits)
+{
+  dAASSERT (g);
+  CHECK_NOT_LOCKED (g->parent_space);
+  g->collide_bits = bits;
+}
+
+
+unsigned long dGeomGetCategoryBits (dxGeom *g)
+{
+  dAASSERT (g);
+  return g->category_bits;
+}
+
+
+unsigned long dGeomGetCollideBits (dxGeom *g)
+{
+  dAASSERT (g);
+  return g->collide_bits;
+}
+
+
+void dGeomEnable (dxGeom *g)
+{
+	dAASSERT (g);
+	g->gflags |= GEOM_ENABLED;
+}
+
+void dGeomDisable (dxGeom *g)
+{
+	dAASSERT (g);
+	g->gflags &= ~GEOM_ENABLED;
+}
+
+int dGeomIsEnabled (dxGeom *g)
+{
+	dAASSERT (g);
+	return (g->gflags & GEOM_ENABLED) != 0;
+}
+
+
+//****************************************************************************
+// C interface that lets the user make new classes. this interface is a lot
+// more cumbersome than C++ subclassing, which is what is used internally
+// in ODE. this API is mainly to support legacy code.
+
+static int num_user_classes = 0;
+static dGeomClass user_classes [dMaxUserClasses];
+
+
+struct dxUserGeom : public dxGeom {
+  void *user_data;
+
+  dxUserGeom (int class_num);
+  ~dxUserGeom();
+  void computeAABB();
+  int AABBTest (dxGeom *o, dReal aabb[6]);
+};
+
+
+dxUserGeom::dxUserGeom (int class_num) : dxGeom (0,1)
+{
+  type = class_num;
+  int size = user_classes[type-dFirstUserClass].bytes;
+  user_data = dAlloc (size);
+  memset (user_data,0,size);
+}
+
+
+dxUserGeom::~dxUserGeom()
+{
+  dGeomClass *c = &user_classes[type-dFirstUserClass];
+  if (c->dtor) c->dtor (this);
+  dFree (user_data,c->bytes);
+}
+
+
+void dxUserGeom::computeAABB()
+{
+  user_classes[type-dFirstUserClass].aabb (this,aabb);
+}
+
+
+int dxUserGeom::AABBTest (dxGeom *o, dReal aabb[6])
+{
+  dGeomClass *c = &user_classes[type-dFirstUserClass];
+  if (c->aabb_test) return c->aabb_test (this,o,aabb);
+  else return 1;
+}
+
+
+static int dCollideUserGeomWithGeom (dxGeom *o1, dxGeom *o2, int flags,
+				     dContactGeom *contact, int skip)
+{
+  // this generic collider function is called the first time that a user class
+  // tries to collide against something. it will find out the correct collider
+  // function and then set the colliders array so that the correct function is
+  // called directly the next time around.
+
+  int t1 = o1->type;	// note that o1 is a user geom
+  int t2 = o2->type;	// o2 *may* be a user geom
+
+  // find the collider function to use. if o1 does not know how to collide with
+  // o2, then o2 might know how to collide with o1 (provided that it is a user
+  // geom).
+  dColliderFn *fn = user_classes[t1-dFirstUserClass].collider (t2);
+  int reverse = 0;
+  if (!fn && t2 >= dFirstUserClass && t2 <= dLastUserClass) {
+    fn = user_classes[t2-dFirstUserClass].collider (t1);
+    reverse = 1;
+  }
+
+  // set the colliders array so that the correct function is called directly
+  // the next time around. note that fn can be 0 here if no collider was found,
+  // which means that dCollide() will always return 0 for this case.
+  colliders[t1][t2].fn = fn;
+  colliders[t1][t2].reverse = reverse;
+  colliders[t2][t1].fn = fn;
+  colliders[t2][t1].reverse = !reverse;
+
+  // now call the collider function indirectly through dCollide(), so that
+  // contact reversing is properly handled.
+  return dCollide (o1,o2,flags,contact,skip);
+}
+
+
+int dCreateGeomClass (const dGeomClass *c)
+{
+  dUASSERT(c && c->bytes >= 0 && c->collider && c->aabb,"bad geom class");
+
+  if (num_user_classes >= dMaxUserClasses) {
+    dDebug (0,"too many user classes, you must increase the limit and "
+	      "recompile ODE");
+  }
+  user_classes[num_user_classes] = *c;
+  int class_number = num_user_classes + dFirstUserClass;
+  initColliders();
+  setAllColliders (class_number,&dCollideUserGeomWithGeom);
+
+  num_user_classes++;
+  return class_number;
+}
+
+
+void * dGeomGetClassData (dxGeom *g)
+{
+  dUASSERT (g && g->type >= dFirstUserClass &&
+	    g->type <= dLastUserClass,"not a custom class");
+  dxUserGeom *user = (dxUserGeom*) g;
+  return user->user_data;
+}
+
+
+dGeomID dCreateGeom (int classnum)
+{
+  dUASSERT (classnum >= dFirstUserClass &&
+	    classnum <= dLastUserClass,"not a custom class");
+  return new dxUserGeom (classnum);
+}
+
+
+
+/* ************************************************************************ */
+/* geom offset from body */
+
+void dGeomCreateOffset (dxGeom *g)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  if (g->offset_posr)
+  {
+	return; // already created
+  }
+  dIASSERT (g->final_posr == &g->body->posr);
+  
+  g->final_posr = dAllocPosr();
+  g->offset_posr = dAllocPosr();
+  dSetZero (g->offset_posr->pos,4);
+  dRSetIdentity (g->offset_posr->R);
+  
+  g->gflags |= GEOM_POSR_BAD;
+}
+
+void dGeomSetOffsetPosition (dxGeom *g, dReal x, dReal y, dReal z)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (!g->offset_posr) 
+  {
+	dGeomCreateOffset(g);
+  }
+  g->offset_posr->pos[0] = x;
+  g->offset_posr->pos[1] = y;
+  g->offset_posr->pos[2] = z;
+  dGeomMoved (g);
+}
+
+void dGeomSetOffsetRotation (dxGeom *g, const dMatrix3 R)
+{
+  dAASSERT (g && R);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (!g->offset_posr) 
+  {
+	dGeomCreateOffset (g);
+  }
+  memcpy (g->offset_posr->R,R,sizeof(dMatrix3));
+  dGeomMoved (g);
+}
+
+void dGeomSetOffsetQuaternion (dxGeom *g, const dQuaternion quat)
+{
+  dAASSERT (g && quat);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (!g->offset_posr) 
+  {
+	dGeomCreateOffset (g);
+  }
+  dQtoR (quat, g->offset_posr->R);
+  dGeomMoved (g);
+}
+
+void dGeomSetOffsetWorldPosition (dxGeom *g, dReal x, dReal y, dReal z)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (!g->offset_posr) 
+  {
+	dGeomCreateOffset(g);
+  }
+  dBodyGetPosRelPoint(g->body, x, y, z, g->offset_posr->pos);
+  dGeomMoved (g);
+}
+
+void dGeomSetOffsetWorldRotation (dxGeom *g, const dMatrix3 R)
+{
+  dAASSERT (g && R);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (!g->offset_posr) 
+  {
+	dGeomCreateOffset (g);
+  }
+  g->recomputePosr();
+  
+  dxPosR new_final_posr;
+  memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
+  memcpy(new_final_posr.R, R, sizeof(dMatrix3));
+  
+  getWorldOffsetPosr(g->body->posr, new_final_posr, *g->offset_posr);
+  dGeomMoved (g);
+}
+
+void dGeomSetOffsetWorldQuaternion (dxGeom *g, const dQuaternion quat)
+{
+  dAASSERT (g && quat);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  dUASSERT (g->body, "geom must be on a body");  
+  CHECK_NOT_LOCKED (g->parent_space);
+  if (!g->offset_posr) 
+  {
+	dGeomCreateOffset (g);
+  }
+
+  g->recomputePosr();
+  
+  dxPosR new_final_posr;
+  memcpy(new_final_posr.pos, g->final_posr->pos, sizeof(dVector3));
+  dQtoR (quat, new_final_posr.R);
+  
+  getWorldOffsetPosr(g->body->posr, new_final_posr, *g->offset_posr);
+  dGeomMoved (g);
+}
+
+void dGeomClearOffset(dxGeom *g)
+{
+  dAASSERT (g);
+  dUASSERT (g->gflags & GEOM_PLACEABLE,"geom must be placeable");
+  if (g->offset_posr)
+  {
+    dIASSERT(g->body);
+    // no longer need an offset posr
+	dFreePosr(g->offset_posr);
+	g->offset_posr = 0;
+    // the geom will now share the position of the body
+    dFreePosr(g->final_posr);
+    g->final_posr = &g->body->posr;
+    // geom has moved
+    g->gflags &= ~GEOM_POSR_BAD;
+    dGeomMoved (g);
+  }
+}
+
+int dGeomIsOffset(dxGeom *g)
+{
+  dAASSERT (g);
+  return ((0 != g->offset_posr) ? 1 : 0);
+}
+
+static const dVector3 OFFSET_POSITION_ZERO = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+const dReal * dGeomGetOffsetPosition (dxGeom *g)
+{
+  dAASSERT (g);
+  if (g->offset_posr)
+  {
+    return g->offset_posr->pos;
+  }
+  return OFFSET_POSITION_ZERO;
+}
+
+void dGeomCopyOffsetPosition (dxGeom *g, dVector3 pos)
+{
+  dAASSERT (g);
+  if (g->offset_posr)
+  {
+    const dReal* src = g->offset_posr->pos;
+    pos[0] = src[0];
+	 pos[1] = src[1];
+	 pos[2] = src[2];
+  }
+  else
+  {
+    pos[0] = 0;
+	 pos[1] = 0;
+	 pos[2] = 0;
+  }
+}
+
+static const dMatrix3 OFFSET_ROTATION_ZERO = 
+{ 
+	1.0f, 0.0f, 0.0f, 0.0f, 
+	0.0f, 1.0f, 0.0f, 0.0f, 
+	0.0f, 0.0f, 1.0f, 0.0f, 
+};
+
+const dReal * dGeomGetOffsetRotation (dxGeom *g)
+{
+  dAASSERT (g);
+  if (g->offset_posr)
+  {
+    return g->offset_posr->R;
+  }
+  return OFFSET_ROTATION_ZERO;
+}
+
+void dGeomCopyOffsetRotation (dxGeom *g, dMatrix3 R)
+{
+	dAASSERT (g);
+	if (g->offset_posr)
+	{
+		const dReal* src = g->final_posr->R;
+		R[0]  = src[0];
+		R[1]  = src[1];
+		R[2]  = src[2];
+		R[4]  = src[4];
+		R[5]  = src[5];
+		R[6]  = src[6];
+		R[8]  = src[8];
+		R[9]  = src[9];
+		R[10] = src[10];
+	}
+	else
+	{
+		R[0]  = OFFSET_ROTATION_ZERO[0];
+		R[1]  = OFFSET_ROTATION_ZERO[1];
+		R[2]  = OFFSET_ROTATION_ZERO[2];
+		R[4]  = OFFSET_ROTATION_ZERO[4];
+		R[5]  = OFFSET_ROTATION_ZERO[5];
+		R[6]  = OFFSET_ROTATION_ZERO[6];
+		R[8]  = OFFSET_ROTATION_ZERO[8];
+		R[9]  = OFFSET_ROTATION_ZERO[9];
+		R[10] = OFFSET_ROTATION_ZERO[10];
+	}
+}
+
+void dGeomGetOffsetQuaternion (dxGeom *g, dQuaternion result)
+{
+  dAASSERT (g);
+  if (g->offset_posr)
+  {
+    dRtoQ (g->offset_posr->R, result);
+  }
+  else
+  {
+    dSetZero (result,4);
+    result[0] = 1;
+  }
+}
+
+//****************************************************************************
+// initialization and shutdown routines - allocate and initialize data,
+// cleanup before exiting
+
+extern void opcode_collider_cleanup();
+
+void dInitODE()
+{
+#if dTRIMESH_ENABLED && dTRIMESH_GIMPACT
+	gimpact_init();
+#endif
+}
+
+void dCloseODE()
+{
+  colliders_initialized = 0;
+  num_user_classes = 0;
+  dClearPosrCache();
+
+#if dTRIMESH_ENABLED && dTRIMESH_GIMPACT
+  gimpact_terminate();
+#endif
+
+#if dTRIMESH_ENABLED && dTRIMESH_OPCODE
+  // Free up static allocations in opcode
+  opcode_collider_cleanup();
+#endif
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_kernel.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_kernel.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_kernel.h	(revision 216)
@@ -0,0 +1,214 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+internal data structures and functions for collision detection.
+
+*/
+
+#ifndef _ODE_COLLISION_KERNEL_H_
+#define _ODE_COLLISION_KERNEL_H_
+
+#include <ode/common.h>
+#include <ode/contact.h>
+#include <ode/collision.h>
+#include "objects.h"
+
+//****************************************************************************
+// constants and macros
+
+// mask for the number-of-contacts field in the dCollide() flags parameter
+#define NUMC_MASK (0xffff)
+
+#define IS_SPACE(geom) \
+  ((geom)->type >= dFirstSpaceClass && (geom)->type <= dLastSpaceClass)
+
+//****************************************************************************
+// geometry object base class
+
+
+// geom flags.
+//
+// GEOM_DIRTY means that the space data structures for this geom are
+// potentially not up to date. NOTE THAT all space parents of a dirty geom
+// are themselves dirty. this is an invariant that must be enforced.
+//
+// GEOM_AABB_BAD means that the cached AABB for this geom is not up to date.
+// note that GEOM_DIRTY does not imply GEOM_AABB_BAD, as the geom might
+// recalculate its own AABB but does not know how to update the space data
+// structures for the space it is in. but GEOM_AABB_BAD implies GEOM_DIRTY.
+// the valid combinations are: 
+//		0
+//		GEOM_DIRTY
+//		GEOM_DIRTY|GEOM_AABB_BAD
+//		GEOM_DIRTY|GEOM_AABB_BAD|GEOM_POSR_BAD
+
+enum {
+  GEOM_DIRTY	= 1,	// geom is 'dirty', i.e. position unknown
+  GEOM_POSR_BAD = 2,	// geom's final posr is not valid
+  GEOM_AABB_BAD	= 4,	// geom's AABB is not valid
+  GEOM_PLACEABLE = 8,	// geom is placeable
+  GEOM_ENABLED = 16,		// geom is enabled
+
+  // Ray specific
+  RAY_FIRSTCONTACT = 0x10000,
+  RAY_BACKFACECULL = 0x20000,
+  RAY_CLOSEST_HIT  = 0x40000
+};
+
+
+// geometry object base class. pos and R will either point to a separately
+// allocated buffer (if body is 0 - pos points to the dxPosR object) or to
+// the pos and R of the body (if body nonzero).
+// a dGeomID is a pointer to this object.
+
+struct dxGeom : public dBase {
+  int type;		// geom type number, set by subclass constructor
+  int gflags;		// flags used by geom and space
+  void *data;		// user-defined data pointer
+  dBodyID body;		// dynamics body associated with this object (if any)
+  dxGeom *body_next;	// next geom in body's linked list of associated geoms
+  dxPosR *final_posr;	// final position of the geom in world coordinates
+  dxPosR *offset_posr;	// offset from body in local coordinates
+
+  // information used by spaces
+  dxGeom *next;		// next geom in linked list of geoms
+  dxGeom **tome;	// linked list backpointer
+  dxSpace *parent_space;// the space this geom is contained in, 0 if none
+  dReal aabb[6];	// cached AABB for this space
+  unsigned long category_bits,collide_bits;
+
+  dxGeom (dSpaceID _space, int is_placeable);
+  virtual ~dxGeom();
+
+
+  // calculate our new final position from our offset and body
+  void computePosr();
+
+  // recalculate our new final position if needed
+  void recomputePosr()
+  {
+    if (gflags & GEOM_POSR_BAD) {
+      computePosr();
+      gflags &= ~GEOM_POSR_BAD;
+    }
+  }
+
+  virtual void computeAABB()=0;
+  // compute the AABB for this object and put it in aabb. this function
+  // always performs a fresh computation, it does not inspect the
+  // GEOM_AABB_BAD flag.
+
+  virtual int AABBTest (dxGeom *o, dReal aabb[6]);
+  // test whether the given AABB object intersects with this object, return
+  // 1=yes, 0=no. this is used as an early-exit test in the space collision
+  // functions. the default implementation returns 1, which is the correct
+  // behavior if no more detailed implementation can be provided.
+
+  // utility functions
+
+  // compute the AABB only if it is not current. this function manipulates
+  // the GEOM_AABB_BAD flag.
+
+  void recomputeAABB() {
+    if (gflags & GEOM_AABB_BAD) {
+      // our aabb functions assume final_posr is up to date
+      recomputePosr(); 
+      computeAABB();
+      gflags &= ~GEOM_AABB_BAD;
+    }
+  }
+
+  // add and remove this geom from a linked list maintained by a space.
+
+  void spaceAdd (dxGeom **first_ptr) {
+    next = *first_ptr;
+    tome = first_ptr;
+    if (*first_ptr) (*first_ptr)->tome = &next;
+    *first_ptr = this;
+  }
+  void spaceRemove() {
+    if (next) next->tome = tome;
+    *tome = next;
+  }
+
+  // add and remove this geom from a linked list maintained by a body.
+
+  void bodyAdd (dxBody *b) {
+    body = b;
+    body_next = b->geom;
+    b->geom = this;
+  }
+  void bodyRemove();
+};
+
+//****************************************************************************
+// the base space class
+//
+// the contained geoms are divided into two kinds: clean and dirty.
+// the clean geoms have not moved since they were put in the list,
+// and their AABBs are valid. the dirty geoms have changed position, and
+// their AABBs are may not be valid. the two types are distinguished by the
+// GEOM_DIRTY flag. all dirty geoms come *before* all clean geoms in the list.
+
+struct dxSpace : public dxGeom {
+  int count;			// number of geoms in this space
+  dxGeom *first;		// first geom in list
+  int cleanup;			// cleanup mode, 1=destroy geoms on exit
+
+  // cached state for getGeom()
+  int current_index;		// only valid if current_geom != 0
+  dxGeom *current_geom;		// if 0 then there is no information
+
+  // locking stuff. the space is locked when it is currently traversing its
+  // internal data structures, e.g. in collide() and collide2(). operations
+  // that modify the contents of the space are not permitted when the space
+  // is locked.
+  int lock_count;
+
+  dxSpace (dSpaceID _space);
+  ~dxSpace();
+
+  void computeAABB();
+
+  void setCleanup (int mode);
+  int getCleanup();
+  int query (dxGeom *geom);
+  int getNumGeoms();
+  virtual dxGeom *getGeom (int i);
+
+  virtual void add (dxGeom *);
+  virtual void remove (dxGeom *);
+  virtual void dirty (dxGeom *);
+
+  virtual void cleanGeoms()=0;
+  // turn all dirty geoms into clean geoms by computing their AABBs and any
+  // other space data structures that are required. this should clear the
+  // GEOM_DIRTY and GEOM_AABB_BAD flags of all geoms.
+
+  virtual void collide (void *data, dNearCallback *callback)=0;
+  virtual void collide2 (void *data, dxGeom *geom, dNearCallback *callback)=0;
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/collision_quadtreespace.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_quadtreespace.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_quadtreespace.cpp	(revision 216)
@@ -0,0 +1,584 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// QuadTreeSpace by Erwin de Vries.
+
+#include <ode/common.h>
+#include <ode/matrix.h>
+#include <ode/collision_space.h>
+#include <ode/collision.h>
+#include "collision_kernel.h"
+
+#include "collision_space_internal.h"
+
+
+#define AXIS0 0
+#define AXIS1 1
+#define UP 2
+
+//#define DRAWBLOCKS
+
+const int SPLITAXIS = 2;
+const int SPLITS = SPLITAXIS * SPLITAXIS;
+
+#define GEOM_ENABLED(g) (g)->gflags & GEOM_ENABLED
+
+class Block{
+public:
+	dReal MinX, MaxX;
+	dReal MinZ, MaxZ;
+
+	dGeomID First;
+	int GeomCount;
+
+	Block* Parent;
+	Block* Children;
+
+	void Create(const dVector3 Center, const dVector3 Extents, Block* Parent, int Depth, Block*& Blocks);
+
+	void Collide(void* UserData, dNearCallback* Callback);
+	void Collide(dGeomID Object, dGeomID g, void* UserData, dNearCallback* Callback);
+
+	void CollideLocal(dGeomID Object, void* UserData, dNearCallback* Callback);
+	
+	void AddObject(dGeomID Object);
+	void DelObject(dGeomID Object);
+	void Traverse(dGeomID Object);
+
+	bool Inside(const dReal* AABB);
+	
+	Block* GetBlock(const dReal* AABB);
+	Block* GetBlockChild(const dReal* AABB);
+};
+
+
+#ifdef DRAWBLOCKS
+#include "..\..\Include\drawstuff\\drawstuff.h"
+
+static void DrawBlock(Block* Block){
+	dVector3 v[8];
+	v[0][AXIS0] = Block->MinX;
+	v[0][UP] = REAL(-1.0);
+	v[0][AXIS1] = Block->MinZ;
+	
+	v[1][AXIS0] = Block->MinX;
+	v[1][UP] = REAL(-1.0);
+	v[1][AXIS1] = Block->MaxZ;
+	
+	v[2][AXIS0] = Block->MaxX;
+	v[2][UP] = REAL(-1.0);
+	v[2][AXIS1] = Block->MinZ;
+	
+	v[3][AXIS0] = Block->MaxX;
+	v[3][UP] = REAL(-1.0);
+	v[3][AXIS1] = Block->MaxZ;
+	
+	v[4][AXIS0] = Block->MinX;
+	v[4][UP] = REAL(1.0);
+	v[4][AXIS1] = Block->MinZ;
+	
+	v[5][AXIS0] = Block->MinX;
+	v[5][UP] = REAL(1.0);
+	v[5][AXIS1] = Block->MaxZ;
+	
+	v[6][AXIS0] = Block->MaxX;
+	v[6][UP] = REAL(1.0);
+	v[6][AXIS1] = Block->MinZ;
+	
+	v[7][AXIS0] = Block->MaxX;
+	v[7][UP] = REAL(1.0);
+	v[7][AXIS1] = Block->MaxZ;
+	
+	// Bottom
+	dsDrawLine(v[0], v[1]);
+	dsDrawLine(v[1], v[3]);
+	dsDrawLine(v[3], v[2]);
+	dsDrawLine(v[2], v[0]);
+	
+	// Top
+	dsDrawLine(v[4], v[5]);
+	dsDrawLine(v[5], v[7]);
+	dsDrawLine(v[7], v[6]);
+	dsDrawLine(v[6], v[4]);
+	
+	// Sides
+	dsDrawLine(v[0], v[4]);
+	dsDrawLine(v[1], v[5]);
+	dsDrawLine(v[2], v[6]);
+	dsDrawLine(v[3], v[7]);
+}
+#endif	//DRAWBLOCKS
+
+
+void Block::Create(const dVector3 Center, const dVector3 Extents, Block* Parent, int Depth, Block*& Blocks){
+	GeomCount = 0;
+	First = 0;
+
+	MinX = Center[AXIS0] - Extents[AXIS0];
+	MaxX = Center[AXIS0] + Extents[AXIS0];
+
+	MinZ = Center[AXIS1] - Extents[AXIS1];
+	MaxZ = Center[AXIS1] + Extents[AXIS1];
+
+	this->Parent = Parent;
+	if (Depth > 0){
+		Children = Blocks;
+		Blocks += SPLITS;
+
+		dVector3 ChildExtents;
+		ChildExtents[AXIS0] = Extents[AXIS0] / SPLITAXIS;
+		ChildExtents[AXIS1] = Extents[AXIS1] / SPLITAXIS;
+		ChildExtents[UP] = Extents[UP];
+
+		for (int i = 0; i < SPLITAXIS; i++){
+			for (int j = 0; j < SPLITAXIS; j++){
+				int Index = i * SPLITAXIS + j;
+
+				dVector3 ChildCenter;
+				ChildCenter[AXIS0] = Center[AXIS0] - Extents[AXIS0] + ChildExtents[AXIS0] + i * (ChildExtents[AXIS0] * 2);
+				ChildCenter[AXIS1] = Center[AXIS1] - Extents[AXIS1] + ChildExtents[AXIS1] + j * (ChildExtents[AXIS1] * 2);
+				ChildCenter[UP] = Center[UP];
+				
+				Children[Index].Create(ChildCenter, ChildExtents, this, Depth - 1, Blocks);
+			}
+		}
+	}
+	else Children = 0;
+}
+
+void Block::Collide(void* UserData, dNearCallback* Callback){
+#ifdef DRAWBLOCKS
+	DrawBlock(this);
+#endif
+	// Collide the local list
+	dxGeom* g = First;
+	while (g){
+		if (GEOM_ENABLED(g)){
+			Collide(g, g->next, UserData, Callback);
+		}
+		g = g->next;
+	}
+
+	// Recurse for children
+	if (Children){
+		for (int i = 0; i < SPLITS; i++){
+			if (Children[i].GeomCount <= 1){	// Early out
+				continue;
+			}
+			Children[i].Collide(UserData, Callback);
+		}
+	}
+}
+
+void Block::Collide(dxGeom* g1, dxGeom* g2, void* UserData, dNearCallback* Callback){
+#ifdef DRAWBLOCKS
+	DrawBlock(this);
+#endif
+	// Collide against local list
+	while (g2){
+		if (GEOM_ENABLED(g2)){
+			collideAABBs (g1, g2, UserData, Callback);
+		}
+		g2 = g2->next;
+	}
+
+	// Collide against children
+	if (Children){
+		for (int i = 0; i < SPLITS; i++){
+			// Early out for empty blocks
+			if (Children[i].GeomCount == 0){
+				continue;
+			}
+
+			// Does the geom's AABB collide with the block?
+			// Dont do AABB tests for single geom blocks.
+			if (Children[i].GeomCount == 1 && Children[i].First){
+				//
+			}
+			else if (true){
+				if (g1->aabb[AXIS0 * 2 + 0] > Children[i].MaxX ||
+					g1->aabb[AXIS0 * 2 + 1] < Children[i].MinX ||
+					g1->aabb[AXIS1 * 2 + 0] > Children[i].MaxZ ||
+					g1->aabb[AXIS1 * 2 + 1] < Children[i].MinZ) continue;
+			}
+			Children[i].Collide(g1, Children[i].First, UserData, Callback);
+		}
+	}
+}
+
+void Block::CollideLocal(dxGeom* g1, void* UserData, dNearCallback* Callback){
+	// Collide against local list
+	dxGeom* g2 = First;
+	while (g2){
+		if (GEOM_ENABLED(g2)){
+			collideAABBs (g1, g2, UserData, Callback);
+		}
+		g2 = g2->next;
+	}
+}
+
+void Block::AddObject(dGeomID Object){
+	// Add the geom
+	Object->next = First;
+	First = Object;
+	Object->tome = (dxGeom**)this;
+
+	// Now traverse upwards to tell that we have a geom
+	Block* Block = this;
+	do{
+		Block->GeomCount++;
+		Block = Block->Parent;
+	}
+	while (Block);
+}
+
+void Block::DelObject(dGeomID Object){
+	// Del the geom
+	dxGeom* g = First;
+	dxGeom* Last = 0;
+	while (g){
+		if (g == Object){
+			if (Last){
+				Last->next = g->next;
+			}
+			else First = g->next;
+
+			break;
+		}
+		Last = g;
+		g = g->next;
+	}
+
+	Object->tome = 0;
+
+	// Now traverse upwards to tell that we have lost a geom
+	Block* Block = this;
+	do{
+		Block->GeomCount--;
+		Block = Block->Parent;
+	}
+	while (Block);
+}
+
+void Block::Traverse(dGeomID Object){
+	Block* NewBlock = GetBlock(Object->aabb);
+
+	if (NewBlock != this){
+		// Remove the geom from the old block and add it to the new block.
+		// This could be more optimal, but the loss should be very small.
+		DelObject(Object);
+		NewBlock->AddObject(Object);
+	}
+}
+
+bool Block::Inside(const dReal* AABB){
+	return AABB[AXIS0 * 2 + 0] >= MinX && AABB[AXIS0 * 2 + 1] <= MaxX && AABB[AXIS1 * 2 + 0] >= MinZ && AABB[AXIS1 * 2 + 1] <= MaxZ;
+}
+
+Block* Block::GetBlock(const dReal* AABB){
+	if (Inside(AABB)){
+		return GetBlockChild(AABB);	// Child or this will have a good block
+	}
+	else if (Parent){
+		return Parent->GetBlock(AABB);	// Parent has a good block
+	}
+	else return this;	// We are at the root, so we have little choice
+}
+
+Block* Block::GetBlockChild(const dReal* AABB){
+	if (Children){
+		for (int i = 0; i < SPLITS; i++){
+			if (Children[i].Inside(AABB)){
+				return Children[i].GetBlockChild(AABB);	// Child will have good block
+			}
+		}
+	}
+	return this;	// This is the best block
+}
+
+//****************************************************************************
+// quadtree space
+
+struct dxQuadTreeSpace : public dxSpace{
+	Block* Blocks;	// Blocks[0] is the root
+
+	dArray<dxGeom*> DirtyList;
+
+	dxQuadTreeSpace(dSpaceID _space, dVector3 Center, dVector3 Extents, int Depth);
+	~dxQuadTreeSpace();
+
+	dxGeom* getGeom(int i);
+	
+	void add(dxGeom* g);
+	void remove(dxGeom* g);
+	void dirty(dxGeom* g);
+
+	void computeAABB();
+	
+	void cleanGeoms();
+	void collide(void* UserData, dNearCallback* Callback);
+	void collide2(void* UserData, dxGeom* g1, dNearCallback* Callback);
+
+	// Temp data
+	Block* CurrentBlock;	// Only used while enumerating
+	int* CurrentChild;	// Only used while enumerating
+	int CurrentLevel;	// Only used while enumerating
+	dxGeom* CurrentObject;	// Only used while enumerating
+	int CurrentIndex;
+};
+
+dxQuadTreeSpace::dxQuadTreeSpace(dSpaceID _space, dVector3 Center, dVector3 Extents, int Depth) : dxSpace(_space){
+	type = dQuadTreeSpaceClass;
+
+	int BlockCount = 0;
+	for (int i = 0; i <= Depth; i++){
+		BlockCount += (int)pow((dReal)SPLITS, i);
+	}
+
+	Blocks = (Block*)dAlloc(BlockCount * sizeof(Block));
+	Block* Blocks = this->Blocks + 1;	// This pointer gets modified!
+
+	this->Blocks[0].Create(Center, Extents, 0, Depth, Blocks);
+
+	CurrentBlock = 0;
+	CurrentChild = (int*)dAlloc((Depth + 1) * sizeof(int));
+	CurrentLevel = 0;
+	CurrentObject = 0;
+	CurrentIndex = -1;
+
+	// Init AABB. We initialize to infinity because it is not illegal for an object to be outside of the tree. Its simply inserted in the root block
+	aabb[0] = -dInfinity;
+	aabb[1] = dInfinity;
+	aabb[2] = -dInfinity;
+	aabb[3] = dInfinity;
+	aabb[4] = -dInfinity;
+	aabb[5] = dInfinity;
+}
+
+dxQuadTreeSpace::~dxQuadTreeSpace(){
+	int Depth = 0;
+	Block* Current = &Blocks[0];
+	while (Current){
+		Depth++;
+		Current = Current->Children;
+	}
+
+	int BlockCount = 0;
+	for (int i = 0; i < Depth; i++){
+		BlockCount += (int)pow((dReal)SPLITS, i);
+	}
+
+	dFree(Blocks, BlockCount * sizeof(Block));
+	dFree(CurrentChild, (Depth + 1) * sizeof(int));
+}
+
+dxGeom* dxQuadTreeSpace::getGeom(int Index){
+	dUASSERT(Index >= 0 && Index < count, "index out of range");
+
+	//@@@
+	dDebug (0,"dxQuadTreeSpace::getGeom() not yet implemented");
+
+	return 0;
+
+	// This doesnt work
+
+	/*if (CurrentIndex == Index){
+		// Loop through all objects in the local list
+CHILDRECURSE:
+		if (CurrentObject){
+			dGeomID g = CurrentObject;
+			CurrentObject = CurrentObject->next;
+			CurrentIndex++;
+		
+#ifdef DRAWBLOCKS
+			DrawBlock(CurrentBlock);
+#endif	//DRAWBLOCKS
+			return g;
+		}
+		else{
+			// Now lets loop through our children. Starting at index 0.
+			if (CurrentBlock->Children){
+				CurrentChild[CurrentLevel] = 0;
+PARENTRECURSE:
+				for (int& i = CurrentChild[CurrentLevel]; i < SPLITS; i++){
+					if (CurrentBlock->Children[i].GeomCount == 0){
+						continue;
+					}
+					CurrentBlock = &CurrentBlock->Children[i];
+					CurrentObject = CurrentBlock->First;
+				
+					i++;
+				
+					CurrentLevel++;
+					goto CHILDRECURSE;
+				}
+			}
+		}
+		
+		// Now lets go back to the parent so it can continue processing its other children.
+		if (CurrentBlock->Parent){
+			CurrentBlock = CurrentBlock->Parent;
+			CurrentLevel--;
+			goto PARENTRECURSE;
+		}
+	}
+	else{
+		CurrentBlock = &Blocks[0];
+		CurrentLevel = 0;
+		CurrentObject = CurrentObject;
+		CurrentIndex = 0;
+
+		// Other states are already set
+		CurrentObject = CurrentBlock->First;
+	}
+
+
+	if (current_geom && current_index == Index - 1){
+		//current_geom = current_geom->next; // next
+		current_index = Index;
+		return current_geom;
+	}
+	else for (int i = 0; i < Index; i++){	// this will be verrrrrrry slow
+		getGeom(i);
+	}*/
+
+	return 0;
+}
+
+void dxQuadTreeSpace::add(dxGeom* g){
+	CHECK_NOT_LOCKED (this);
+	dAASSERT(g);
+	dUASSERT(g->parent_space == 0 && g->next == 0, "geom is already in a space");
+
+	g->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
+	DirtyList.push(g);
+
+	// add
+	g->parent_space = this;
+	Blocks[0].GetBlock(g->aabb)->AddObject(g);	// Add to best block
+	count++;
+	
+	// enumerator has been invalidated
+	current_geom = 0;
+	
+	dGeomMoved(this);
+}
+
+void dxQuadTreeSpace::remove(dxGeom* g){
+	CHECK_NOT_LOCKED(this);
+	dAASSERT(g);
+	dUASSERT(g->parent_space == this,"object is not in this space");
+	
+	// remove
+	((Block*)g->tome)->DelObject(g);
+	count--;
+
+	for (int i = 0; i < DirtyList.size(); i++){
+		if (DirtyList[i] == g){
+			DirtyList.remove(i);
+			// (mg) there can be multiple instances of a dirty object on stack  be sure to remove ALL and not just first, for this we decrement i
+			--i;
+		}
+	}
+	
+	// safeguard
+	g->next = 0;
+	g->tome = 0;
+	g->parent_space = 0;
+	
+	// enumerator has been invalidated
+	current_geom = 0;
+	
+	// the bounding box of this space (and that of all the parents) may have
+	// changed as a consequence of the removal.
+	dGeomMoved(this);
+}
+
+void dxQuadTreeSpace::dirty(dxGeom* g){
+	DirtyList.push(g);
+}
+
+void dxQuadTreeSpace::computeAABB(){
+	//
+}
+
+void dxQuadTreeSpace::cleanGeoms(){
+	// compute the AABBs of all dirty geoms, and clear the dirty flags
+	lock_count++;
+	
+	for (int i = 0; i < DirtyList.size(); i++){
+		dxGeom* g = DirtyList[i];
+		if (IS_SPACE(g)){
+			((dxSpace*)g)->cleanGeoms();
+		}
+		g->recomputeAABB();
+		g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD));
+
+		((Block*)g->tome)->Traverse(g);
+	}
+	DirtyList.setSize(0);
+
+	lock_count--;
+}
+
+void dxQuadTreeSpace::collide(void* UserData, dNearCallback* Callback){
+  dAASSERT(Callback);
+
+  lock_count++;
+  cleanGeoms();
+
+  Blocks[0].Collide(UserData, Callback);
+
+  lock_count--;
+}
+
+void dxQuadTreeSpace::collide2(void* UserData, dxGeom* g1, dNearCallback* Callback){
+  dAASSERT(g1 && Callback);
+
+  lock_count++;
+  cleanGeoms();
+  g1->recomputeAABB();
+
+  if (g1->parent_space == this){
+	  // The block the geom is in
+	  Block* CurrentBlock = (Block*)g1->tome;
+	  
+	  // Collide against block and its children
+	  CurrentBlock->Collide(g1, CurrentBlock->First, UserData, Callback);
+	  
+	  // Collide against parents
+	  while (true){
+		  CurrentBlock = CurrentBlock->Parent;
+		  if (!CurrentBlock){
+			  break;
+		  }
+		  CurrentBlock->CollideLocal(g1, UserData, Callback);
+	  }
+  }
+  else Blocks[0].Collide(g1, Blocks[0].First, UserData, Callback);
+
+  lock_count--;
+}
+
+dSpaceID dQuadTreeSpaceCreate(dxSpace* space, dVector3 Center, dVector3 Extents, int Depth){
+	return new dxQuadTreeSpace(space, Center, Extents, Depth);
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_space.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_space.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_space.cpp	(revision 216)
@@ -0,0 +1,790 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+spaces
+
+*/
+
+#include <ode/common.h>
+#include <ode/matrix.h>
+#include <ode/collision_space.h>
+#include <ode/collision.h>
+#include "collision_kernel.h"
+
+#include "collision_space_internal.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// make the geom dirty by setting the GEOM_DIRTY and GEOM_BAD_AABB flags
+// and moving it to the front of the space's list. all the parents of a
+// dirty geom also become dirty.
+
+void dGeomMoved (dxGeom *geom)
+{
+  dAASSERT (geom);
+  
+  // if geom is offset, mark it as needing a calculate
+  if (geom->offset_posr) {
+    geom->gflags |= GEOM_POSR_BAD;
+  }
+  
+  // from the bottom of the space heirarchy up, process all clean geoms
+  // turning them into dirty geoms.
+  dxSpace *parent = geom->parent_space;
+
+  while (parent && (geom->gflags & GEOM_DIRTY)==0) {
+    CHECK_NOT_LOCKED (parent);
+    geom->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
+    parent->dirty (geom);
+    geom = parent;
+    parent = parent->parent_space;
+  }
+
+  // all the remaining dirty geoms must have their AABB_BAD flags set, to
+  // ensure that their AABBs get recomputed
+  while (geom) {
+    geom->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
+    CHECK_NOT_LOCKED (geom->parent_space);
+    geom = geom->parent_space;
+  }
+}
+
+#define GEOM_ENABLED(g) ((g)->gflags & GEOM_ENABLED)
+
+//****************************************************************************
+// dxSpace
+
+dxSpace::dxSpace (dSpaceID _space) : dxGeom (_space,0)
+{
+  count = 0;
+  first = 0;
+  cleanup = 1;
+  current_index = 0;
+  current_geom = 0;
+  lock_count = 0;
+}
+
+
+dxSpace::~dxSpace()
+{
+  CHECK_NOT_LOCKED (this);
+  if (cleanup) {
+    // note that destroying each geom will call remove()
+    dxGeom *g,*n;
+    for (g = first; g; g=n) {
+      n = g->next;
+      dGeomDestroy (g);
+    }
+  }
+  else {
+    dxGeom *g,*n;
+    for (g = first; g; g=n) {
+      n = g->next;
+      remove (g);
+    }
+  }
+}
+
+
+void dxSpace::computeAABB()
+{
+  if (first) {
+    int i;
+    dReal a[6];
+    a[0] = dInfinity;
+    a[1] = -dInfinity;
+    a[2] = dInfinity;
+    a[3] = -dInfinity;
+    a[4] = dInfinity;
+    a[5] = -dInfinity;
+    for (dxGeom *g=first; g; g=g->next) {
+      g->recomputeAABB();
+      for (i=0; i<6; i += 2) if (g->aabb[i] < a[i]) a[i] = g->aabb[i];
+      for (i=1; i<6; i += 2) if (g->aabb[i] > a[i]) a[i] = g->aabb[i];
+    }
+    memcpy(aabb,a,6*sizeof(dReal));
+  }
+  else {
+    dSetZero (aabb,6);
+  }
+}
+
+
+void dxSpace::setCleanup (int mode)
+{
+  cleanup = (mode != 0);
+}
+
+
+int dxSpace::getCleanup()
+{
+  return cleanup;
+}
+
+
+int dxSpace::query (dxGeom *geom)
+{
+  dAASSERT (geom);
+  return (geom->parent_space == this);
+}
+
+
+int dxSpace::getNumGeoms()
+{
+  return count;
+}
+
+
+// the dirty geoms are numbered 0..k, the clean geoms are numbered k+1..count-1
+
+dxGeom *dxSpace::getGeom (int i)
+{
+  dUASSERT (i >= 0 && i < count,"index out of range");
+  if (current_geom && current_index == i-1) {
+    current_geom = current_geom->next;
+    current_index = i;
+    return current_geom;
+  }
+  else {
+    dxGeom *g=first;
+    for (int j=0; j<i; j++) {
+      if (g) g = g->next; else return 0;
+    }
+    current_geom = g;
+    current_index = i;
+    return g;
+  }
+}
+
+
+void dxSpace::add (dxGeom *geom)
+{
+  CHECK_NOT_LOCKED (this);
+  dAASSERT (geom);
+  dUASSERT (geom->parent_space == 0 && geom->next == 0,
+	    "geom is already in a space");
+
+  // add
+  geom->parent_space = this;
+  geom->spaceAdd (&first);
+  count++;
+
+  // enumerator has been invalidated
+  current_geom = 0;
+
+  // new geoms are added to the front of the list and are always
+  // considered to be dirty. as a consequence, this space and all its
+  // parents are dirty too.
+  geom->gflags |= GEOM_DIRTY | GEOM_AABB_BAD;
+  dGeomMoved (this);
+}
+
+
+void dxSpace::remove (dxGeom *geom)
+{
+  CHECK_NOT_LOCKED (this);
+  dAASSERT (geom);
+  dUASSERT (geom->parent_space == this,"object is not in this space");
+
+  // remove
+  geom->spaceRemove();
+  count--;
+
+  // safeguard
+  geom->next = 0;
+  geom->tome = 0;
+  geom->parent_space = 0;
+
+  // enumerator has been invalidated
+  current_geom = 0;
+
+  // the bounding box of this space (and that of all the parents) may have
+  // changed as a consequence of the removal.
+  dGeomMoved (this);
+}
+
+
+void dxSpace::dirty (dxGeom *geom)
+{
+  geom->spaceRemove();
+  geom->spaceAdd (&first);
+}
+
+//****************************************************************************
+// simple space - reports all n^2 object intersections
+
+struct dxSimpleSpace : public dxSpace {
+  dxSimpleSpace (dSpaceID _space);
+  void cleanGeoms();
+  void collide (void *data, dNearCallback *callback);
+  void collide2 (void *data, dxGeom *geom, dNearCallback *callback);
+};
+
+
+dxSimpleSpace::dxSimpleSpace (dSpaceID _space) : dxSpace (_space)
+{
+  type = dSimpleSpaceClass;
+}
+
+
+void dxSimpleSpace::cleanGeoms()
+{
+  // compute the AABBs of all dirty geoms, and clear the dirty flags
+  lock_count++;
+  for (dxGeom *g=first; g && (g->gflags & GEOM_DIRTY); g=g->next) {
+    if (IS_SPACE(g)) {
+      ((dxSpace*)g)->cleanGeoms();
+    }
+    g->recomputeAABB();
+    g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD));
+  }
+  lock_count--;
+}
+
+
+void dxSimpleSpace::collide (void *data, dNearCallback *callback)
+{
+  dAASSERT (callback);
+
+  lock_count++;
+  cleanGeoms();
+
+  // intersect all bounding boxes
+  for (dxGeom *g1=first; g1; g1=g1->next) {
+    if (GEOM_ENABLED(g1)){
+      for (dxGeom *g2=g1->next; g2; g2=g2->next) {
+	if (GEOM_ENABLED(g2)){
+	  collideAABBs (g1,g2,data,callback);
+	}
+      }
+    }
+  }
+
+  lock_count--;
+}
+
+
+void dxSimpleSpace::collide2 (void *data, dxGeom *geom,
+			      dNearCallback *callback)
+{
+  dAASSERT (geom && callback);
+
+  lock_count++;
+  cleanGeoms();
+  geom->recomputeAABB();
+
+  // intersect bounding boxes
+  for (dxGeom *g=first; g; g=g->next) {
+    if (GEOM_ENABLED(g)){
+      collideAABBs (g,geom,data,callback);
+    }
+  }
+
+  lock_count--;
+}
+
+//****************************************************************************
+// utility stuff for hash table space
+
+// kind of silly, but oh well...
+#ifndef MAXINT
+#define MAXINT ((int)((((unsigned int)(-1)) << 1) >> 1))
+#endif
+
+
+// prime[i] is the largest prime smaller than 2^i
+#define NUM_PRIMES 31
+static long int prime[NUM_PRIMES] = {1L,2L,3L,7L,13L,31L,61L,127L,251L,509L,
+  1021L,2039L,4093L,8191L,16381L,32749L,65521L,131071L,262139L,
+  524287L,1048573L,2097143L,4194301L,8388593L,16777213L,33554393L,
+  67108859L,134217689L,268435399L,536870909L,1073741789L};
+
+
+// an axis aligned bounding box in the hash table
+struct dxAABB {
+  dxAABB *next;		// next in the list of all AABBs
+  int level;		// the level this is stored in (cell size = 2^level)
+  int dbounds[6];	// AABB bounds, discretized to cell size
+  dxGeom *geom;		// corresponding geometry object (AABB stored here)
+  int index;		// index of this AABB, starting from 0
+};
+
+
+// a hash table node that represents an AABB that intersects a particular cell
+// at a particular level
+struct Node {
+  Node *next;		// next node in hash table collision list, 0 if none
+  int x,y,z;		// cell position in space, discretized to cell size
+  dxAABB *aabb;		// axis aligned bounding box that intersects this cell
+};
+
+
+// return the `level' of an AABB. the AABB will be put into cells at this
+// level - the cell size will be 2^level. the level is chosen to be the
+// smallest value such that the AABB occupies no more than 8 cells, regardless
+// of its placement. this means that:
+//	size/2 < q <= size
+// where q is the maximum AABB dimension.
+
+static int findLevel (dReal bounds[6])
+{
+  if (bounds[0] <= -dInfinity || bounds[1] >= dInfinity ||
+      bounds[2] <= -dInfinity || bounds[3] >= dInfinity ||
+      bounds[4] <= -dInfinity || bounds[5] >= dInfinity) {
+    return MAXINT;
+  }
+
+  // compute q
+  dReal q,q2;
+  q = bounds[1] - bounds[0];	// x bounds
+  q2 = bounds[3] - bounds[2];	// y bounds
+  if (q2 > q) q = q2;
+  q2 = bounds[5] - bounds[4];	// z bounds
+  if (q2 > q) q = q2;
+
+  // find level such that 0.5 * 2^level < q <= 2^level
+  int level;
+  frexp (q,&level);	// q = (0.5 .. 1.0) * 2^level (definition of frexp)
+  return level;
+}
+
+
+// find a virtual memory address for a cell at the given level and x,y,z
+// position.
+// @@@ currently this is not very sophisticated, e.g. the scaling
+// factors could be better designed to avoid collisions, and they should
+// probably depend on the hash table physical size.
+
+static unsigned long getVirtualAddress (int level, int x, int y, int z)
+{
+  return level*1000 + x*100 + y*10 + z;
+}
+
+//****************************************************************************
+// hash space
+
+struct dxHashSpace : public dxSpace {
+  int global_minlevel;	// smallest hash table level to put AABBs in
+  int global_maxlevel;	// objects that need a level larger than this will be
+			// put in a "big objects" list instead of a hash table
+
+  dxHashSpace (dSpaceID _space);
+  void setLevels (int minlevel, int maxlevel);
+  void getLevels (int *minlevel, int *maxlevel);
+  void cleanGeoms();
+  void collide (void *data, dNearCallback *callback);
+  void collide2 (void *data, dxGeom *geom, dNearCallback *callback);
+};
+
+
+dxHashSpace::dxHashSpace (dSpaceID _space) : dxSpace (_space)
+{
+  type = dHashSpaceClass;
+  global_minlevel = -3;
+  global_maxlevel = 10;
+}
+
+
+void dxHashSpace::setLevels (int minlevel, int maxlevel)
+{
+  dAASSERT (minlevel <= maxlevel);
+  global_minlevel = minlevel;
+  global_maxlevel = maxlevel;
+}
+
+
+void dxHashSpace::getLevels (int *minlevel, int *maxlevel)
+{
+  if (minlevel) *minlevel = global_minlevel;
+  if (maxlevel) *maxlevel = global_maxlevel;
+}
+
+
+void dxHashSpace::cleanGeoms()
+{
+  // compute the AABBs of all dirty geoms, and clear the dirty flags
+  lock_count++;
+  for (dxGeom *g=first; g && (g->gflags & GEOM_DIRTY); g=g->next) {
+    if (IS_SPACE(g)) {
+      ((dxSpace*)g)->cleanGeoms();
+    }
+    g->recomputeAABB();
+    g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD));
+  }
+  lock_count--;
+}
+
+
+void dxHashSpace::collide (void *data, dNearCallback *callback)
+{
+  dAASSERT(this && callback);
+  dxGeom *geom;
+  dxAABB *aabb;
+  int i,maxlevel;
+
+  // 0 or 1 geoms can't collide with anything
+  if (count < 2) return;
+
+  lock_count++;
+  cleanGeoms();
+
+  // create a list of auxiliary information for all geom axis aligned bounding
+  // boxes. set the level for all AABBs. put AABBs larger than the space's
+  // global_maxlevel in the big_boxes list, check everything else against
+  // that list at the end. for AABBs that are not too big, record the maximum
+  // level that we need.
+
+  int n = 0;			// number of AABBs in main list
+  dxAABB *first_aabb = 0;	// list of AABBs in hash table
+  dxAABB *big_boxes = 0;	// list of AABBs too big for hash table
+  maxlevel = global_minlevel - 1;
+  for (geom = first; geom; geom=geom->next) {
+    if (!GEOM_ENABLED(geom)){
+      continue;
+    }
+    dxAABB *aabb = (dxAABB*) ALLOCA (sizeof(dxAABB));
+    aabb->geom = geom;
+    // compute level, but prevent cells from getting too small
+    int level = findLevel (geom->aabb);
+    if (level < global_minlevel) level = global_minlevel;
+    if (level <= global_maxlevel) {
+      // aabb goes in main list
+      aabb->next = first_aabb;
+      first_aabb = aabb;
+      aabb->level = level;
+      if (level > maxlevel) maxlevel = level;
+      // cellsize = 2^level
+      dReal cellsize = (dReal) ldexp (1.0,level);
+      // discretize AABB position to cell size
+      for (i=0; i < 6; i++) aabb->dbounds[i] = (int)
+			      floor (geom->aabb[i]/cellsize);
+      // set AABB index
+      aabb->index = n;
+      n++;
+    }
+    else {
+      // aabb is too big, put it in the big_boxes list. we don't care about
+      // setting level, dbounds, index, or the maxlevel
+      aabb->next = big_boxes;
+      big_boxes = aabb;
+    }
+  }
+
+  // for `n' objects, an n*n array of bits is used to record if those objects
+  // have been intersection-tested against each other yet. this array can
+  // grow large with high n, but oh well...
+  int tested_rowsize = (n+7) >> 3;	// number of bytes needed for n bits
+  unsigned char *tested = (unsigned char *) ALLOCA (n * tested_rowsize);
+  memset (tested,0,n * tested_rowsize);
+
+  // create a hash table to store all AABBs. each AABB may take up to 8 cells.
+  // we use chaining to resolve collisions, but we use a relatively large table
+  // to reduce the chance of collisions.
+
+  // compute hash table size sz to be a prime > 8*n
+  for (i=0; i<NUM_PRIMES; i++) {
+    if (prime[i] >= (8*n)) break;
+  }
+  if (i >= NUM_PRIMES) i = NUM_PRIMES-1;	// probably pointless
+  int sz = prime[i];
+
+  // allocate and initialize hash table node pointers
+  Node **table = (Node **) ALLOCA (sizeof(Node*) * sz);
+  for (i=0; i<sz; i++) table[i] = 0;
+
+  // add each AABB to the hash table (may need to add it to up to 8 cells)
+  for (aabb=first_aabb; aabb; aabb=aabb->next) {
+    int *dbounds = aabb->dbounds;
+    for (int xi = dbounds[0]; xi <= dbounds[1]; xi++) {
+      for (int yi = dbounds[2]; yi <= dbounds[3]; yi++) {
+	for (int zi = dbounds[4]; zi <= dbounds[5]; zi++) {
+	  // get the hash index
+	  unsigned long hi = getVirtualAddress (aabb->level,xi,yi,zi) % sz;
+	  // add a new node to the hash table
+	  Node *node = (Node*) ALLOCA (sizeof (Node));
+	  node->x = xi;
+	  node->y = yi;
+	  node->z = zi;
+	  node->aabb = aabb;
+	  node->next = table[hi];
+	  table[hi] = node;
+	}
+      }
+    }
+  }
+
+  // now that all AABBs are loaded into the hash table, we do the actual
+  // collision detection. for all AABBs, check for other AABBs in the
+  // same cells for collisions, and then check for other AABBs in all
+  // intersecting higher level cells.
+
+  int db[6];			// discrete bounds at current level
+  for (aabb=first_aabb; aabb; aabb=aabb->next) {
+    // we are searching for collisions with aabb
+    for (i=0; i<6; i++) db[i] = aabb->dbounds[i];
+    for (int level = aabb->level; level <= maxlevel; level++) {
+      for (int xi = db[0]; xi <= db[1]; xi++) {
+	for (int yi = db[2]; yi <= db[3]; yi++) {
+	  for (int zi = db[4]; zi <= db[5]; zi++) {
+	    // get the hash index
+	    unsigned long hi = getVirtualAddress (level,xi,yi,zi) % sz;
+	    // search all nodes at this index
+	    Node *node;
+	    for (node = table[hi]; node; node=node->next) {
+	      // node points to an AABB that may intersect aabb
+	      if (node->aabb == aabb) continue;
+	      if (node->aabb->level == level &&
+		  node->x == xi && node->y == yi && node->z == zi) {
+		// see if aabb and node->aabb have already been tested
+		// against each other
+		unsigned char mask;
+		if (aabb->index <= node->aabb->index) {
+		  i = (aabb->index * tested_rowsize)+(node->aabb->index >> 3);
+		  mask = 1 << (node->aabb->index & 7);
+		}
+		else {
+		  i = (node->aabb->index * tested_rowsize)+(aabb->index >> 3);
+		  mask = 1 << (aabb->index & 7);
+		}
+		dIASSERT (i >= 0 && i < (tested_rowsize*n));
+		if ((tested[i] & mask)==0) {
+		  collideAABBs (aabb->geom,node->aabb->geom,data,callback);
+		}
+		tested[i] |= mask;
+	      }
+	    }
+	  }
+	}
+      }
+      // get the discrete bounds for the next level up
+      for (i=0; i<6; i++) db[i] >>= 1;
+    }
+  }
+
+  // every AABB in the normal list must now be intersected against every
+  // AABB in the big_boxes list. so let's hope there are not too many objects
+  // in the big_boxes list.
+  for (aabb=first_aabb; aabb; aabb=aabb->next) {
+    for (dxAABB *aabb2=big_boxes; aabb2; aabb2=aabb2->next) {
+      collideAABBs (aabb->geom,aabb2->geom,data,callback);
+    }
+  }
+
+  // intersected all AABBs in the big_boxes list together
+  for (aabb=big_boxes; aabb; aabb=aabb->next) {
+    for (dxAABB *aabb2=aabb->next; aabb2; aabb2=aabb2->next) {
+      collideAABBs (aabb->geom,aabb2->geom,data,callback);
+    }
+  }
+
+  lock_count--;
+}
+
+
+void dxHashSpace::collide2 (void *data, dxGeom *geom,
+			    dNearCallback *callback)
+{
+  dAASSERT (geom && callback);
+  
+  // this could take advantage of the hash structure to avoid
+  // O(n2) complexity, but it does not yet.
+  
+  lock_count++;
+  cleanGeoms();
+  geom->recomputeAABB();
+  
+  // intersect bounding boxes
+  for (dxGeom *g=first; g; g=g->next) {
+    if (GEOM_ENABLED(g)) collideAABBs (g,geom,data,callback);
+  }
+  
+  lock_count--;
+}
+
+//****************************************************************************
+// space functions
+
+dxSpace *dSimpleSpaceCreate (dxSpace *space)
+{
+  return new dxSimpleSpace (space);
+}
+
+
+dxSpace *dHashSpaceCreate (dxSpace *space)
+{
+  return new dxHashSpace (space);
+}
+
+
+void dHashSpaceSetLevels (dxSpace *space, int minlevel, int maxlevel)
+{
+  dAASSERT (space);
+  dUASSERT (minlevel <= maxlevel,"must have minlevel <= maxlevel");
+  dUASSERT (space->type == dHashSpaceClass,"argument must be a hash space");
+  dxHashSpace *hspace = (dxHashSpace*) space;
+  hspace->setLevels (minlevel,maxlevel);
+}
+
+
+void dHashSpaceGetLevels (dxSpace *space, int *minlevel, int *maxlevel)
+{
+  dAASSERT (space);
+  dUASSERT (space->type == dHashSpaceClass,"argument must be a hash space");
+  dxHashSpace *hspace = (dxHashSpace*) space;
+  hspace->getLevels (minlevel,maxlevel);
+}
+
+
+void dSpaceDestroy (dxSpace *space)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  dGeomDestroy (space);
+}
+
+
+void dSpaceSetCleanup (dxSpace *space, int mode)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  space->setCleanup (mode);
+}
+
+
+int dSpaceGetCleanup (dxSpace *space)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  return space->getCleanup();
+}
+
+
+void dSpaceAdd (dxSpace *space, dxGeom *g)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  CHECK_NOT_LOCKED (space);
+  space->add (g);
+}
+
+
+void dSpaceRemove (dxSpace *space, dxGeom *g)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  CHECK_NOT_LOCKED (space);
+  space->remove (g);
+}
+
+
+int dSpaceQuery (dxSpace *space, dxGeom *g)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  return space->query (g);
+}
+
+void dSpaceClean (dxSpace *space){
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+
+  space->cleanGeoms();
+}
+
+int dSpaceGetNumGeoms (dxSpace *space)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  return space->getNumGeoms();
+}
+
+
+dGeomID dSpaceGetGeom (dxSpace *space, int i)
+{
+  dAASSERT (space);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  return space->getGeom (i);
+}
+
+
+void dSpaceCollide (dxSpace *space, void *data, dNearCallback *callback)
+{
+  dAASSERT (space && callback);
+  dUASSERT (dGeomIsSpace(space),"argument not a space");
+  space->collide (data,callback);
+}
+
+
+void dSpaceCollide2 (dxGeom *g1, dxGeom *g2, void *data,
+		     dNearCallback *callback)
+{
+  dAASSERT (g1 && g2 && callback);
+  dxSpace *s1,*s2;
+
+  // see if either geom is a space
+  if (IS_SPACE(g1)) s1 = (dxSpace*) g1; else s1 = 0;
+  if (IS_SPACE(g2)) s2 = (dxSpace*) g2; else s2 = 0;
+
+  // handle the four space/geom cases
+  if (s1) {
+    if (s2) {
+      // g1 and g2 are spaces.
+      if (s1==s2) {
+	// collide a space with itself --> interior collision
+	s1->collide (data,callback);
+      }
+      else {
+	// iterate through the space that has the fewest geoms, calling
+	// collide2 in the other space for each one.
+	if (s1->count < s2->count) {
+	  for (dxGeom *g = s1->first; g; g=g->next) {
+	    s2->collide2 (data,g,callback);
+	  }
+	}
+	else {
+	  for (dxGeom *g = s2->first; g; g=g->next) {
+	    s1->collide2 (data,g,callback);
+	  }
+	}
+      }
+    }
+    else {
+      // g1 is a space, g2 is a geom
+      s1->collide2 (data,g2,callback);
+    }
+  }
+  else {
+    if (s2) {
+      // g1 is a geom, g2 is a space
+      s2->collide2 (data,g1,callback);
+    }
+    else {
+      // g1 and g2 are geoms, call the callback directly
+      callback (data,g1,g2);
+    }
+  }
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_space_internal.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_space_internal.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_space_internal.h	(revision 216)
@@ -0,0 +1,84 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+stuff common to all spaces
+
+*/
+
+#ifndef _ODE_COLLISION_SPACE_INTERNAL_H_
+#define _ODE_COLLISION_SPACE_INTERNAL_H_
+
+#define ALLOCA(x) dALLOCA16(x)
+
+#define CHECK_NOT_LOCKED(space) \
+  dUASSERT ((space)==0 || (space)->lock_count==0, \
+	    "invalid operation for locked space");
+
+
+// collide two geoms together. for the hash table space, this is
+// called if the two AABBs inhabit the same hash table cells.
+// this only calls the callback function if the AABBs actually
+// intersect. if a geom has an AABB test function, that is called to
+// provide a further refinement of the intersection.
+//
+// NOTE: this assumes that the geom AABBs are valid on entry
+// and that both geoms are enabled.
+
+static void collideAABBs (dxGeom *g1, dxGeom *g2,
+			  void *data, dNearCallback *callback)
+{
+  dIASSERT((g1->gflags & GEOM_AABB_BAD)==0);
+  dIASSERT((g2->gflags & GEOM_AABB_BAD)==0);
+
+  // no contacts if both geoms on the same body, and the body is not 0
+  if (g1->body == g2->body && g1->body) return;
+
+  // test if the category and collide bitfields match
+  if ( ((g1->category_bits & g2->collide_bits) ||
+	(g2->category_bits & g1->collide_bits)) == 0) {
+    return;
+  }
+
+  // if the bounding boxes are disjoint then don't do anything
+  dReal *bounds1 = g1->aabb;
+  dReal *bounds2 = g2->aabb;
+  if (bounds1[0] > bounds2[1] ||
+      bounds1[1] < bounds2[0] ||
+      bounds1[2] > bounds2[3] ||
+      bounds1[3] < bounds2[2] ||
+      bounds1[4] > bounds2[5] ||
+      bounds1[5] < bounds2[4]) {
+    return;
+  }
+
+  // check if either object is able to prove that it doesn't intersect the
+  // AABB of the other
+  if (g1->AABBTest (g2,bounds2) == 0) return;
+  if (g2->AABBTest (g1,bounds1) == 0) return;
+
+  // the objects might actually intersect - call the space callback function
+  callback (data,g1,g2);
+}
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/collision_std.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_std.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_std.h	(revision 216)
@@ -0,0 +1,172 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+the standard ODE geometry primitives.
+
+*/
+
+#ifndef _ODE_COLLISION_STD_H_
+#define _ODE_COLLISION_STD_H_
+
+#include <set>
+#include <ode/common.h>
+#include "collision_kernel.h"
+
+
+// primitive collision functions - these have the dColliderFn interface, i.e.
+// the same interface as dCollide(). the first and second geom arguments must
+// have the specified types.
+
+int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip);
+int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip);
+int dCollideSpherePlane (dxGeom *o1, dxGeom *o2, int flags,
+			 dContactGeom *contact, int skip);
+int dCollideBoxBox (dxGeom *o1, dxGeom *o2, int flags,
+		    dContactGeom *contact, int skip);
+int dCollideBoxPlane (dxGeom *o1, dxGeom *o2,
+		      int flags, dContactGeom *contact, int skip);
+int dCollideCapsuleSphere (dxGeom *o1, dxGeom *o2, int flags,
+			     dContactGeom *contact, int skip);
+int dCollideCapsuleBox (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip);
+int dCollideCapsuleCapsule (dxGeom *o1, dxGeom *o2,
+				int flags, dContactGeom *contact, int skip);
+int dCollideCapsulePlane (dxGeom *o1, dxGeom *o2, int flags,
+			    dContactGeom *contact, int skip);
+int dCollideRaySphere (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip);
+int dCollideRayBox (dxGeom *o1, dxGeom *o2, int flags,
+		    dContactGeom *contact, int skip);
+int dCollideRayCapsule (dxGeom *o1, dxGeom *o2,
+			  int flags, dContactGeom *contact, int skip);
+int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags,
+		      dContactGeom *contact, int skip);
+int dCollideRayCylinder (dxGeom *o1, dxGeom *o2, int flags,
+		      dContactGeom *contact, int skip);
+
+// Cylinder - Box/Sphere by (C) CroTeam
+// Ported by Nguyen Binh
+int dCollideCylinderBox(dxGeom *o1, dxGeom *o2, 
+                        int flags, dContactGeom *contact, int skip);
+int dCollideCylinderSphere(dxGeom *gCylinder, dxGeom *gSphere, 
+                           int flags, dContactGeom *contact, int skip); 
+int dCollideCylinderPlane(dxGeom *gCylinder, dxGeom *gPlane, 
+                           int flags, dContactGeom *contact, int skip); 
+
+//--> Convex Collision
+int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags,
+			 dContactGeom *contact, int skip);
+int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip);
+int dCollideConvexBox (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip);
+int dCollideConvexCapsule (dxGeom *o1, dxGeom *o2,
+			   int flags, dContactGeom *contact, int skip);
+int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags, 
+			  dContactGeom *contact, int skip);
+int dCollideRayConvex (dxGeom *o1, dxGeom *o2, int flags, 
+		       dContactGeom *contact, int skip);
+//<-- Convex Collision
+
+// dHeightfield
+int dCollideHeightfield( dxGeom *o1, dxGeom *o2, 
+						 int flags, dContactGeom *contact, int skip );
+
+//****************************************************************************
+// the basic geometry objects
+
+struct dxSphere : public dxGeom {
+  dReal radius;		// sphere radius
+  dxSphere (dSpaceID space, dReal _radius);
+  void computeAABB();
+};
+
+
+struct dxBox : public dxGeom {
+  dVector3 side;	// side lengths (x,y,z)
+  dxBox (dSpaceID space, dReal lx, dReal ly, dReal lz);
+  void computeAABB();
+};
+
+
+struct dxCapsule : public dxGeom {
+  dReal radius,lz;	// radius, length along z axis
+  dxCapsule (dSpaceID space, dReal _radius, dReal _length);
+  void computeAABB();
+};
+
+
+struct dxCylinder : public dxGeom {
+        dReal radius,lz;        // radius, length along z axis
+        dxCylinder (dSpaceID space, dReal _radius, dReal _length);
+        void computeAABB();
+};
+
+
+struct dxPlane : public dxGeom {
+  dReal p[4];
+  dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d);
+  void computeAABB();
+};
+
+
+struct dxRay : public dxGeom {
+  dReal length;
+  dxRay (dSpaceID space, dReal _length);
+  void computeAABB();
+};
+
+typedef std::pair<unsigned int,unsigned int> edge; /*!< Used to descrive a convex hull edge, an edge is a pair or indices into the hull's points */
+struct dxConvex : public dxGeom 
+{
+  
+  dReal *planes; /*!< An array of planes in the form:
+		   normal X, normal Y, normal Z,Distance
+		 */
+  dReal *points; /*!< An array of points X,Y,Z */  
+  unsigned int *polygons; /*! An array of indices to the points of each polygon, it should be the number of vertices followed by that amount of indices to "points" in counter clockwise order*/
+  unsigned int planecount; /*!< Amount of planes in planes */
+  unsigned int pointcount;/*!< Amount of points in points */
+  dReal saabb[6];/*!< Static AABB */
+  std::set<edge> edges;
+  dxConvex(dSpaceID space,
+	   dReal *planes,
+	   unsigned int planecount,
+	   dReal *points,
+	   unsigned int pointcount,
+	   unsigned int *polygons);
+  ~dxConvex()
+  {
+    //fprintf(stdout,"dxConvex Destroy\n");
+  }
+  void computeAABB();
+  private:
+  // For Internal Use Only
+  void FillEdges();
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/collision_transform.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_transform.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_transform.cpp	(revision 216)
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+geom transform
+
+*/
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_transform.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// dxGeomTransform class
+
+struct dxGeomTransform : public dxGeom {
+  dxGeom *obj;		// object that is being transformed
+  int cleanup;		// 1 to destroy obj when destroyed
+  int infomode;		// 1 to put Tx geom in dContactGeom g1
+
+  // cached final object transform (body tx + relative tx). this is set by
+  // computeAABB(), and it is valid while the AABB is valid.
+  dxPosR transform_posr;
+
+  dxGeomTransform (dSpaceID space);
+  ~dxGeomTransform();
+  void computeAABB();
+  void computeFinalTx();
+};
+/*
+void RunMe()
+{
+  printf("sizeof body = %i\n", sizeof(dxBody));
+  printf("sizeof geom = %i\n", sizeof(dxGeom));
+  printf("sizeof geomtransform = %i\n", sizeof(dxGeomTransform));
+  printf("sizeof posr = %i\n", sizeof(dxPosR));
+}
+*/
+
+dxGeomTransform::dxGeomTransform (dSpaceID space) : dxGeom (space,1)
+{
+  type = dGeomTransformClass;
+  obj = 0;
+  cleanup = 0;
+  infomode = 0;
+  dSetZero (transform_posr.pos,4);
+  dRSetIdentity (transform_posr.R);
+}
+
+
+dxGeomTransform::~dxGeomTransform()
+{
+  if (obj && cleanup) delete obj;
+}
+
+
+void dxGeomTransform::computeAABB()
+{
+  if (!obj) {
+    dSetZero (aabb,6);
+    return;
+  }
+
+  // backup the relative pos and R pointers of the encapsulated geom object
+  dxPosR* posr_bak = obj->final_posr;
+
+  // compute temporary pos and R for the encapsulated geom object
+  computeFinalTx();
+  obj->final_posr = &transform_posr;
+
+  // compute the AABB
+  obj->computeAABB();
+  memcpy (aabb,obj->aabb,6*sizeof(dReal));
+
+  // restore the pos and R
+  obj->final_posr = posr_bak;
+}
+
+
+// utility function for dCollideTransform() : compute final pos and R
+// for the encapsulated geom object
+
+void dxGeomTransform::computeFinalTx()
+{
+  dMULTIPLY0_331 (transform_posr.pos,final_posr->R,obj->final_posr->pos);
+  transform_posr.pos[0] += final_posr->pos[0];
+  transform_posr.pos[1] += final_posr->pos[1];
+  transform_posr.pos[2] += final_posr->pos[2];
+  dMULTIPLY0_333 (transform_posr.R,final_posr->R,obj->final_posr->R);
+}
+
+//****************************************************************************
+// collider function:
+// this collides a transformed geom with another geom. the other geom can
+// also be a transformed geom, but this case is not handled specially.
+
+int dCollideTransform (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dGeomTransformClass);
+
+  dxGeomTransform *tr = (dxGeomTransform*) o1;
+  if (!tr->obj) return 0;
+  dUASSERT (tr->obj->parent_space==0,
+	    "GeomTransform encapsulated object must not be in a space");
+  dUASSERT (tr->obj->body==0,
+	    "GeomTransform encapsulated object must not be attached "
+	    "to a body");
+
+  // backup the relative pos and R pointers of the encapsulated geom object,
+  // and the body pointer
+  dxPosR *posr_bak = tr->obj->final_posr;
+  dxBody *bodybak = tr->obj->body;
+
+  // compute temporary pos and R for the encapsulated geom object.
+  // note that final_pos and final_R are valid if no GEOM_AABB_BAD flag,
+  // because computeFinalTx() will have already been called in
+  // dxGeomTransform::computeAABB()
+
+  if (tr->gflags & GEOM_AABB_BAD) tr->computeFinalTx();
+  tr->obj->final_posr = &tr->transform_posr;
+  tr->obj->body = o1->body;
+
+  // do the collision
+  int n = dCollide (tr->obj,o2,flags,contact,skip);
+
+  // if required, adjust the 'g1' values in the generated contacts so that
+  // thay indicated the GeomTransform object instead of the encapsulated
+  // object.
+  if (tr->infomode) {
+    for (int i=0; i<n; i++) {
+      dContactGeom *c = CONTACT(contact,skip*i);
+      c->g1 = o1;
+    }
+  }
+
+  // restore the pos, R and body
+  tr->obj->final_posr = posr_bak;
+  tr->obj->body = bodybak;
+  return n;
+}
+
+//****************************************************************************
+// public API
+
+dGeomID dCreateGeomTransform (dSpaceID space)
+{
+  return new dxGeomTransform (space);
+}
+
+
+void dGeomTransformSetGeom (dGeomID g, dGeomID obj)
+{
+  dUASSERT (g && g->type == dGeomTransformClass,
+	    "argument not a geom transform");
+  dxGeomTransform *tr = (dxGeomTransform*) g;
+  if (tr->obj && tr->cleanup) delete tr->obj;
+  tr->obj = obj;
+}
+
+
+dGeomID dGeomTransformGetGeom (dGeomID g)
+{
+  dUASSERT (g && g->type == dGeomTransformClass,
+	    "argument not a geom transform");
+  dxGeomTransform *tr = (dxGeomTransform*) g;
+  return tr->obj;
+}
+
+
+void dGeomTransformSetCleanup (dGeomID g, int mode)
+{
+  dUASSERT (g && g->type == dGeomTransformClass,
+	    "argument not a geom transform");
+  dxGeomTransform *tr = (dxGeomTransform*) g;
+  tr->cleanup = mode;
+}
+
+
+int dGeomTransformGetCleanup (dGeomID g)
+{
+  dUASSERT (g && g->type == dGeomTransformClass,
+	    "argument not a geom transform");
+  dxGeomTransform *tr = (dxGeomTransform*) g;
+  return tr->cleanup;
+}
+
+
+void dGeomTransformSetInfo (dGeomID g, int mode)
+{
+  dUASSERT (g && g->type == dGeomTransformClass,
+	    "argument not a geom transform");
+  dxGeomTransform *tr = (dxGeomTransform*) g;
+  tr->infomode = mode;
+}
+
+
+int dGeomTransformGetInfo (dGeomID g)
+{
+  dUASSERT (g && g->type == dGeomTransformClass,
+	    "argument not a geom transform");
+  dxGeomTransform *tr = (dxGeomTransform*) g;
+  return tr->infomode;
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_transform.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_transform.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_transform.h	(revision 216)
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+geom transform
+
+*/
+
+#ifndef _ODE_COLLISION_TRANSFORM_H_
+#define _ODE_COLLISION_TRANSFORM_H_
+
+#include <ode/common.h>
+#include "collision_kernel.h"
+
+
+int dCollideTransform (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip);
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_box.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_box.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_box.cpp	(revision 216)
@@ -0,0 +1,1497 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+
+/*************************************************************************
+ *                                                                       *
+ * Triangle-box collider by Alen Ladavac and Vedran Klanac.              *
+ * Ported to ODE by Oskari Nyman.                                        *
+ *                                                                       *
+ *************************************************************************/
+
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_ENABLED
+
+
+static void
+GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride,
+                dxGeom* in_g1,  dxGeom* in_g2,
+                const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth,
+                int& OutTriCount);
+
+
+// largest number, double or float
+#if defined(dSINGLE)
+  #define MAXVALUE FLT_MAX
+#else
+  #define MAXVALUE DBL_MAX
+#endif
+
+
+// dVector3
+// r=a-b
+#define SUBTRACT(a,b,r) do{ \
+  (r)[0]=(a)[0] - (b)[0]; \
+  (r)[1]=(a)[1] - (b)[1]; \
+  (r)[2]=(a)[2] - (b)[2]; }while(0)
+
+
+// dVector3
+// a=b
+#define SET(a,b) do{ \
+  (a)[0]=(b)[0]; \
+  (a)[1]=(b)[1]; \
+  (a)[2]=(b)[2]; }while(0)
+
+
+// dMatrix3
+// a=b
+#define SETM(a,b) do{ \
+  (a)[0]=(b)[0]; \
+  (a)[1]=(b)[1]; \
+  (a)[2]=(b)[2]; \
+  (a)[3]=(b)[3]; \
+  (a)[4]=(b)[4]; \
+  (a)[5]=(b)[5]; \
+  (a)[6]=(b)[6]; \
+  (a)[7]=(b)[7]; \
+  (a)[8]=(b)[8]; \
+  (a)[9]=(b)[9]; \
+  (a)[10]=(b)[10]; \
+                     (a)[11]=(b)[11]; }while(0)
+
+
+// dVector3
+// r=a+b
+#define ADD(a,b,r) do{ \
+  (r)[0]=(a)[0] + (b)[0]; \
+  (r)[1]=(a)[1] + (b)[1]; \
+  (r)[2]=(a)[2] + (b)[2]; }while(0)
+
+
+// dMatrix3, int, dVector3
+// v=column a from m
+#define GETCOL(m,a,v) do{ \
+  (v)[0]=(m)[(a)+0]; \
+  (v)[1]=(m)[(a)+4]; \
+  (v)[2]=(m)[(a)+8]; }while(0)
+
+
+// dVector4, dVector3
+// distance between plane p and point v
+#define POINTDISTANCE(p,v) \
+  ( p[0]*v[0] + p[1]*v[1] + p[2]*v[2] + p[3] )
+
+
+// dVector4, dVector3, dReal
+// construct plane from normal and d
+#define CONSTRUCTPLANE(plane,normal,d) do{ \
+  plane[0]=normal[0];\
+  plane[1]=normal[1];\
+  plane[2]=normal[2];\
+  plane[3]=d; }while(0)
+
+
+// dVector3
+// length of vector a
+#define LENGTHOF(a) \
+  dSqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2])
+
+
+// box data
+static dMatrix3 mHullBoxRot;
+static dVector3 vHullBoxPos;
+static dVector3 vBoxHalfSize;
+
+// mesh data
+static dVector3   vHullDstPos;
+
+// global collider data
+static dVector3 vBestNormal;
+static dReal    fBestDepth;
+static int    iBestAxis = 0;
+static int    iExitAxis = 0;
+static dVector3 vE0, vE1, vE2, vN;
+
+// global info for contact creation
+static int iFlags;
+static dContactGeom *ContactGeoms;
+static int iStride;
+static dxGeom *Geom1;
+static dxGeom *Geom2;
+static int ctContacts = 0;
+
+
+
+// Test normal of mesh face as separating axis for intersection
+static bool _cldTestNormal( dReal fp0, dReal fR, dVector3 vNormal, int iAxis )
+{
+  // calculate overlapping interval of box and triangle
+  dReal fDepth = fR+fp0;
+
+  // if we do not overlap
+  if ( fDepth<0 ) {
+    // do nothing
+    return false;
+  }
+
+  // calculate normal's length
+  dReal fLength = LENGTHOF(vNormal);
+  // if long enough
+  if ( fLength > 0.0f ) {
+
+    dReal fOneOverLength = 1.0f/fLength;
+    // normalize depth
+    fDepth = fDepth*fOneOverLength;
+
+    // get minimum depth
+    if (fDepth<fBestDepth) {
+      vBestNormal[0] = -vNormal[0]*fOneOverLength;
+      vBestNormal[1] = -vNormal[1]*fOneOverLength;
+      vBestNormal[2] = -vNormal[2]*fOneOverLength;
+      iBestAxis = iAxis;
+      //dAASSERT(fDepth>=0);
+      fBestDepth = fDepth;
+    }
+
+  }
+
+  return true;
+}
+
+
+
+
+// Test box axis as separating axis
+static bool _cldTestFace( dReal fp0, dReal fp1, dReal fp2, dReal fR, dReal fD,
+                          dVector3 vNormal, int iAxis )
+{
+  dReal fMin, fMax;
+
+  // find min of triangle interval
+  if ( fp0 < fp1 ) {
+    if ( fp0 < fp2 ) {
+      fMin = fp0;
+    } else {
+      fMin = fp2;
+    }
+  } else {
+    if( fp1 < fp2 ) {
+      fMin = fp1;
+    } else {
+      fMin = fp2;
+    }
+  }
+
+  // find max of triangle interval
+  if ( fp0 > fp1 ) {
+    if ( fp0 > fp2 ) {
+      fMax = fp0;
+    } else {
+      fMax = fp2;
+    }
+  } else {
+    if( fp1 > fp2 ) {
+      fMax = fp1;
+    } else {
+      fMax = fp2;
+    }
+  }
+
+  // calculate minimum and maximum depth
+  dReal fDepthMin = fR - fMin;
+  dReal fDepthMax = fMax + fR;
+
+  // if we dont't have overlapping interval
+  if ( fDepthMin < 0 || fDepthMax < 0 ) {
+    // do nothing
+    return false;
+  }
+
+  dReal fDepth = 0;
+
+  // if greater depth is on negative side
+  if ( fDepthMin > fDepthMax ) {
+    // use smaller depth (one from positive side)
+    fDepth = fDepthMax;
+    // flip normal direction
+    vNormal[0] = -vNormal[0];
+    vNormal[1] = -vNormal[1];
+    vNormal[2] = -vNormal[2];
+    fD = -fD;
+  // if greater depth is on positive side
+  } else {
+    // use smaller depth (one from negative side)
+    fDepth = fDepthMin;
+  }
+
+
+  // if lower depth than best found so far
+  if (fDepth<fBestDepth) {
+    // remember current axis as best axis
+    vBestNormal[0]  = vNormal[0];
+    vBestNormal[1]  = vNormal[1];
+    vBestNormal[2]  = vNormal[2];
+    iBestAxis    = iAxis;
+    //dAASSERT(fDepth>=0);
+    fBestDepth   = fDepth;
+  }
+
+  return true;
+}
+
+
+
+
+
+// Test cross products of box axis and triangle edges as separating axis
+static bool _cldTestEdge( dReal fp0, dReal fp1, dReal fR, dReal fD,
+                          dVector3 vNormal, int iAxis )
+{
+  dReal fMin, fMax;
+
+
+  // ===== Begin Patch by Francisco Leon, 2006/10/28 =====
+
+  // Fixed Null Normal. This prevents boxes passing
+  // through trimeshes at certain contact angles
+
+  fMin = vNormal[0] * vNormal[0] +
+		 vNormal[1] * vNormal[1] +
+		 vNormal[2] * vNormal[2];
+
+  if ( fMin <= dEpsilon ) /// THIS NORMAL WOULD BE DANGEROUS
+	  return true;
+
+  // ===== Ending Patch by Francisco Leon =====
+
+
+  // calculate min and max interval values
+  if ( fp0 < fp1 ) {
+    fMin = fp0;
+    fMax = fp1;
+  } else {
+    fMin = fp1;
+    fMax = fp0;
+  }
+
+  // check if we overlapp
+  dReal fDepthMin = fR - fMin;
+  dReal fDepthMax = fMax + fR;
+
+  // if we don't overlapp
+  if ( fDepthMin < 0 || fDepthMax < 0 ) {
+    // do nothing
+    return false;
+  }
+
+  dReal fDepth;
+
+
+  // if greater depth is on negative side
+  if ( fDepthMin > fDepthMax ) {
+    // use smaller depth (one from positive side)
+    fDepth = fDepthMax;
+    // flip normal direction
+    vNormal[0] = -vNormal[0];
+    vNormal[1] = -vNormal[1];
+    vNormal[2] = -vNormal[2];
+    fD = -fD;
+  // if greater depth is on positive side
+  } else {
+    // use smaller depth (one from negative side)
+    fDepth = fDepthMin;
+  }
+
+  // calculate normal's length
+  dReal fLength = LENGTHOF(vNormal);
+
+  // if long enough
+  if ( fLength > 0.0f ) {
+
+    // normalize depth
+    dReal fOneOverLength = 1.0f/fLength;
+    fDepth = fDepth*fOneOverLength;
+    fD*=fOneOverLength;
+
+
+    // if lower depth than best found so far (favor face over edges)
+    if (fDepth*1.5f<fBestDepth) {
+      // remember current axis as best axis
+      vBestNormal[0]  = vNormal[0]*fOneOverLength;
+      vBestNormal[1]  = vNormal[1]*fOneOverLength;
+      vBestNormal[2]  = vNormal[2]*fOneOverLength;
+      iBestAxis    = iAxis;
+      //dAASSERT(fDepth>=0);
+      fBestDepth   = fDepth;
+    }
+  }
+
+  return true;
+}
+
+
+
+
+
+// clip polygon with plane and generate new polygon points
+static void _cldClipPolyToPlane( dVector3 avArrayIn[], int ctIn,
+                      dVector3 avArrayOut[], int &ctOut,
+                      const dVector4 &plPlane )
+{
+  // start with no output points
+  ctOut = 0;
+
+  int i0 = ctIn-1;
+
+  // for each edge in input polygon
+  for (int i1=0; i1<ctIn; i0=i1, i1++) {
+
+
+    // calculate distance of edge points to plane
+    dReal fDistance0 = POINTDISTANCE( plPlane ,avArrayIn[i0] );
+    dReal fDistance1 = POINTDISTANCE( plPlane ,avArrayIn[i1] );
+
+
+    // if first point is in front of plane
+    if( fDistance0 >= 0 ) {
+      // emit point
+      avArrayOut[ctOut][0] = avArrayIn[i0][0];
+      avArrayOut[ctOut][1] = avArrayIn[i0][1];
+      avArrayOut[ctOut][2] = avArrayIn[i0][2];
+      ctOut++;
+    }
+
+    // if points are on different sides
+    if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) {
+
+      // find intersection point of edge and plane
+      dVector3 vIntersectionPoint;
+      vIntersectionPoint[0]= avArrayIn[i0][0] - (avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1);
+      vIntersectionPoint[1]= avArrayIn[i0][1] - (avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1);
+      vIntersectionPoint[2]= avArrayIn[i0][2] - (avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1);
+
+      // emit intersection point
+      avArrayOut[ctOut][0] = vIntersectionPoint[0];
+      avArrayOut[ctOut][1] = vIntersectionPoint[1];
+      avArrayOut[ctOut][2] = vIntersectionPoint[2];
+      ctOut++;
+    }
+  }
+
+}
+
+
+
+
+static bool _cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {
+  // reset best axis
+  iBestAxis = 0;
+  iExitAxis = -1;
+  fBestDepth = MAXVALUE;
+
+  // calculate edges
+  SUBTRACT(v1,v0,vE0);
+  SUBTRACT(v2,v0,vE1);
+  SUBTRACT(vE1,vE0,vE2);
+
+  // calculate poly normal
+  dCROSS(vN,=,vE0,vE1);
+
+  // extract box axes as vectors
+  dVector3 vA0,vA1,vA2;
+  GETCOL(mHullBoxRot,0,vA0);
+  GETCOL(mHullBoxRot,1,vA1);
+  GETCOL(mHullBoxRot,2,vA2);
+
+  // box halfsizes
+  dReal fa0 = vBoxHalfSize[0];
+  dReal fa1 = vBoxHalfSize[1];
+  dReal fa2 = vBoxHalfSize[2];
+
+  // calculate relative position between box and triangle
+  dVector3 vD;
+  SUBTRACT(v0,vHullBoxPos,vD);
+
+  // calculate length of face normal
+  dReal fNLen = LENGTHOF( vN );
+
+  dVector3 vL;
+  dReal fp0, fp1, fp2, fR, fD;
+
+  // Test separating axes for intersection
+  // ************************************************
+  // Axis 1 - Triangle Normal
+  SET(vL,vN);
+  fp0  = dDOT(vL,vD);
+  fp1  = fp0;
+  fp2  = fp0;
+  fR=fa0*dFabs( dDOT(vN,vA0) ) + fa1 * dFabs( dDOT(vN,vA1) ) + fa2 * dFabs( dDOT(vN,vA2) );
+
+
+  if( !_cldTestNormal( fp0, fR, vL, 1) ) {
+    iExitAxis=1;
+    return false;
+  }
+
+  // ************************************************
+
+  // Test Faces
+  // ************************************************
+  // Axis 2 - Box X-Axis
+  SET(vL,vA0);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 + dDOT(vA0,vE0);
+  fp2 = fp0 + dDOT(vA0,vE1);
+  fR  = fa0;
+
+
+  if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 2) ) {
+    iExitAxis=2;
+    return false;
+  }
+  // ************************************************
+
+  // ************************************************
+  // Axis 3 - Box Y-Axis
+  SET(vL,vA1);
+  fD = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 + dDOT(vA1,vE0);
+  fp2 = fp0 + dDOT(vA1,vE1);
+  fR  = fa1;
+
+
+  if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 3) ) {
+    iExitAxis=3;
+    return false;
+  }
+
+  // ************************************************
+
+  // ************************************************
+  // Axis 4 - Box Z-Axis
+  SET(vL,vA2);
+  fD = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 + dDOT(vA2,vE0);
+  fp2 = fp0 + dDOT(vA2,vE1);
+  fR  = fa2;
+
+
+  if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 4) ) {
+    iExitAxis=4;
+    return false;
+  }
+
+  // ************************************************
+
+  // Test Edges
+  // ************************************************
+  // Axis 5 - Box X-Axis cross Edge0
+  dCROSS(vL,=,vA0,vE0);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0;
+  fp2 = fp0 + dDOT(vA0,vN);
+  fR  = fa1 * dFabs(dDOT(vA2,vE0)) + fa2 * dFabs(dDOT(vA1,vE0));
+
+
+  if( !_cldTestEdge( fp1, fp2, fR, fD, vL, 5) ) {
+    iExitAxis=5;
+    return false;
+  }
+  // ************************************************
+
+  // ************************************************
+  // Axis 6 - Box X-Axis cross Edge1
+  dCROSS(vL,=,vA0,vE1);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 - dDOT(vA0,vN);
+  fp2 = fp0;
+  fR  = fa1 * dFabs(dDOT(vA2,vE1)) + fa2 * dFabs(dDOT(vA1,vE1));
+
+
+  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 6) ) {
+    iExitAxis=6;
+    return false;
+  }
+  // ************************************************
+
+  // ************************************************
+  // Axis 7 - Box X-Axis cross Edge2
+  dCROSS(vL,=,vA0,vE2);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 - dDOT(vA0,vN);
+  fp2 = fp0 - dDOT(vA0,vN);
+  fR  = fa1 * dFabs(dDOT(vA2,vE2)) + fa2 * dFabs(dDOT(vA1,vE2));
+
+
+  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 7) ) {
+    iExitAxis=7;
+    return false;
+  }
+
+  // ************************************************
+
+  // ************************************************
+  // Axis 8 - Box Y-Axis cross Edge0
+  dCROSS(vL,=,vA1,vE0);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0;
+  fp2 = fp0 + dDOT(vA1,vN);
+  fR  = fa0 * dFabs(dDOT(vA2,vE0)) + fa2 * dFabs(dDOT(vA0,vE0));
+
+
+  if( !_cldTestEdge( fp0, fp2, fR, fD, vL, 8) ) {
+    iExitAxis=8;
+    return false;
+  }
+
+  // ************************************************
+
+  // ************************************************
+  // Axis 9 - Box Y-Axis cross Edge1
+  dCROSS(vL,=,vA1,vE1);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 - dDOT(vA1,vN);
+  fp2 = fp0;
+  fR  = fa0 * dFabs(dDOT(vA2,vE1)) + fa2 * dFabs(dDOT(vA0,vE1));
+
+
+  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 9) ) {
+    iExitAxis=9;
+    return false;
+  }
+
+  // ************************************************
+
+  // ************************************************
+  // Axis 10 - Box Y-Axis cross Edge2
+  dCROSS(vL,=,vA1,vE2);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 - dDOT(vA1,vN);
+  fp2 = fp0 - dDOT(vA1,vN);
+  fR  = fa0 * dFabs(dDOT(vA2,vE2)) + fa2 * dFabs(dDOT(vA0,vE2));
+
+
+  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 10) ) {
+    iExitAxis=10;
+    return false;
+  }
+
+  // ************************************************
+
+  // ************************************************
+  // Axis 11 - Box Z-Axis cross Edge0
+  dCROSS(vL,=,vA2,vE0);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0;
+  fp2 = fp0 + dDOT(vA2,vN);
+  fR  = fa0 * dFabs(dDOT(vA1,vE0)) + fa1 * dFabs(dDOT(vA0,vE0));
+
+
+  if( !_cldTestEdge( fp0, fp2, fR, fD, vL, 11) ) {
+    iExitAxis=11;
+    return false;
+  }
+  // ************************************************
+
+  // ************************************************
+  // Axis 12 - Box Z-Axis cross Edge1
+  dCROSS(vL,=,vA2,vE1);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 - dDOT(vA2,vN);
+  fp2 = fp0;
+  fR  = fa0 * dFabs(dDOT(vA1,vE1)) + fa1 * dFabs(dDOT(vA0,vE1));
+
+
+  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 12) ) {
+    iExitAxis=12;
+    return false;
+  }
+  // ************************************************
+
+  // ************************************************
+  // Axis 13 - Box Z-Axis cross Edge2
+  dCROSS(vL,=,vA2,vE2);
+  fD  = dDOT(vL,vN)/fNLen;
+  fp0 = dDOT(vL,vD);
+  fp1 = fp0 - dDOT(vA2,vN);
+  fp2 = fp0 - dDOT(vA2,vN);
+  fR  = fa0 * dFabs(dDOT(vA1,vE2)) + fa1 * dFabs(dDOT(vA0,vE2));
+
+
+  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 13) ) {
+    iExitAxis=13;
+    return false;
+  }
+
+  // ************************************************
+  return true;
+}
+
+
+
+
+
+// find two closest points on two lines
+static bool _cldClosestPointOnTwoLines( dVector3 vPoint1, dVector3 vLenVec1,
+                                        dVector3 vPoint2, dVector3 vLenVec2,
+                                        dReal &fvalue1, dReal &fvalue2)
+{
+  // calulate denominator
+  dVector3 vp;
+  SUBTRACT(vPoint2,vPoint1,vp);
+  dReal fuaub  = dDOT(vLenVec1,vLenVec2);
+  dReal fq1    = dDOT(vLenVec1,vp);
+  dReal fq2    = -dDOT(vLenVec2,vp);
+  dReal fd     = 1.0f - fuaub * fuaub;
+
+  // if denominator is positive
+  if (fd > 0.0f) {
+    // calculate points of closest approach
+    fd = 1.0f/fd;
+    fvalue1 = (fq1 + fuaub*fq2)*fd;
+    fvalue2 = (fuaub*fq1 + fq2)*fd;
+    return true;
+  // otherwise
+  } else {
+    // lines are parallel
+    fvalue1 = 0.0f;
+    fvalue2 = 0.0f;
+    return false;
+  }
+
+}
+
+
+
+
+
+// clip and generate contacts
+static void _cldClipping(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {
+  dIASSERT( !(iFlags & CONTACTS_UNIMPORTANT) || ctContacts < (iFlags & NUMC_MASK) ); // Do not call the function if there is no room to store results
+
+  // if we have edge/edge intersection
+  if ( iBestAxis > 4 ) {
+
+    dVector3 vub,vPb,vPa;
+
+    SET(vPa,vHullBoxPos);
+
+    // calculate point on box edge
+    for( int i=0; i<3; i++) {
+      dVector3 vRotCol;
+      GETCOL(mHullBoxRot,i,vRotCol);
+      dReal fSign = dDOT(vBestNormal,vRotCol) > 0 ? 1.0f : -1.0f;
+
+      vPa[0] += fSign * vBoxHalfSize[i] * vRotCol[0];
+      vPa[1] += fSign * vBoxHalfSize[i] * vRotCol[1];
+      vPa[2] += fSign * vBoxHalfSize[i] * vRotCol[2];
+    }
+
+    int iEdge = (iBestAxis-5)%3;
+
+    // decide which edge is on triangle
+    if ( iEdge == 0 ) {
+      SET(vPb,v0);
+      SET(vub,vE0);
+    } else if ( iEdge == 1) {
+      SET(vPb,v2);
+      SET(vub,vE1);
+    } else {
+      SET(vPb,v1);
+      SET(vub,vE2);
+    }
+
+
+    // setup direction parameter for face edge
+    dNormalize3(vub);
+
+    dReal fParam1, fParam2;
+
+    // setup direction parameter for box edge
+    dVector3 vua;
+    int col=(iBestAxis-5)/3;
+    GETCOL(mHullBoxRot,col,vua);
+
+    // find two closest points on both edges
+    _cldClosestPointOnTwoLines( vPa, vua, vPb, vub, fParam1, fParam2 );
+    vPa[0] += vua[0]*fParam1;
+    vPa[1] += vua[1]*fParam1;
+    vPa[2] += vua[2]*fParam1;
+
+    vPb[0] += vub[0]*fParam2;
+    vPb[1] += vub[1]*fParam2;
+    vPb[2] += vub[2]*fParam2;
+
+    // calculate collision point
+    dVector3 vPntTmp;
+    ADD(vPa,vPb,vPntTmp);
+
+    vPntTmp[0]*=0.5f;
+    vPntTmp[1]*=0.5f;
+    vPntTmp[2]*=0.5f;
+
+    // generate contact point between two closest points
+#if 0 //#ifdef ORIG -- if to use conditional define, GenerateContact must be moved into #else
+	dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
+	Contact->depth = fBestDepth;
+	SET(Contact->normal,vBestNormal);
+	SET(Contact->pos,vPntTmp);
+	Contact->g1 = Geom1;
+	Contact->g2 = Geom2;
+	ctContacts++;
+#endif
+    GenerateContact(iFlags, ContactGeoms, iStride,  Geom1, Geom2,
+                    vPntTmp, vBestNormal, fBestDepth, ctContacts);
+
+
+  // if triangle is the referent face then clip box to triangle face
+  } else if ( iBestAxis == 1 ) {
+
+
+    dVector3 vNormal2;
+    vNormal2[0]=-vBestNormal[0];
+    vNormal2[1]=-vBestNormal[1];
+    vNormal2[2]=-vBestNormal[2];
+
+
+    // vNr is normal in box frame, pointing from triangle to box
+    dMatrix3 mTransposed;
+    mTransposed[0*4+0]=mHullBoxRot[0*4+0];
+    mTransposed[0*4+1]=mHullBoxRot[1*4+0];
+    mTransposed[0*4+2]=mHullBoxRot[2*4+0];
+
+    mTransposed[1*4+0]=mHullBoxRot[0*4+1];
+    mTransposed[1*4+1]=mHullBoxRot[1*4+1];
+    mTransposed[1*4+2]=mHullBoxRot[2*4+1];
+
+    mTransposed[2*4+0]=mHullBoxRot[0*4+2];
+    mTransposed[2*4+1]=mHullBoxRot[1*4+2];
+    mTransposed[2*4+2]=mHullBoxRot[2*4+2];
+
+    dVector3 vNr;
+    vNr[0]=mTransposed[0*4+0]*vNormal2[0]+  mTransposed[0*4+1]*vNormal2[1]+  mTransposed[0*4+2]*vNormal2[2];
+    vNr[1]=mTransposed[1*4+0]*vNormal2[0]+  mTransposed[1*4+1]*vNormal2[1]+  mTransposed[1*4+2]*vNormal2[2];
+    vNr[2]=mTransposed[2*4+0]*vNormal2[0]+  mTransposed[2*4+1]*vNormal2[1]+  mTransposed[2*4+2]*vNormal2[2];
+
+
+    dVector3 vAbsNormal;
+    vAbsNormal[0] = dFabs( vNr[0] );
+    vAbsNormal[1] = dFabs( vNr[1] );
+    vAbsNormal[2] = dFabs( vNr[2] );
+
+    // get closest face from box
+    int iB0, iB1, iB2;
+    if (vAbsNormal[1] > vAbsNormal[0]) {
+      if (vAbsNormal[1] > vAbsNormal[2]) {
+        iB1 = 0;  iB0 = 1;  iB2 = 2;
+      } else {
+        iB1 = 0;  iB2 = 1;  iB0 = 2;
+      }
+    } else {
+
+      if (vAbsNormal[0] > vAbsNormal[2]) {
+        iB0 = 0;  iB1 = 1;  iB2 = 2;
+      } else {
+        iB1 = 0;  iB2 = 1;  iB0 = 2;
+      }
+    }
+
+    // Here find center of box face we are going to project
+    dVector3 vCenter;
+    dVector3 vRotCol;
+    GETCOL(mHullBoxRot,iB0,vRotCol);
+
+    if (vNr[iB0] > 0) {
+        vCenter[0] = vHullBoxPos[0] - v0[0] - vBoxHalfSize[iB0] * vRotCol[0];
+      vCenter[1] = vHullBoxPos[1] - v0[1] - vBoxHalfSize[iB0] * vRotCol[1];
+      vCenter[2] = vHullBoxPos[2] - v0[2] - vBoxHalfSize[iB0] * vRotCol[2];
+    } else {
+      vCenter[0] = vHullBoxPos[0] - v0[0] + vBoxHalfSize[iB0] * vRotCol[0];
+      vCenter[1] = vHullBoxPos[1] - v0[1] + vBoxHalfSize[iB0] * vRotCol[1];
+      vCenter[2] = vHullBoxPos[2] - v0[2] + vBoxHalfSize[iB0] * vRotCol[2];
+    }
+
+    // Here find 4 corner points of box
+    dVector3 avPoints[4];
+
+    dVector3 vRotCol2;
+    GETCOL(mHullBoxRot,iB1,vRotCol);
+    GETCOL(mHullBoxRot,iB2,vRotCol2);
+
+    for(int x=0;x<3;x++) {
+        avPoints[0][x] = vCenter[x] + (vBoxHalfSize[iB1] * vRotCol[x]) - (vBoxHalfSize[iB2] * vRotCol2[x]);
+        avPoints[1][x] = vCenter[x] - (vBoxHalfSize[iB1] * vRotCol[x]) - (vBoxHalfSize[iB2] * vRotCol2[x]);
+        avPoints[2][x] = vCenter[x] - (vBoxHalfSize[iB1] * vRotCol[x]) + (vBoxHalfSize[iB2] * vRotCol2[x]);
+        avPoints[3][x] = vCenter[x] + (vBoxHalfSize[iB1] * vRotCol[x]) + (vBoxHalfSize[iB2] * vRotCol2[x]);
+    }
+
+
+    // clip Box face with 4 planes of triangle (1 face plane, 3 egde planes)
+    dVector3 avTempArray1[9];
+    dVector3 avTempArray2[9];
+    dVector4 plPlane;
+
+    int iTempCnt1=0;
+    int iTempCnt2=0;
+
+    // zeroify vectors - necessary?
+    for(int i=0; i<9; i++) {
+      avTempArray1[i][0]=0;
+      avTempArray1[i][1]=0;
+      avTempArray1[i][2]=0;
+
+      avTempArray2[i][0]=0;
+      avTempArray2[i][1]=0;
+      avTempArray2[i][2]=0;
+    }
+
+
+    // Normal plane
+    dVector3 vTemp;
+    vTemp[0]=-vN[0];
+    vTemp[1]=-vN[1];
+    vTemp[2]=-vN[2];
+    dNormalize3(vTemp);
+    CONSTRUCTPLANE(plPlane,vTemp,0);
+
+    _cldClipPolyToPlane( avPoints, 4, avTempArray1, iTempCnt1, plPlane  );
+
+
+    // Plane p0
+    dVector3 vTemp2;
+    SUBTRACT(v1,v0,vTemp2);
+    dCROSS(vTemp,=,vN,vTemp2);
+    dNormalize3(vTemp);
+    CONSTRUCTPLANE(plPlane,vTemp,0);
+
+    _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane  );
+
+
+    // Plane p1
+    SUBTRACT(v2,v1,vTemp2);
+    dCROSS(vTemp,=,vN,vTemp2);
+    dNormalize3(vTemp);
+    SUBTRACT(v0,v2,vTemp2);
+    CONSTRUCTPLANE(plPlane,vTemp,dDOT(vTemp2,vTemp));
+
+    _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane  );
+
+
+    // Plane p2
+    SUBTRACT(v0,v2,vTemp2);
+    dCROSS(vTemp,=,vN,vTemp2);
+    dNormalize3(vTemp);
+    CONSTRUCTPLANE(plPlane,vTemp,0);
+
+    _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane  );
+
+
+    // END of clipping polygons
+
+
+
+    // for each generated contact point
+    for ( int i=0; i<iTempCnt2; i++ ) {
+      // calculate depth
+      dReal fTempDepth = dDOT(vNormal2,avTempArray2[i]);
+
+      // clamp depth to zero
+      if (fTempDepth > 0) {
+        fTempDepth = 0;
+      }
+
+      dVector3 vPntTmp;
+      ADD(avTempArray2[i],v0,vPntTmp);
+
+#if 0 //#ifdef ORIG -- if to use conditional define, GenerateContact must be moved into #else
+      dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
+	  
+      Contact->depth = -fTempDepth;
+      SET(Contact->normal,vBestNormal);
+      SET(Contact->pos,vPntTmp);
+      Contact->g1 = Geom1;
+      Contact->g2 = Geom2;
+      ctContacts++;
+#endif
+		GenerateContact(iFlags, ContactGeoms, iStride,  Geom1, Geom2,
+						vPntTmp, vBestNormal, -fTempDepth, ctContacts);
+
+		if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+			break;
+		}
+    }
+
+    //dAASSERT(ctContacts>0);
+
+  // if box face is the referent face, then clip triangle on box face
+  } else { // 2 <= if iBestAxis <= 4
+
+    // get normal of box face
+    dVector3 vNormal2;
+    SET(vNormal2,vBestNormal);
+
+    // get indices of box axes in correct order
+    int iA0,iA1,iA2;
+    iA0 = iBestAxis-2;
+    if ( iA0 == 0 ) {
+      iA1 = 1; iA2 = 2;
+    } else if ( iA0 == 1 ) {
+      iA1 = 0; iA2 = 2;
+    } else {
+      iA1 = 0; iA2 = 1;
+    }
+
+    dVector3 avPoints[3];
+    // calculate triangle vertices in box frame
+    SUBTRACT(v0,vHullBoxPos,avPoints[0]);
+    SUBTRACT(v1,vHullBoxPos,avPoints[1]);
+    SUBTRACT(v2,vHullBoxPos,avPoints[2]);
+
+    // CLIP Polygons
+    // define temp data for clipping
+    dVector3 avTempArray1[9];
+    dVector3 avTempArray2[9];
+
+    int iTempCnt1, iTempCnt2;
+
+    // zeroify vectors - necessary?
+    for(int i=0; i<9; i++) {
+      avTempArray1[i][0]=0;
+      avTempArray1[i][1]=0;
+      avTempArray1[i][2]=0;
+
+      avTempArray2[i][0]=0;
+      avTempArray2[i][1]=0;
+      avTempArray2[i][2]=0;
+    }
+
+    // clip triangle with 5 box planes (1 face plane, 4 edge planes)
+
+    dVector4 plPlane;
+
+    // Normal plane
+    dVector3 vTemp;
+    vTemp[0]=-vNormal2[0];
+    vTemp[1]=-vNormal2[1];
+    vTemp[2]=-vNormal2[2];
+    CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA0]);
+
+    _cldClipPolyToPlane( avPoints, 3, avTempArray1, iTempCnt1, plPlane );
+
+
+    // Plane p0
+    GETCOL(mHullBoxRot,iA1,vTemp);
+    CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA1]);
+
+    _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane );
+
+
+    // Plane p1
+    GETCOL(mHullBoxRot,iA1,vTemp);
+    vTemp[0]=-vTemp[0];
+    vTemp[1]=-vTemp[1];
+    vTemp[2]=-vTemp[2];
+    CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA1]);
+
+    _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane );
+
+
+    // Plane p2
+    GETCOL(mHullBoxRot,iA2,vTemp);
+    CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA2]);
+
+    _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane );
+
+
+    // Plane p3
+    GETCOL(mHullBoxRot,iA2,vTemp);
+    vTemp[0]=-vTemp[0];
+    vTemp[1]=-vTemp[1];
+    vTemp[2]=-vTemp[2];
+    CONSTRUCTPLANE(plPlane,vTemp,vBoxHalfSize[iA2]);
+
+    _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane );
+
+
+    // for each generated contact point
+    for ( int i=0; i<iTempCnt1; i++ ) {
+      // calculate depth
+      dReal fTempDepth = dDOT(vNormal2,avTempArray1[i])-vBoxHalfSize[iA0];
+
+      // clamp depth to zero
+      if (fTempDepth > 0) {
+        fTempDepth = 0;
+      }
+
+      // generate contact data
+      dVector3 vPntTmp;
+      ADD(avTempArray1[i],vHullBoxPos,vPntTmp);
+
+#if 0 //#ifdef ORIG -- if to use conditional define, GenerateContact must be moved into #else
+      dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
+
+      Contact->depth = -fTempDepth;
+      SET(Contact->normal,vBestNormal);
+      SET(Contact->pos,vPntTmp);
+      Contact->g1 = Geom1;
+      Contact->g2 = Geom2;
+      ctContacts++;
+#endif
+		GenerateContact(iFlags, ContactGeoms, iStride,  Geom1, Geom2,
+					  vPntTmp, vBestNormal, -fTempDepth, ctContacts);
+
+		if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+			break;
+		}
+    }
+
+    //dAASSERT(ctContacts>0);
+  }
+
+}
+
+
+
+
+
+// test one mesh triangle on intersection with given box
+static void _cldTestOneTriangle(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2)//, void *pvUser)
+{
+  // do intersection test and find best separating axis
+  if(!_cldTestSeparatingAxes(v0, v1, v2) ) {
+     // if not found do nothing
+    return;
+  }
+
+  // if best separation axis is not found
+  if ( iBestAxis == 0 ) {
+    // this should not happen (we should already exit in that case)
+    //dMessage (0, "best separation axis not found");
+    // do nothing
+    return;
+  }
+
+  _cldClipping(v0, v1, v2);
+}
+
+
+
+
+
+// OPCODE version of box to mesh collider
+#if dTRIMESH_OPCODE
+int dCollideBTL(dxGeom* g1, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride){
+  dIASSERT (Stride >= (int)sizeof(dContactGeom));
+  dIASSERT (g1->type == dTriMeshClass);
+  dIASSERT (BoxGeom->type == dBoxClass);
+  dIASSERT ((Flags & NUMC_MASK) >= 1);
+
+
+  dxTriMesh* TriMesh = (dxTriMesh*)g1;
+
+
+  // get source hull position, orientation and half size
+  const dMatrix3& mRotBox=*(const dMatrix3*)dGeomGetRotation(BoxGeom);
+  const dVector3& vPosBox=*(const dVector3*)dGeomGetPosition(BoxGeom);
+
+  // to global
+  SETM(mHullBoxRot,mRotBox);
+  SET(vHullBoxPos,vPosBox);
+
+  dGeomBoxGetLengths(BoxGeom, vBoxHalfSize);
+  vBoxHalfSize[0] *= 0.5f;
+  vBoxHalfSize[1] *= 0.5f;
+  vBoxHalfSize[2] *= 0.5f;
+
+
+
+  // get destination hull position and orientation
+  const dMatrix3& mRotMesh=*(const dMatrix3*)dGeomGetRotation(TriMesh);
+  const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh);
+
+  // to global
+  SET(vHullDstPos,vPosMesh);
+
+
+
+  // global info for contact creation
+  ctContacts = 0;
+  iStride=Stride;
+  iFlags=Flags;
+  ContactGeoms=Contacts;
+  Geom1=TriMesh;
+  Geom2=BoxGeom;
+
+
+
+  // reset stuff
+  fBestDepth = MAXVALUE;
+  vBestNormal[0]=0;
+  vBestNormal[1]=0;
+  vBestNormal[2]=0;
+
+  OBBCollider& Collider = TriMesh->_OBBCollider;
+
+
+
+
+  // Make OBB
+  OBB Box;
+  Box.mCenter.x = vPosBox[0];
+  Box.mCenter.y = vPosBox[1];
+  Box.mCenter.z = vPosBox[2];
+
+  // It is a potential issue to explicitly cast to float 
+  // if custom width floating point type is introduced in OPCODE.
+  // It is necessary to make a typedef and cast to it
+  // (e.g. typedef float opc_float;)
+  // However I'm not sure in what header it should be added.
+
+  Box.mExtents.x = /*(float)*/vBoxHalfSize[0];
+  Box.mExtents.y = /*(float)*/vBoxHalfSize[1];
+  Box.mExtents.z = /*(float)*/vBoxHalfSize[2];
+
+  Box.mRot.m[0][0] = /*(float)*/mRotBox[0];
+  Box.mRot.m[1][0] = /*(float)*/mRotBox[1];
+  Box.mRot.m[2][0] = /*(float)*/mRotBox[2];
+
+  Box.mRot.m[0][1] = /*(float)*/mRotBox[4];
+  Box.mRot.m[1][1] = /*(float)*/mRotBox[5];
+  Box.mRot.m[2][1] = /*(float)*/mRotBox[6];
+
+  Box.mRot.m[0][2] = /*(float)*/mRotBox[8];
+  Box.mRot.m[1][2] = /*(float)*/mRotBox[9];
+  Box.mRot.m[2][2] = /*(float)*/mRotBox[10];
+
+  Matrix4x4 amatrix;
+  Matrix4x4 BoxMatrix = MakeMatrix(vPosBox, mRotBox, amatrix);
+
+  Matrix4x4 InvBoxMatrix;
+  InvertPRMatrix(InvBoxMatrix, BoxMatrix);
+
+  // TC results
+  if (TriMesh->doBoxTC) {
+	dxTriMesh::BoxTC* BoxTC = 0;
+	for (int i = 0; i < TriMesh->BoxTCCache.size(); i++){
+		if (TriMesh->BoxTCCache[i].Geom == BoxGeom){
+			BoxTC = &TriMesh->BoxTCCache[i];
+			break;
+		}
+	}
+	if (!BoxTC){
+		TriMesh->BoxTCCache.push(dxTriMesh::BoxTC());
+
+		BoxTC = &TriMesh->BoxTCCache[TriMesh->BoxTCCache.size() - 1];
+		BoxTC->Geom = BoxGeom;
+    BoxTC->FatCoeff = 1.1f; // Pierre recommends this, instead of 1.0
+	}
+
+	// Intersect
+	Collider.SetTemporalCoherence(true);
+	Collider.Collide(*BoxTC, Box, TriMesh->Data->BVTree, null, &MakeMatrix(vPosMesh, mRotMesh, amatrix));
+  }
+  else {
+		Collider.SetTemporalCoherence(false);
+		Collider.Collide(dxTriMesh::defaultBoxCache, Box, TriMesh->Data->BVTree, null,
+						 &MakeMatrix(vPosMesh, mRotMesh, amatrix));
+	}
+
+  if (! Collider.GetContactStatus()) {
+  	// no collision occurred
+  	return 0;
+  }
+
+  // Retrieve data
+  int TriCount = Collider.GetNbTouchedPrimitives();
+  const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
+
+  if (TriCount != 0){
+      if (TriMesh->ArrayCallback != null){
+         TriMesh->ArrayCallback(TriMesh, BoxGeom, Triangles, TriCount);
+    }
+
+    int ctContacts0 = 0;
+
+    // loop through all intersecting triangles
+    for (int i = 0; i < TriCount; i++){
+
+
+        const int Triint = Triangles[i];
+        if (!Callback(TriMesh, BoxGeom, Triint)) continue;
+
+
+        dVector3 dv[3];
+        FetchTriangle(TriMesh, Triint, vPosMesh, mRotMesh, dv);
+
+
+        // test this triangle
+        _cldTestOneTriangle(dv[0],dv[1],dv[2]);
+
+		// fill-in tri index for generated contacts
+		for (; ctContacts0<ctContacts; ctContacts0++)
+			SAFECONTACT(iFlags, ContactGeoms, ctContacts0, iStride)->side1 = Triint;
+
+		/*
+			NOTE by Oleh_Derevenko:
+			The function continues checking triangles after maximal number 
+			of contacts is reached because it selects maximal penetration depths.
+			See also comments in GenerateContact()
+		*/
+		// Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
+		if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
+			break;
+    }
+  }
+
+
+  return ctContacts;
+}
+#endif
+
+// GIMPACT version of box to mesh collider
+#if dTRIMESH_GIMPACT
+int dCollideBTL(dxGeom* g1, dxGeom* BoxGeom, int Flags, dContactGeom* Contacts, int Stride)
+{
+  dIASSERT (Stride >= (int)sizeof(dContactGeom));
+  dIASSERT (g1->type == dTriMeshClass);
+  dIASSERT (BoxGeom->type == dBoxClass);
+  dIASSERT ((Flags & NUMC_MASK) >= 1);
+
+  
+  dxTriMesh* TriMesh = (dxTriMesh*)g1;
+
+
+  // get source hull position, orientation and half size
+  const dMatrix3& mRotBox=*(const dMatrix3*)dGeomGetRotation(BoxGeom);
+  const dVector3& vPosBox=*(const dVector3*)dGeomGetPosition(BoxGeom);
+
+  // to global
+  SETM(mHullBoxRot,mRotBox);
+  SET(vHullBoxPos,vPosBox);
+
+  dGeomBoxGetLengths(BoxGeom, vBoxHalfSize);
+  vBoxHalfSize[0] *= 0.5f;
+  vBoxHalfSize[1] *= 0.5f;
+  vBoxHalfSize[2] *= 0.5f;
+
+  // get destination hull position and orientation
+  /*const dMatrix3& mRotMesh=*(const dMatrix3*)dGeomGetRotation(TriMesh);
+  const dVector3& vPosMesh=*(const dVector3*)dGeomGetPosition(TriMesh);
+
+  // to global
+  SET(vHullDstPos,vPosMesh);*/
+
+  // global info for contact creation
+  ctContacts = 0;
+  iStride=Stride;
+  iFlags=Flags;
+  ContactGeoms=Contacts;
+  Geom1=TriMesh;
+  Geom2=BoxGeom;
+
+
+  // reset stuff
+  fBestDepth = MAXVALUE;
+  vBestNormal[0]=0;
+  vBestNormal[1]=0;
+  vBestNormal[2]=0;
+
+
+//*****at first , collide box aabb******//
+
+    GIM_TRIMESH * ptrimesh = &TriMesh->m_collision_trimesh;
+	aabb3f test_aabb;
+
+	test_aabb.minX = BoxGeom->aabb[0];
+	test_aabb.maxX = BoxGeom->aabb[1];
+	test_aabb.minY = BoxGeom->aabb[2];
+	test_aabb.maxY = BoxGeom->aabb[3];
+	test_aabb.minZ = BoxGeom->aabb[4];
+	test_aabb.maxZ = BoxGeom->aabb[5];
+
+	GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_BOXQUERY_LIST(collision_result);
+
+	gim_aabbset_box_collision(&test_aabb, &ptrimesh->m_aabbset , &collision_result);
+
+	if(collision_result.m_size==0)
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	    return 0;
+	}
+//*****Set globals for box collision******//
+
+	//collide triangles
+
+	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
+	gim_trimesh_locks_work_data(ptrimesh);
+
+    int ctContacts0 = 0;
+	
+	for(unsigned int i=0;i<collision_result.m_size;i++)
+	{
+		dVector3 dv[3];
+
+		int Triint = boxesresult[i];
+		gim_trimesh_get_triangle_vertices(ptrimesh, Triint,dv[0],dv[1],dv[2]);
+        // test this triangle
+        _cldTestOneTriangle(dv[0],dv[1],dv[2]);
+		
+		// fill-in tri index for generated contacts
+		for (; ctContacts0<ctContacts; ctContacts0++)
+			SAFECONTACT(iFlags, ContactGeoms, ctContacts0, iStride)->side1 = Triint;
+		
+		/*
+			NOTE by Oleh_Derevenko:
+			The function continues checking triangles after maximal number 
+			of contacts is reached because it selects maximal penetration depths.
+			See also comments in GenerateContact()
+		*/
+		// Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
+		if ((ctContacts | CONTACTS_UNIMPORTANT) == (iFlags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
+			break;
+	}
+
+	gim_trimesh_unlocks_work_data(ptrimesh);
+	GIM_DYNARRAY_DESTROY(collision_result);
+
+	return ctContacts;
+}
+#endif
+
+
+// GenerateContact - Written by Jeff Smith (jeff@burri.to)
+//   Generate a "unique" contact.  A unique contact has a unique
+//   position or normal.  If the potential contact has the same
+//   position and normal as an existing contact, but a larger
+//   penetration depth, this new depth is used instead
+//
+static void
+GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride,
+                dxGeom* in_g1,  dxGeom* in_g2,
+                const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth,
+                int& OutTriCount)
+{
+	/*
+		NOTE by Oleh_Derevenko:
+		This function is called after maximal number of contacts has already been 
+		collected because it has a side effect of replacing penetration depth of
+		existing contact with larger penetration depth of another matching normal contact.
+		If this logic is not necessary any more, you can bail out on reach of contact
+		number maximum immediately in dCollideBTL(). You will also need to correct 
+		conditional statements after invocations of GenerateContact() in _cldClipping().
+	*/
+	do 
+	{
+		dContactGeom* Contact;
+		dVector3 diff;
+		
+		if (!(in_Flags & CONTACTS_UNIMPORTANT))
+		{
+			bool duplicate = false;
+			for (int i=0; i<OutTriCount; i++)
+			{
+				Contact = SAFECONTACT(in_Flags, in_Contacts, i, in_Stride);
+
+				// same position?
+				for (int j=0; j<3; j++)
+					diff[j] = in_ContactPos[j] - Contact->pos[j];
+				if (dDOT(diff, diff) < dEpsilon)
+				{
+					// same normal?
+					if (dFabs(dDOT(in_Normal, Contact->normal)) > (REAL(1.0)-dEpsilon))
+					{
+						if (in_Depth > Contact->depth)
+							Contact->depth = in_Depth;
+						duplicate = true;
+						/*
+							NOTE by Oleh_Derevenko:
+							There may be a case when two normals are close to each other but not duplicate
+							while third normal is detected to be duplicate for both of them.
+							This is the only reason I can think of, there is no "break" statement.
+							Perhaps author considered it to be logical that the third normal would 
+							replace the depth in both of initial contacts. 
+							However, I consider it a questionable practice which should not
+							be applied without deep understanding of underlaying physics.
+							Even more, is this situation with close normal triplet acceptable at all?
+							Should not be two initial contacts reduced to one (replaced with the latter)?
+							If you know the answers for these questions, you may want to change this code.
+							See the same statement in GenerateContact() of collision_trimesh_trimesh.cpp
+						*/
+					}
+				}
+			}
+			if (duplicate || OutTriCount == (in_Flags & NUMC_MASK))
+			{
+				break;
+			}
+		}
+		else
+		{
+			dIASSERT(OutTriCount < (in_Flags & NUMC_MASK));
+		}
+
+		// Add a new contact
+		Contact = SAFECONTACT(in_Flags, in_Contacts, OutTriCount, in_Stride);
+
+		Contact->pos[0] = in_ContactPos[0];
+		Contact->pos[1] = in_ContactPos[1];
+		Contact->pos[2] = in_ContactPos[2];
+		Contact->pos[3] = 0.0;
+
+		Contact->normal[0] = in_Normal[0];
+		Contact->normal[1] = in_Normal[1];
+		Contact->normal[2] = in_Normal[2];
+		Contact->normal[3] = 0.0;
+
+		Contact->depth = in_Depth;
+
+		Contact->g1 = in_g1;
+		Contact->g2 = in_g2;
+
+		OutTriCount++;
+	}
+	while (false);
+}
+
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_ccylinder.cpp	(revision 216)
@@ -0,0 +1,1181 @@
+/*************************************************************************
+*                                                                       *
+* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+*                                                                       *
+* This library is free software; you can redistribute it and/or         *
+* modify it under the terms of EITHER:                                  *
+*   (1) The GNU Lesser General Public License as published by the Free  *
+*       Software Foundation; either version 2.1 of the License, or (at  *
+*       your option) any later version. The text of the GNU Lesser      *
+*       General Public License is included with this library in the     *
+*       file LICENSE.TXT.                                               *
+*   (2) The BSD-style license that is included with this library in     *
+*       the file LICENSE-BSD.TXT.                                       *
+*                                                                       *
+* This library is distributed in the hope that it will be useful,       *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+*                                                                       *
+*************************************************************************/
+
+/*
+ *	Triangle-Capsule(Capsule) collider by Alen Ladavac
+ *  Ported to ODE by Nguyen Binh
+ */
+
+// NOTES from Nguyen Binh
+//	14 Apr : Seem to be robust
+//       There is a problem when you use original Step and set contact friction
+//		surface.mu = dInfinity;
+//		More description : 
+//			When I dropped Capsule over the bunny ears, it seems to stuck
+//			there for a while. I think the cause is when you set surface.mu = dInfinity;
+//			the friction force is too high so it just hang the capsule there.
+//			So the good cure for this is to set mu = around 1.5 (in my case)
+//		For StepFast1, this become as solid as rock : StepFast1 just approximate 
+//		friction force.
+
+// NOTES from Croteam's Alen
+//As a side note... there are some extra contacts that can be generated
+//on the edge between two triangles, and if the capsule penetrates deeply into
+//the triangle (usually happens with large mass or low FPS), some such
+//contacts can in some cases push the capsule away from the edge instead of
+//away from the two triangles. This shows up as capsule slowing down a bit
+//when hitting an edge while sliding along a flat tesselated grid of
+//triangles. This is only if capsule is standing upwards.
+
+//Same thing can appear whenever a smooth object (e.g sphere) hits such an
+//edge, and it needs to be solved as a special case probably. This is a
+//problem we are looking forward to address soon.
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_ENABLED
+
+// OPCODE version
+#if dTRIMESH_OPCODE
+// largest number, double or float
+#if defined(dSINGLE)
+#define MAX_REAL	FLT_MAX
+#define MIN_REAL	(-FLT_MAX)
+#else
+#define MAX_REAL	DBL_MAX
+#define MIN_REAL	(-DBL_MAX)
+#endif
+
+// To optimize before send contacts to dynamic part
+#define OPTIMIZE_CONTACTS
+
+// dVector3
+// r=a-b
+#define SUBTRACT(a,b,r) \
+	(r)[0]=(a)[0] - (b)[0]; \
+	(r)[1]=(a)[1] - (b)[1]; \
+	(r)[2]=(a)[2] - (b)[2]; 
+
+
+// dVector3
+// a=b
+#define SET(a,b) \
+	(a)[0]=(b)[0]; \
+	(a)[1]=(b)[1]; \
+	(a)[2]=(b)[2]; 
+
+
+// dMatrix3
+// a=b
+#define SETM(a,b) \
+	(a)[0]=(b)[0]; \
+	(a)[1]=(b)[1]; \
+	(a)[2]=(b)[2]; \
+	(a)[3]=(b)[3]; \
+	(a)[4]=(b)[4]; \
+	(a)[5]=(b)[5]; \
+	(a)[6]=(b)[6]; \
+	(a)[7]=(b)[7]; \
+	(a)[8]=(b)[8]; \
+	(a)[9]=(b)[9]; \
+	(a)[10]=(b)[10]; \
+	(a)[11]=(b)[11];
+
+
+// dVector3
+// r=a+b
+#define ADD(a,b,r) \
+	(r)[0]=(a)[0] + (b)[0]; \
+	(r)[1]=(a)[1] + (b)[1]; \
+	(r)[2]=(a)[2] + (b)[2]; 
+
+
+// dMatrix3, int, dVector3
+// v=column a from m
+#define GETCOL(m,a,v) \
+	(v)[0]=(m)[(a)+0]; \
+	(v)[1]=(m)[(a)+4]; \
+	(v)[2]=(m)[(a)+8];
+
+
+// dVector4, dVector3
+// distance between plane p and point v
+#define POINTDISTANCE(p,v) \
+	( p[0]*v[0] + p[1]*v[1] + p[2]*v[2] + p[3] ); \
+
+
+// dVector4, dVector3, dReal
+// construct plane from normal and d
+#define CONSTRUCTPLANE(plane,normal,d) \
+	plane[0]=normal[0];\
+	plane[1]=normal[1];\
+	plane[2]=normal[2];\
+	plane[3]=d;
+
+
+// dVector3
+// length of vector a
+#define LENGTHOF(a) \
+	dSqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);\
+
+inline dReal _length2OfVector3(dVector3 v)
+{
+	return (v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
+}
+
+
+// Local contacts data
+typedef struct _sLocalContactData
+{
+	dVector3	vPos;
+	dVector3	vNormal;
+	dReal		fDepth;
+	int			triIndex;
+	int			nFlags; // 0 = filtered out, 1 = OK
+}sLocalContactData;
+
+static sLocalContactData   *gLocalContacts;
+static unsigned int			ctContacts = 0;
+
+// capsule data
+// real time data
+static dMatrix3  mCapsuleRotation;
+static dVector3   vCapsulePosition;
+static dVector3   vCapsuleAxis;
+// static data
+static dReal      vCapsuleRadius;
+static dReal      fCapsuleSize;
+
+// mesh data
+static  dMatrix4  mHullDstPl;
+static   dMatrix3  mTriMeshRot;
+static dVector3   mTriMeshPos;
+static dVector3   vE0, vE1, vE2;
+
+// Two geom
+dxGeom*	   gCylinder;
+dxGeom*	   gTriMesh;
+
+// global collider data
+static dVector3 vNormal;
+static dReal    fBestDepth;
+static dReal    fBestCenter;
+static dReal    fBestrt;
+static int		iBestAxis;
+static dVector3 vN = {0,0,0,0};
+
+static dVector3 vV0; 
+static dVector3 vV1;
+static dVector3 vV2;
+
+// ODE contact's specific
+static unsigned int iFlags;
+static dContactGeom *ContactGeoms;
+static int iStride;
+
+// Capsule lie on axis number 3 = (Z axis)
+static const int nCAPSULE_AXIS = 2;
+
+// Use to classify contacts to be "near" in position
+static const dReal fSameContactPositionEpsilon = REAL(0.0001); // 1e-4
+// Use to classify contacts to be "near" in normal direction
+static const dReal fSameContactNormalEpsilon = REAL(0.0001); // 1e-4
+
+
+// If this two contact can be classified as "near"
+inline int _IsNearContacts(sLocalContactData& c1,sLocalContactData& c2)
+{
+	int bPosNear = 0;
+	int bSameDir = 0;
+	dVector3	vDiff;
+
+	// First check if they are "near" in position
+	SUBTRACT(c1.vPos,c2.vPos,vDiff);
+	if (  (dFabs(vDiff[0]) < fSameContactPositionEpsilon)
+		&&(dFabs(vDiff[1]) < fSameContactPositionEpsilon)
+		&&(dFabs(vDiff[2]) < fSameContactPositionEpsilon))
+	{
+		bPosNear = 1;
+	}
+
+	// Second check if they are "near" in normal direction
+	SUBTRACT(c1.vNormal,c2.vNormal,vDiff);
+	if (  (dFabs(vDiff[0]) < fSameContactNormalEpsilon)
+		&&(dFabs(vDiff[1]) < fSameContactNormalEpsilon)
+		&&(dFabs(vDiff[2]) < fSameContactNormalEpsilon) )
+	{
+		bSameDir = 1;
+	}
+
+	// Will be "near" if position and normal direction are "near"
+	return (bPosNear && bSameDir);
+}
+
+inline int _IsBetter(sLocalContactData& c1,sLocalContactData& c2)
+{
+	// The not better will be throw away
+	// You can change the selection criteria here
+	return (c1.fDepth > c2.fDepth);
+}
+
+// iterate through gLocalContacts and filtered out "near contact"
+inline void	_OptimizeLocalContacts()
+{
+	int nContacts = ctContacts;
+		
+	for (int i = 0; i < nContacts-1; i++)
+	{
+		for (int j = i+1; j < nContacts; j++)
+		{
+			if (_IsNearContacts(gLocalContacts[i],gLocalContacts[j]))
+			{
+				// If they are seem to be the samed then filtered 
+				// out the least penetrate one
+				if (_IsBetter(gLocalContacts[j],gLocalContacts[i]))
+				{
+					gLocalContacts[i].nFlags = 0; // filtered 1st contact
+				}
+				else
+				{
+					gLocalContacts[j].nFlags = 0; // filtered 2nd contact
+				}
+
+				// NOTE
+				// There is other way is to add two depth together but
+				// it not work so well. Why???
+			}
+		}
+	}
+}
+
+inline int	_ProcessLocalContacts()
+{
+	if (ctContacts == 0)
+	{
+		return 0;
+	}
+
+#ifdef OPTIMIZE_CONTACTS
+	if (ctContacts > 1 && !(iFlags & CONTACTS_UNIMPORTANT))
+	{
+		// Can be optimized...
+		_OptimizeLocalContacts();
+	}
+#endif		
+
+	unsigned int iContact = 0;
+	dContactGeom* Contact = 0;
+
+	unsigned int nFinalContact = 0;
+
+	for (iContact = 0; iContact < ctContacts; iContact ++)
+	{
+        // Ensure that we haven't created too many contacts
+        if( nFinalContact >= (iFlags & NUMC_MASK)) 
+		{
+            break;
+        }
+
+		if (1 == gLocalContacts[iContact].nFlags)
+		{
+				Contact =  SAFECONTACT(iFlags, ContactGeoms, nFinalContact, iStride);
+				Contact->depth = gLocalContacts[iContact].fDepth;
+				SET(Contact->normal,gLocalContacts[iContact].vNormal);
+				SET(Contact->pos,gLocalContacts[iContact].vPos);
+				Contact->g1 = gTriMesh;
+				Contact->g2 = gCylinder;
+				Contact->side2 = gLocalContacts[iContact].triIndex;
+
+				nFinalContact++;
+		}
+	}
+	// debug
+	//if (nFinalContact != ctContacts)
+	//{
+	//	printf("[Info] %d contacts generated,%d  filtered.\n",ctContacts,ctContacts-nFinalContact);
+	//}
+
+	return nFinalContact;
+}
+
+BOOL _cldClipEdgeToPlane( dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane)
+{
+	// calculate distance of edge points to plane
+	dReal fDistance0 = POINTDISTANCE( plPlane, vEpnt0 );
+	dReal fDistance1 = POINTDISTANCE( plPlane, vEpnt1 );
+
+	// if both points are behind the plane
+	if ( fDistance0 < 0 && fDistance1 < 0 ) 
+	{
+		// do nothing
+		return FALSE;
+		// if both points in front of the plane
+	} else if ( fDistance0 > 0 && fDistance1 > 0 ) 
+	{
+		// accept them
+		return TRUE;
+		// if we have edge/plane intersection
+	} else if ((fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0)) 
+	{
+
+			// find intersection point of edge and plane
+			dVector3 vIntersectionPoint;
+			vIntersectionPoint[0]= vEpnt0[0]-(vEpnt0[0]-vEpnt1[0])*fDistance0/(fDistance0-fDistance1);
+			vIntersectionPoint[1]= vEpnt0[1]-(vEpnt0[1]-vEpnt1[1])*fDistance0/(fDistance0-fDistance1);
+			vIntersectionPoint[2]= vEpnt0[2]-(vEpnt0[2]-vEpnt1[2])*fDistance0/(fDistance0-fDistance1);
+
+			// clamp correct edge to intersection point
+			if ( fDistance0 < 0 ) 
+			{
+				SET(vEpnt0,vIntersectionPoint);
+			} else 
+			{
+				SET(vEpnt1,vIntersectionPoint);
+			}
+			return TRUE;
+		}
+		return TRUE;
+}
+
+static BOOL _cldTestAxis(const dVector3 &v0,
+						 const dVector3 &v1,
+						 const dVector3 &v2, 
+						 dVector3 vAxis, 
+						 int iAxis,
+						 BOOL bNoFlip = FALSE) 
+{
+
+	// calculate length of separating axis vector
+	dReal fL = LENGTHOF(vAxis);
+	// if not long enough
+	// TODO : dReal epsilon please
+	if ( fL < REAL(1e-5) ) 
+	{
+		// do nothing
+		//iLastOutAxis = 0;
+		return TRUE;
+	}
+
+	// otherwise normalize it
+	dNormalize3(vAxis);
+
+	// project capsule on vAxis
+	dReal frc = dFabs(dDOT(vCapsuleAxis,vAxis))*(fCapsuleSize*REAL(0.5)-vCapsuleRadius) + vCapsuleRadius;
+
+	// project triangle on vAxis
+	dReal afv[3];
+	afv[0] = dDOT( vV0 , vAxis );
+	afv[1] = dDOT( vV1 , vAxis );
+	afv[2] = dDOT( vV2 , vAxis );
+
+	dReal fMin = MAX_REAL;
+	dReal fMax = MIN_REAL;
+
+	// for each vertex 
+	for(int i=0; i<3; i++) 
+	{
+		// find minimum
+		if (afv[i]<fMin) 
+		{
+			fMin = afv[i];
+		}
+		// find maximum
+		if (afv[i]>fMax) 
+		{
+			fMax = afv[i];
+		}
+	}
+
+	// find triangle's center of interval on axis
+	dReal fCenter = (fMin+fMax)*REAL(0.5);
+	// calculate triangles half interval 
+	dReal fTriangleRadius = (fMax-fMin)*REAL(0.5);
+
+	// if they do not overlap, 
+	if( dFabs(fCenter) > ( frc + fTriangleRadius ) ) 
+	{ 
+		// exit, we have no intersection
+		return FALSE; 
+	}
+
+	// calculate depth 
+	dReal fDepth = dFabs(fCenter) - (frc+fTriangleRadius);
+
+	// if greater then best found so far
+	if ( fDepth > fBestDepth ) 
+	{
+		// remember depth
+		fBestDepth  = fDepth;
+		fBestCenter = fCenter;
+		fBestrt     = fTriangleRadius;
+
+		vNormal[0]     = vAxis[0];
+		vNormal[1]     = vAxis[1];
+		vNormal[2]     = vAxis[2];
+
+		iBestAxis   = iAxis;
+
+		// flip normal if interval is wrong faced
+		if (fCenter<0 && !bNoFlip) 
+		{ 
+			vNormal[0] = -vNormal[0];
+			vNormal[1] = -vNormal[1];
+			vNormal[2] = -vNormal[2];
+
+			fBestCenter = -fCenter;
+		}
+	}
+
+	return TRUE;
+}
+
+// helper for less key strokes
+inline void _CalculateAxis(const dVector3& v1,
+						   const dVector3& v2,
+						   const dVector3& v3,
+						   const dVector3& v4,
+						   dVector3& r)
+{
+	dVector3 t1;
+	dVector3 t2;
+
+	SUBTRACT(v1,v2,t1);
+	dCROSS(t2,=,t1,v3);
+	dCROSS(r,=,t2,v4);
+}
+
+static BOOL _cldTestSeparatingAxesOfCapsule(const dVector3 &v0,
+											const dVector3 &v1,
+											const dVector3 &v2,
+											uint8 flags) 
+{
+	// calculate caps centers in absolute space
+	dVector3 vCp0;
+	vCp0[0] = vCapsulePosition[0] + vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCp0[1] = vCapsulePosition[1] + vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCp0[2] = vCapsulePosition[2] + vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+
+	dVector3 vCp1;
+	vCp1[0] = vCapsulePosition[0] - vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCp1[1] = vCapsulePosition[1] - vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCp1[2] = vCapsulePosition[2] - vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+
+	// reset best axis
+	iBestAxis = 0;
+	// reset best depth
+	fBestDepth  = -MAX_REAL;
+	// reset separating axis vector
+	dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)};
+
+	// Epsilon value for checking axis vector length 
+	const dReal fEpsilon = 1e-6f;
+
+	// Translate triangle to Cc cord.
+	SUBTRACT(v0 , vCapsulePosition, vV0);
+	SUBTRACT(v1 , vCapsulePosition, vV1);
+	SUBTRACT(v2 , vCapsulePosition, vV2);
+	
+	// We begin to test for 19 separating axis now
+	// I wonder does it help if we employ the method like ISA-GJK???
+	// Or at least we should do experiment and find what axis will
+	// be most likely to be separating axis to check it first.
+
+	// Original
+	// axis vN
+	//vAxis = -vN;
+	vAxis[0] = - vN[0];
+	vAxis[1] = - vN[1];
+	vAxis[2] = - vN[2];
+	if (!_cldTestAxis( v0, v1, v2, vAxis, 1, TRUE)) 
+	{ 
+		return FALSE; 
+	}
+
+	if (flags & dxTriMeshData::kEdge0)
+	{
+		// axis CxE0 - Edge 0
+		dCROSS(vAxis,=,vCapsuleAxis,vE0);
+		//vAxis = dCROSS( vCapsuleAxis cross vE0 );
+		if( _length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 2)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge1)
+	{
+		// axis CxE1 - Edge 1
+		dCROSS(vAxis,=,vCapsuleAxis,vE1);
+		//vAxis = ( vCapsuleAxis cross vE1 );
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 3)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge2)
+	{
+		// axis CxE2 - Edge 2
+		//vAxis = ( vCapsuleAxis cross vE2 );
+		dCROSS(vAxis,=,vCapsuleAxis,vE2);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 4)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge0)
+	{
+		// first capsule point
+		// axis ((Cp0-V0) x E0) x E0
+		_CalculateAxis(vCp0,v0,vE0,vE0,vAxis);
+	//	vAxis = ( ( vCp0-v0) cross vE0 ) cross vE0;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 5)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge1)
+	{
+		// axis ((Cp0-V1) x E1) x E1
+		_CalculateAxis(vCp0,v1,vE1,vE1,vAxis);
+		//vAxis = ( ( vCp0-v1) cross vE1 ) cross vE1;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 6)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge2)
+	{
+		// axis ((Cp0-V2) x E2) x E2
+		_CalculateAxis(vCp0,v2,vE2,vE2,vAxis);
+		//vAxis = ( ( vCp0-v2) cross vE2 ) cross vE2;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 7)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge0)
+	{
+		// second capsule point
+		// axis ((Cp1-V0) x E0) x E0
+		_CalculateAxis(vCp1,v0,vE0,vE0,vAxis);	
+		//vAxis = ( ( vCp1-v0 ) cross vE0 ) cross vE0;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 8)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge1)
+	{
+		// axis ((Cp1-V1) x E1) x E1
+		_CalculateAxis(vCp1,v1,vE1,vE1,vAxis);	
+		//vAxis = ( ( vCp1-v1 ) cross vE1 ) cross vE1;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 9)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kEdge2)
+	{
+		// axis ((Cp1-V2) x E2) x E2
+		_CalculateAxis(vCp1,v2,vE2,vE2,vAxis);	
+		//vAxis = ( ( vCp1-v2 ) cross vE2 ) cross vE2;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 10)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert0)
+	{
+		// first vertex on triangle
+		// axis ((V0-Cp0) x C) x C
+		_CalculateAxis(v0,vCp0,vCapsuleAxis,vCapsuleAxis,vAxis);	
+		//vAxis = ( ( v0-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 11)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert1)
+	{
+		// second vertex on triangle
+		// axis ((V1-Cp0) x C) x C
+		_CalculateAxis(v1,vCp0,vCapsuleAxis,vCapsuleAxis,vAxis);	
+		//vAxis = ( ( v1-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 12)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert2)
+	{
+		// third vertex on triangle
+		// axis ((V2-Cp0) x C) x C
+		_CalculateAxis(v2,vCp0,vCapsuleAxis,vCapsuleAxis,vAxis);	
+		//vAxis = ( ( v2-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 13)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	// Test as separating axes direction vectors between each triangle
+	// edge and each capsule's cap center
+
+	if (flags & dxTriMeshData::kVert0)
+	{
+		// first triangle vertex and first capsule point
+		//vAxis = v0 - vCp0;
+		SUBTRACT(v0,vCp0,vAxis);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 14)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert1)
+	{
+		// second triangle vertex and first capsule point
+		//vAxis = v1 - vCp0;
+		SUBTRACT(v1,vCp0,vAxis);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 15)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert2)
+	{
+		// third triangle vertex and first capsule point
+		//vAxis = v2 - vCp0;
+		SUBTRACT(v2,vCp0,vAxis);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 16)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert0)
+	{
+		// first triangle vertex and second capsule point
+		//vAxis = v0 - vCp1;
+		SUBTRACT(v0,vCp1,vAxis);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 17)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert1)
+	{
+		// second triangle vertex and second capsule point
+		//vAxis = v1 - vCp1;
+		SUBTRACT(v1,vCp1,vAxis);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 18)) { 
+				return FALSE; 
+			}
+		}
+	}
+
+	if (flags & dxTriMeshData::kVert2)
+	{
+		// third triangle vertex and second capsule point
+		//vAxis = v2 - vCp1;
+		SUBTRACT(v2,vCp1,vAxis);
+		if(_length2OfVector3( vAxis ) > fEpsilon ) {
+			if (!_cldTestAxis( v0, v1, v2, vAxis, 19)) { 
+				return FALSE; 
+			}
+		}	
+	}
+
+	return TRUE;
+}
+
+// test one mesh triangle on intersection with capsule
+static void _cldTestOneTriangleVSCapsule( const dVector3 &v0, 
+											const dVector3 &v1, 
+											const dVector3 &v2,
+											uint8 flags)
+{
+
+	// calculate edges
+	SUBTRACT(v1,v0,vE0);
+	SUBTRACT(v2,v1,vE1);
+	SUBTRACT(v0,v2,vE2);
+
+	dVector3	_minus_vE0;
+	SUBTRACT(v0,v1,_minus_vE0);
+
+	// calculate poly normal
+	dCROSS(vN,=,vE1,_minus_vE0);
+	dNormalize3(vN);
+	
+	// create plane from triangle
+	dReal plDistance = -dDOT(v0,vN);
+	dVector4 plTrianglePlane;
+	CONSTRUCTPLANE(plTrianglePlane,vN,plDistance);
+	
+	// calculate capsule distance to plane
+	dReal fDistanceCapsuleCenterToPlane = POINTDISTANCE(plTrianglePlane,vCapsulePosition);
+
+	// Capsule must be over positive side of triangle
+	if(fDistanceCapsuleCenterToPlane < 0 /* && !bDoubleSided*/) 
+	{
+		// if not don't generate contacts
+		return;
+	}
+
+	dVector3 vPnt0;
+	SET	(vPnt0,v0);
+	dVector3 vPnt1;
+	SET	(vPnt1,v1);
+	dVector3 vPnt2;
+	SET	(vPnt2,v2);
+
+	if (fDistanceCapsuleCenterToPlane < 0 )
+	{
+		SET	(vPnt0,v0);
+		SET	(vPnt1,v2);
+		SET	(vPnt2,v1);
+	}
+
+	// do intersection test and find best separating axis
+	if(!_cldTestSeparatingAxesOfCapsule(vPnt0, vPnt1, vPnt2, flags) ) 
+	{
+		// if not found do nothing
+		return;
+	}
+
+	// if best separation axis is not found
+	if ( iBestAxis == 0 ) 
+	{
+		// this should not happen (we should already exit in that case)
+		dIASSERT(FALSE);
+		// do nothing
+		return;
+	}
+
+	// calculate caps centers in absolute space
+	dVector3 vCposTrans;
+	vCposTrans[0] = vCapsulePosition[0] + vNormal[0]*vCapsuleRadius;
+	vCposTrans[1] = vCapsulePosition[1] + vNormal[1]*vCapsuleRadius;
+	vCposTrans[2] = vCapsulePosition[2] + vNormal[2]*vCapsuleRadius;
+
+	dVector3 vCEdgePoint0;
+	vCEdgePoint0[0]  = vCposTrans[0] + vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCEdgePoint0[1]  = vCposTrans[1] + vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCEdgePoint0[2]  = vCposTrans[2] + vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+    
+	dVector3 vCEdgePoint1;
+	vCEdgePoint1[0] = vCposTrans[0] - vCapsuleAxis[0]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCEdgePoint1[1] = vCposTrans[1] - vCapsuleAxis[1]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+	vCEdgePoint1[2] = vCposTrans[2] - vCapsuleAxis[2]*(fCapsuleSize*REAL(0.5)-vCapsuleRadius);
+
+	// transform capsule edge points into triangle space
+	vCEdgePoint0[0] -= vPnt0[0];
+	vCEdgePoint0[1] -= vPnt0[1];
+	vCEdgePoint0[2] -= vPnt0[2];
+
+	vCEdgePoint1[0] -= vPnt0[0];
+	vCEdgePoint1[1] -= vPnt0[1];
+	vCEdgePoint1[2] -= vPnt0[2];
+
+	dVector4 plPlane;
+	dVector3 _minus_vN;
+	_minus_vN[0] = -vN[0];
+	_minus_vN[1] = -vN[1];
+	_minus_vN[2] = -vN[2];
+	// triangle plane
+	CONSTRUCTPLANE(plPlane,_minus_vN,0);
+	//plPlane = Plane4f( -vN, 0);
+
+	if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
+	{ 
+		return; 
+	}
+
+	// plane with edge 0
+	dVector3 vTemp;
+	dCROSS(vTemp,=,vN,vE0);
+	CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5));
+	if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
+	{ 
+		return; 
+	}
+
+	dCROSS(vTemp,=,vN,vE1);
+	CONSTRUCTPLANE(plPlane, vTemp, -(dDOT(vE0,vTemp)-REAL(1e-5)));
+	if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
+	{ 
+		return; 
+	}
+
+	dCROSS(vTemp,=,vN,vE2);
+	CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5));
+	if(!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { 
+		return; 
+	}
+
+	// return capsule edge points into absolute space
+	vCEdgePoint0[0] += vPnt0[0];
+	vCEdgePoint0[1] += vPnt0[1];
+	vCEdgePoint0[2] += vPnt0[2];
+
+	vCEdgePoint1[0] += vPnt0[0];
+	vCEdgePoint1[1] += vPnt0[1];
+	vCEdgePoint1[2] += vPnt0[2];
+
+	// calculate depths for both contact points
+	SUBTRACT(vCEdgePoint0,vCapsulePosition,vTemp);
+	dReal fDepth0 = dDOT(vTemp,vNormal) - (fBestCenter-fBestrt);
+	SUBTRACT(vCEdgePoint1,vCapsulePosition,vTemp);
+	dReal fDepth1 = dDOT(vTemp,vNormal) - (fBestCenter-fBestrt);
+
+	// clamp depths to zero
+	if(fDepth0 < 0) 
+	{
+		fDepth0 = 0.0f;
+	}
+
+	if(fDepth1 < 0 ) 
+	{
+		fDepth1 = 0.0f;
+	}
+
+	// Cached contacts's data
+	// contact 0
+    dIASSERT(ctContacts < (iFlags & NUMC_MASK)); // Do not call function if there is no room to store result
+	gLocalContacts[ctContacts].fDepth = fDepth0;
+	SET(gLocalContacts[ctContacts].vNormal,vNormal);
+	SET(gLocalContacts[ctContacts].vPos,vCEdgePoint0);
+	gLocalContacts[ctContacts].nFlags = 1;
+	ctContacts++;
+
+        if (ctContacts < (iFlags & NUMC_MASK)) {
+	// contact 1
+	gLocalContacts[ctContacts].fDepth = fDepth1;
+	SET(gLocalContacts[ctContacts].vNormal,vNormal);
+	SET(gLocalContacts[ctContacts].vPos,vCEdgePoint1);
+	gLocalContacts[ctContacts].nFlags = 1;
+	ctContacts++;
+        }
+
+}
+
+// capsule - trimesh by CroTeam
+// Ported by Nguyem Binh
+int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dTriMeshClass);
+	dIASSERT (o2->type == dCapsuleClass);
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+	
+	dxTriMesh* TriMesh = (dxTriMesh*)o1;
+	gCylinder = o2;
+	gTriMesh = o1;
+
+	const dMatrix3* pRot = (const dMatrix3*) dGeomGetRotation(gCylinder);
+	memcpy(mCapsuleRotation,pRot,sizeof(dMatrix3));
+
+	const dVector3* pDst = (const dVector3*)dGeomGetPosition(gCylinder);
+	memcpy(vCapsulePosition,pDst,sizeof(dVector3));
+
+	vCapsuleAxis[0] = mCapsuleRotation[0*4 + nCAPSULE_AXIS]; 
+	vCapsuleAxis[1] = mCapsuleRotation[1*4 + nCAPSULE_AXIS];
+	vCapsuleAxis[2] = mCapsuleRotation[2*4 + nCAPSULE_AXIS];
+
+	// Get size of Capsule
+	dGeomCapsuleGetParams(gCylinder,&vCapsuleRadius,&fCapsuleSize);
+	fCapsuleSize += 2*vCapsuleRadius;
+
+	const dMatrix3* pTriRot = (const dMatrix3*)dGeomGetRotation(TriMesh);
+	memcpy(mTriMeshRot,pTriRot,sizeof(dMatrix3));
+
+	const dVector3* pTriPos = (const dVector3*)dGeomGetPosition(TriMesh);
+	memcpy(mTriMeshPos,pTriPos,sizeof(dVector3));	
+
+	// global info for contact creation
+	iStride			=skip;
+	iFlags			=flags;
+	ContactGeoms	=contact;
+
+	// reset contact counter
+	ctContacts = 0;	
+
+	// reset best depth
+	fBestDepth  = - MAX_REAL;
+	fBestCenter = 0;
+	fBestrt     = 0;
+
+
+
+
+	// reset collision normal
+	vNormal[0] = REAL(0.0);
+	vNormal[1] = REAL(0.0);
+	vNormal[2] = REAL(0.0);
+
+	// Will it better to use LSS here? -> confirm Pierre.
+	 OBBCollider& Collider = TriMesh->_OBBCollider;
+
+	 // It is a potential issue to explicitly cast to float 
+	 // if custom width floating point type is introduced in OPCODE.
+	 // It is necessary to make a typedef and cast to it
+	 // (e.g. typedef float opc_float;)
+	 // However I'm not sure in what header it should be added.
+	 
+	 Point cCenter(/*(float)*/ vCapsulePosition[0], /*(float)*/ vCapsulePosition[1], /*(float)*/ vCapsulePosition[2]);
+	 Point cExtents(/*(float)*/ vCapsuleRadius, /*(float)*/ vCapsuleRadius,/*(float)*/ fCapsuleSize/2);
+	 
+	 Matrix3x3 obbRot;
+
+	 obbRot[0][0] = /*(float)*/ mCapsuleRotation[0];
+	 obbRot[1][0] = /*(float)*/ mCapsuleRotation[1];
+	 obbRot[2][0] = /*(float)*/ mCapsuleRotation[2];
+
+	 obbRot[0][1] = /*(float)*/ mCapsuleRotation[4];
+	 obbRot[1][1] = /*(float)*/ mCapsuleRotation[5];
+	 obbRot[2][1] = /*(float)*/ mCapsuleRotation[6];
+
+	 obbRot[0][2] = /*(float)*/ mCapsuleRotation[8];
+	 obbRot[1][2] = /*(float)*/ mCapsuleRotation[9];
+	 obbRot[2][2] = /*(float)*/ mCapsuleRotation[10];
+
+	 OBB obbCapsule(cCenter,cExtents,obbRot);
+
+	 Matrix4x4 CapsuleMatrix;
+	 MakeMatrix(vCapsulePosition, mCapsuleRotation, CapsuleMatrix);
+
+	 Matrix4x4 MeshMatrix;
+	 MakeMatrix(mTriMeshPos, mTriMeshRot, MeshMatrix);
+
+	 // TC results
+	 if (TriMesh->doBoxTC) {
+		 dxTriMesh::BoxTC* BoxTC = 0;
+		 for (int i = 0; i < TriMesh->BoxTCCache.size(); i++){
+			 if (TriMesh->BoxTCCache[i].Geom == gCylinder){
+				 BoxTC = &TriMesh->BoxTCCache[i];
+				 break;
+			 }
+		 }
+		 if (!BoxTC){
+			 TriMesh->BoxTCCache.push(dxTriMesh::BoxTC());
+
+			 BoxTC = &TriMesh->BoxTCCache[TriMesh->BoxTCCache.size() - 1];
+			 BoxTC->Geom = gCylinder;
+			 BoxTC->FatCoeff = 1.0f;
+		 }
+
+		 // Intersect
+		 Collider.SetTemporalCoherence(true);
+		 Collider.Collide(*BoxTC, obbCapsule, TriMesh->Data->BVTree, null, &MeshMatrix);
+	 }
+	 else {
+		 Collider.SetTemporalCoherence(false);
+		 Collider.Collide(dxTriMesh::defaultBoxCache, obbCapsule, TriMesh->Data->BVTree, null,&MeshMatrix);
+	 }
+	 
+	 if (! Collider.GetContactStatus()) {
+	 	// no collision occurred
+	 	return 0;
+	 }
+
+	 // Retrieve data
+	 int TriCount = Collider.GetNbTouchedPrimitives();
+	 const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
+
+	 if (TriCount != 0)
+	 {
+		 if (TriMesh->ArrayCallback != null)
+		 {
+			 TriMesh->ArrayCallback(TriMesh, gCylinder, Triangles, TriCount);
+		 }
+
+		// allocate buffer for local contacts on stack
+		gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(iFlags & NUMC_MASK));
+
+	    unsigned int ctContacts0 = ctContacts;
+
+		uint8* UseFlags = TriMesh->Data->UseFlags;
+
+		// loop through all intersecting triangles
+		for (int i = 0; i < TriCount; i++)
+		{
+			const int Triint = Triangles[i];
+			if (!Callback(TriMesh, gCylinder, Triint)) continue;
+
+
+			dVector3 dv[3];
+			FetchTriangle(TriMesh, Triint, mTriMeshPos, mTriMeshRot, dv);
+
+			uint8 flags = UseFlags ? UseFlags[Triint] : dxTriMeshData::kUseAll;
+
+			// test this triangle
+			_cldTestOneTriangleVSCapsule(dv[0],dv[1],dv[2], flags);
+			
+			// fill-in tri index for generated contacts
+			for (; ctContacts0<ctContacts; ctContacts0++)
+				gLocalContacts[ctContacts0].triIndex = Triint;
+
+			// Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
+			if(ctContacts>=(iFlags & NUMC_MASK)) 
+			{
+				break;
+			}
+			
+		}
+	 }
+
+	return _ProcessLocalContacts();
+}
+#endif
+
+// GIMPACT version
+#if dTRIMESH_GIMPACT
+#define nCAPSULE_AXIS 2
+// capsule - trimesh  By francisco leon
+int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dTriMeshClass);
+	dIASSERT (o2->type == dCapsuleClass);
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+	
+	dxTriMesh* TriMesh = (dxTriMesh*)o1;
+	dxGeom*	   gCylinder = o2;
+
+    //Get capsule params
+    dMatrix3  mCapsuleRotation;
+    dVector3   vCapsulePosition;
+    dVector3   vCapsuleAxis;
+    dReal      vCapsuleRadius;
+    dReal      fCapsuleSize;
+    dMatrix3* pRot = (dMatrix3*) dGeomGetRotation(gCylinder);
+	memcpy(mCapsuleRotation,pRot,sizeof(dMatrix3));
+	dVector3* pDst = (dVector3*)dGeomGetPosition(gCylinder);
+	memcpy(vCapsulePosition,pDst,sizeof(dVector3));
+	//Axis
+	vCapsuleAxis[0] = mCapsuleRotation[0*4 + nCAPSULE_AXIS];
+	vCapsuleAxis[1] = mCapsuleRotation[1*4 + nCAPSULE_AXIS];
+	vCapsuleAxis[2] = mCapsuleRotation[2*4 + nCAPSULE_AXIS];
+	// Get size of CCylinder
+	dGeomCCylinderGetParams(gCylinder,&vCapsuleRadius,&fCapsuleSize);
+	fCapsuleSize*=0.5f;
+	//Set Capsule params
+	GIM_CAPSULE_DATA capsule;
+
+	capsule.m_radius = vCapsuleRadius;
+	VEC_SCALE(capsule.m_point1,fCapsuleSize,vCapsuleAxis);
+	VEC_SUM(capsule.m_point1,vCapsulePosition,capsule.m_point1);
+	VEC_SCALE(capsule.m_point2,-fCapsuleSize,vCapsuleAxis);
+	VEC_SUM(capsule.m_point2,vCapsulePosition,capsule.m_point2);
+
+
+//Create contact list
+    GDYNAMIC_ARRAY trimeshcontacts;
+    GIM_CREATE_CONTACT_LIST(trimeshcontacts);
+
+    //Collide trimeshe vs capsule
+    gim_trimesh_capsule_collision(&TriMesh->m_collision_trimesh,&capsule,&trimeshcontacts);
+
+
+    if(trimeshcontacts.m_size == 0)
+    {
+        GIM_DYNARRAY_DESTROY(trimeshcontacts);
+        return 0;
+    }
+
+    GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
+
+	unsigned contactcount = trimeshcontacts.m_size;
+	unsigned contactmax = (unsigned)(flags & NUMC_MASK);
+	if (contactcount > contactmax)
+	{
+		contactcount = contactmax;
+	}
+
+    dContactGeom* pcontact;
+	unsigned i;
+
+	for (i=0;i<contactcount;i++)
+	{
+        pcontact = SAFECONTACT(flags, contact, i, skip);
+
+        pcontact->pos[0] = ptrimeshcontacts->m_point[0];
+        pcontact->pos[1] = ptrimeshcontacts->m_point[1];
+        pcontact->pos[2] = ptrimeshcontacts->m_point[2];
+        pcontact->pos[3] = 1.0f;
+
+        pcontact->normal[0] = ptrimeshcontacts->m_normal[0];
+        pcontact->normal[1] = ptrimeshcontacts->m_normal[1];
+        pcontact->normal[2] = ptrimeshcontacts->m_normal[2];
+        pcontact->normal[3] = 0;
+
+        pcontact->depth = ptrimeshcontacts->m_depth;
+        pcontact->g1 = TriMesh;
+        pcontact->g2 = gCylinder;
+
+        ptrimeshcontacts++;
+	}
+
+	GIM_DYNARRAY_DESTROY(trimeshcontacts);
+
+    return (int)contactcount;
+}
+#endif
+
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_distance.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_distance.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_distance.cpp	(revision 216)
@@ -0,0 +1,1255 @@
+// This file contains some code based on the code from Magic Software.
+// That code is available under a Free Source License Agreement
+// that can be found at http://www.magic-software.com/License/free.pdf
+ 
+#include <ode/common.h>
+#include <ode/odemath.h>
+#include <ode/collision.h>
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+//------------------------------------------------------------------------------
+/**
+  @brief Finds the shortest distance squared between a point and a triangle.
+  
+  @param pfSParam  Barycentric coordinate of triangle at point closest to p (u)
+  @param pfTParam  Barycentric coordinate of triangle at point closest to p (v)
+  @return Shortest distance squared.
+  
+  The third Barycentric coordinate is implicit, ie. w = 1.0 - u - v
+  
+  Taken from:
+  Magic Software, Inc.
+  http://www.magic-software.com
+*/
+dReal SqrDistancePointTri( const dVector3 p, const dVector3 triOrigin, 
+                           const dVector3 triEdge0, const dVector3 triEdge1,
+                           dReal* pfSParam, dReal* pfTParam )
+{
+  dVector3 kDiff;
+  Vector3Subtract( triOrigin, p, kDiff );
+  dReal fA00 = dDOT( triEdge0, triEdge0 );
+  dReal fA01 = dDOT( triEdge0, triEdge1 );
+  dReal fA11 = dDOT( triEdge1, triEdge1 );
+  dReal fB0 = dDOT( kDiff, triEdge0 );
+  dReal fB1 = dDOT( kDiff, triEdge1 );
+  dReal fC = dDOT( kDiff, kDiff );
+  dReal fDet = dReal(fabs(fA00*fA11-fA01*fA01));
+  dReal fS = fA01*fB1-fA11*fB0;
+  dReal fT = fA01*fB0-fA00*fB1;
+  dReal fSqrDist;
+
+  if ( fS + fT <= fDet )
+  {
+    if ( fS < REAL(0.0) )
+    {
+      if ( fT < REAL(0.0) )  // region 4
+      {
+        if ( fB0 < REAL(0.0) )
+        {
+          fT = REAL(0.0);
+          if ( -fB0 >= fA00 )
+          {
+            fS = REAL(1.0);
+            fSqrDist = fA00+REAL(2.0)*fB0+fC;
+          }
+          else
+          {
+            fS = -fB0/fA00;
+            fSqrDist = fB0*fS+fC;
+          }
+        }
+        else
+        {
+          fS = REAL(0.0);
+          if ( fB1 >= REAL(0.0) )
+          {
+            fT = REAL(0.0);
+            fSqrDist = fC;
+          }
+          else if ( -fB1 >= fA11 )
+          {
+            fT = REAL(1.0);
+            fSqrDist = fA11+REAL(2.0)*fB1+fC;
+          }
+          else
+          {
+            fT = -fB1/fA11;
+            fSqrDist = fB1*fT+fC;
+          }
+        }
+      }
+      else  // region 3
+      {
+        fS = REAL(0.0);
+        if ( fB1 >= REAL(0.0) )
+        {
+          fT = REAL(0.0);
+          fSqrDist = fC;
+        }
+        else if ( -fB1 >= fA11 )
+        {
+          fT = REAL(1.0);
+          fSqrDist = fA11+REAL(2.0)*fB1+fC;
+        }
+        else
+        {
+          fT = -fB1/fA11;
+          fSqrDist = fB1*fT+fC;
+        }
+      }
+    }
+    else if ( fT < REAL(0.0) )  // region 5
+    {
+      fT = REAL(0.0);
+      if ( fB0 >= REAL(0.0) )
+      {
+        fS = REAL(0.0);
+        fSqrDist = fC;
+      }
+      else if ( -fB0 >= fA00 )
+      {
+        fS = REAL(1.0);
+        fSqrDist = fA00+REAL(2.0)*fB0+fC;
+      }
+      else
+      {
+        fS = -fB0/fA00;
+        fSqrDist = fB0*fS+fC;
+      }
+    }
+    else  // region 0
+    {
+      // minimum at interior point
+      if ( fDet == REAL(0.0) )
+      {
+        fS = REAL(0.0);
+        fT = REAL(0.0);
+        fSqrDist = dInfinity;
+      } 
+      else
+      {
+        dReal fInvDet = REAL(1.0)/fDet;
+        fS *= fInvDet;
+        fT *= fInvDet;
+        fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
+                   fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
+      }
+    }
+  }
+  else
+  {
+    dReal fTmp0, fTmp1, fNumer, fDenom;
+
+    if ( fS < REAL(0.0) )  // region 2
+    {
+      fTmp0 = fA01 + fB0;
+      fTmp1 = fA11 + fB1;
+      if ( fTmp1 > fTmp0 )
+      {
+        fNumer = fTmp1 - fTmp0;
+        fDenom = fA00-REAL(2.0)*fA01+fA11;
+        if ( fNumer >= fDenom )
+        {
+          fS = REAL(1.0);
+          fT = REAL(0.0);
+          fSqrDist = fA00+REAL(2.0)*fB0+fC;
+        }
+        else
+        {
+          fS = fNumer/fDenom;
+          fT = REAL(1.0) - fS;
+          fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
+                     fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
+        }
+      }
+      else
+      {
+        fS = REAL(0.0);
+        if ( fTmp1 <= REAL(0.0) )
+        {
+          fT = REAL(1.0);
+          fSqrDist = fA11+REAL(2.0)*fB1+fC;
+        }
+        else if ( fB1 >= REAL(0.0) )
+        {
+          fT = REAL(0.0);
+          fSqrDist = fC;
+        }
+        else
+        {
+          fT = -fB1/fA11;
+          fSqrDist = fB1*fT+fC;
+        }
+      }
+    }
+    else if ( fT < REAL(0.0) )  // region 6
+    {
+      fTmp0 = fA01 + fB1;
+      fTmp1 = fA00 + fB0;
+      if ( fTmp1 > fTmp0 )
+      {
+        fNumer = fTmp1 - fTmp0;
+        fDenom = fA00-REAL(2.0)*fA01+fA11;
+        if ( fNumer >= fDenom )
+        {
+          fT = REAL(1.0);
+          fS = REAL(0.0);
+          fSqrDist = fA11+REAL(2.0)*fB1+fC;
+        }
+        else
+        {
+          fT = fNumer/fDenom;
+          fS = REAL(1.0) - fT;
+          fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
+                     fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
+        }
+      }
+      else
+      {
+        fT = REAL(0.0);
+        if ( fTmp1 <= REAL(0.0) )
+        {
+          fS = REAL(1.0);
+          fSqrDist = fA00+REAL(2.0)*fB0+fC;
+        }
+        else if ( fB0 >= REAL(0.0) )
+        {
+          fS = REAL(0.0);
+          fSqrDist = fC;
+        }
+        else
+        {
+          fS = -fB0/fA00;
+          fSqrDist = fB0*fS+fC;
+        }
+      }
+    }
+    else  // region 1
+    {
+      fNumer = fA11 + fB1 - fA01 - fB0;
+      if ( fNumer <= REAL(0.0) )
+      {
+        fS = REAL(0.0);
+        fT = REAL(1.0);
+        fSqrDist = fA11+REAL(2.0)*fB1+fC;
+      }
+      else
+      {
+        fDenom = fA00-REAL(2.0)*fA01+fA11;
+        if ( fNumer >= fDenom )
+        {
+          fS = REAL(1.0);
+          fT = REAL(0.0);
+          fSqrDist = fA00+REAL(2.0)*fB0+fC;
+        }
+        else
+        {
+          fS = fNumer/fDenom;
+          fT = REAL(1.0) - fS;
+          fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
+                     fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
+        }
+      }
+    }
+  }
+
+  if ( pfSParam )
+      *pfSParam = (float)fS;
+
+  if ( pfTParam )
+      *pfTParam = (float)fT;
+
+  return dReal(fabs(fSqrDist));
+}
+
+//------------------------------------------------------------------------------
+/**
+  @brief Finds the shortest distance squared between two line segments.
+  @param pfSegP0  t value for seg1 where the shortest distance between
+                  the segments exists.
+  @param pfSegP0  t value for seg2 where the shortest distance between
+                  the segments exists.
+  @return Shortest distance squared.
+  
+  Taken from:
+  Magic Software, Inc.
+  http://www.magic-software.com
+*/
+dReal SqrDistanceSegments( const dVector3 seg1Origin, const dVector3 seg1Direction, 
+                           const dVector3 seg2Origin, const dVector3 seg2Direction,
+                           dReal* pfSegP0, dReal* pfSegP1 )
+{
+  const dReal gs_fTolerance = 1e-05f;
+  dVector3 kDiff, kNegDiff, seg1NegDirection;
+  Vector3Subtract( seg1Origin, seg2Origin, kDiff );
+  Vector3Negate( kDiff, kNegDiff );
+  dReal fA00 = dDOT( seg1Direction, seg1Direction );
+  Vector3Negate( seg1Direction, seg1NegDirection );
+  dReal fA01 = dDOT( seg1NegDirection, seg2Direction );
+  dReal fA11 = dDOT( seg2Direction, seg2Direction );
+  dReal fB0 = dDOT( kDiff, seg1Direction );
+  dReal fC = dDOT( kDiff, kDiff );
+  dReal fDet = dReal(fabs(fA00*fA11-fA01*fA01));
+  dReal fB1, fS, fT, fSqrDist, fTmp;
+
+  if ( fDet >= gs_fTolerance )
+  {
+    // line segments are not parallel
+    fB1 = dDOT( kNegDiff, seg2Direction );
+    fS = fA01*fB1-fA11*fB0;
+    fT = fA01*fB0-fA00*fB1;
+        
+    if ( fS >= REAL(0.0) )
+    {
+      if ( fS <= fDet )
+      {
+        if ( fT >= REAL(0.0) )
+        {
+          if ( fT <= fDet )  // region 0 (interior)
+          {
+            // minimum at two interior points of 3D lines
+            dReal fInvDet = REAL(1.0)/fDet;
+            fS *= fInvDet;
+            fT *= fInvDet;
+            fSqrDist = fS*(fA00*fS+fA01*fT+REAL(2.0)*fB0) +
+                       fT*(fA01*fS+fA11*fT+REAL(2.0)*fB1)+fC;
+          }
+          else  // region 3 (side)
+          {
+            fT = REAL(1.0);
+            fTmp = fA01+fB0;
+            if ( fTmp >= REAL(0.0) )
+            {
+              fS = REAL(0.0);
+              fSqrDist = fA11+REAL(2.0)*fB1+fC;
+            }
+            else if ( -fTmp >= fA00 )
+            {
+              fS = REAL(1.0);
+              fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB1+fTmp);
+            }
+            else
+            {
+              fS = -fTmp/fA00;
+              fSqrDist = fTmp*fS+fA11+REAL(2.0)*fB1+fC;
+            }
+          }
+        }
+        else  // region 7 (side)
+        {
+          fT = REAL(0.0);
+          if ( fB0 >= REAL(0.0) )
+          {
+            fS = REAL(0.0);
+            fSqrDist = fC;
+          }
+          else if ( -fB0 >= fA00 )
+          {
+            fS = REAL(1.0);
+            fSqrDist = fA00+REAL(2.0)*fB0+fC;
+          }
+          else
+          {
+            fS = -fB0/fA00;
+            fSqrDist = fB0*fS+fC;
+          }
+        }
+      }
+      else
+      {
+        if ( fT >= REAL(0.0) )
+        {
+          if ( fT <= fDet )  // region 1 (side)
+          {
+            fS = REAL(1.0);
+            fTmp = fA01+fB1;
+            if ( fTmp >= REAL(0.0) )
+            {
+              fT = REAL(0.0);
+              fSqrDist = fA00+REAL(2.0)*fB0+fC;
+            }
+            else if ( -fTmp >= fA11 )
+            {
+              fT = REAL(1.0);
+              fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB0+fTmp);
+            }
+            else
+            {
+              fT = -fTmp/fA11;
+              fSqrDist = fTmp*fT+fA00+REAL(2.0)*fB0+fC;
+            }
+          }
+          else  // region 2 (corner)
+          {
+            fTmp = fA01+fB0;
+            if ( -fTmp <= fA00 )
+            {
+              fT = REAL(1.0);
+              if ( fTmp >= REAL(0.0) )
+              {
+                fS = REAL(0.0);
+                fSqrDist = fA11+REAL(2.0)*fB1+fC;
+              }
+              else
+              {
+                fS = -fTmp/fA00;
+                fSqrDist = fTmp*fS+fA11+REAL(2.0)*fB1+fC;
+              }
+            }
+            else
+            {
+              fS = REAL(1.0);
+              fTmp = fA01+fB1;
+              if ( fTmp >= REAL(0.0) )
+              {
+                fT = REAL(0.0);
+                fSqrDist = fA00+REAL(2.0)*fB0+fC;
+              }
+              else if ( -fTmp >= fA11 )
+              {
+                fT = REAL(1.0);
+                fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB0+fTmp);
+              }
+              else
+              {
+                fT = -fTmp/fA11;
+                fSqrDist = fTmp*fT+fA00+REAL(2.0)*fB0+fC;
+              }
+            }
+          }
+        }
+        else  // region 8 (corner)
+        {
+          if ( -fB0 < fA00 )
+          { 
+            fT = REAL(0.0);
+            if ( fB0 >= REAL(0.0) )
+            {
+              fS = REAL(0.0);
+              fSqrDist = fC;
+            }
+            else
+            {
+              fS = -fB0/fA00;
+              fSqrDist = fB0*fS+fC;
+            }
+          }
+          else
+          {
+            fS = REAL(1.0);
+            fTmp = fA01+fB1;
+            if ( fTmp >= REAL(0.0) )
+            {
+              fT = REAL(0.0);
+              fSqrDist = fA00+REAL(2.0)*fB0+fC;
+            }
+            else if ( -fTmp >= fA11 )
+            {
+              fT = REAL(1.0);
+              fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB0+fTmp);
+            }
+            else
+            {
+              fT = -fTmp/fA11;
+              fSqrDist = fTmp*fT+fA00+REAL(2.0)*fB0+fC;
+            }
+          }
+        }
+      }
+    }
+    else 
+    {
+      if ( fT >= REAL(0.0) )
+      {
+        if ( fT <= fDet )  // region 5 (side)
+        {
+          fS = REAL(0.0);
+          if ( fB1 >= REAL(0.0) )
+          {
+            fT = REAL(0.0);
+            fSqrDist = fC;
+          }
+          else if ( -fB1 >= fA11 )
+          {
+            fT = REAL(1.0);
+            fSqrDist = fA11+REAL(2.0)*fB1+fC;
+          }
+          else
+          {
+            fT = -fB1/fA11;
+            fSqrDist = fB1*fT+fC;
+          }
+        }
+        else  // region 4 (corner)
+        {
+          fTmp = fA01+fB0;
+          if ( fTmp < REAL(0.0) )
+          {
+            fT = REAL(1.0);
+            if ( -fTmp >= fA00 )
+            {
+              fS = REAL(1.0);
+              fSqrDist = fA00+fA11+fC+REAL(2.0)*(fB1+fTmp);
+            }
+            else
+            {
+              fS = -fTmp/fA00;
+              fSqrDist = fTmp*fS+fA11+REAL(2.0)*fB1+fC;
+            }
+          }
+          else
+          {
+            fS = REAL(0.0);
+            if ( fB1 >= REAL(0.0) )
+            {
+              fT = REAL(0.0);
+              fSqrDist = fC;
+            }
+            else if ( -fB1 >= fA11 )
+            {
+              fT = REAL(1.0);
+              fSqrDist = fA11+REAL(2.0)*fB1+fC;
+            }
+            else
+            {
+              fT = -fB1/fA11;
+              fSqrDist = fB1*fT+fC;
+            }
+          }
+        }
+      }
+      else   // region 6 (corner)
+      {
+        if ( fB0 < REAL(0.0) )
+        {
+          fT = REAL(0.0);
+          if ( -fB0 >= fA00 )
+          {
+            fS = REAL(1.0);
+            fSqrDist = fA00+REAL(2.0)*fB0+fC;
+          }
+          else
+          {
+            fS = -fB0/fA00;
+            fSqrDist = fB0*fS+fC;
+          }
+        }
+        else
+        {
+          fS = REAL(0.0);
+          if ( fB1 >= REAL(0.0) )
+          {
+            fT = REAL(0.0);
+            fSqrDist = fC;
+          }
+          else if ( -fB1 >= fA11 )
+          {
+            fT = REAL(1.0);
+            fSqrDist = fA11+REAL(2.0)*fB1+fC;
+          }
+          else
+          {
+            fT = -fB1/fA11;
+            fSqrDist = fB1*fT+fC;
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    // line segments are parallel
+    if ( fA01 > REAL(0.0) )
+    {
+      // direction vectors form an obtuse angle
+      if ( fB0 >= REAL(0.0) )
+      {
+        fS = REAL(0.0);
+        fT = REAL(0.0);
+        fSqrDist = fC;
+      }
+      else if ( -fB0 <= fA00 )
+      {
+        fS = -fB0/fA00;
+        fT = REAL(0.0);
+        fSqrDist = fB0*fS+fC;
+      }
+      else
+      {
+        //fB1 = -kDiff % seg2.m;
+        fB1 = dDOT( kNegDiff, seg2Direction );
+        fS = REAL(1.0);
+        fTmp = fA00+fB0;
+        if ( -fTmp >= fA01 )
+        {
+          fT = REAL(1.0);
+          fSqrDist = fA00+fA11+fC+REAL(2.0)*(fA01+fB0+fB1);
+        }
+        else
+        {
+          fT = -fTmp/fA01;
+          fSqrDist = fA00+REAL(2.0)*fB0+fC+fT*(fA11*fT+REAL(2.0)*(fA01+fB1));
+        }
+      }
+    }
+    else
+    {
+      // direction vectors form an acute angle
+      if ( -fB0 >= fA00 )
+      {
+        fS = REAL(1.0);
+        fT = REAL(0.0);
+        fSqrDist = fA00+REAL(2.0)*fB0+fC;
+      }
+      else if ( fB0 <= REAL(0.0) )
+      {
+        fS = -fB0/fA00;
+        fT = REAL(0.0);
+        fSqrDist = fB0*fS+fC;
+      }
+      else
+      {
+        fB1 = dDOT( kNegDiff, seg2Direction );
+        fS = REAL(0.0);
+        if ( fB0 >= -fA01 )
+        {
+          fT = REAL(1.0);
+          fSqrDist = fA11+REAL(2.0)*fB1+fC;
+        }
+        else
+        {
+          fT = -fB0/fA01;
+          fSqrDist = fC+fT*(REAL(2.0)*fB1+fA11*fT);
+        }
+      }
+    }
+  }
+    
+  if ( pfSegP0 )
+    *pfSegP0 = fS;
+  
+  if ( pfSegP1 )
+    *pfSegP1 = fT;
+    
+  return dReal(fabs(fSqrDist));
+}
+
+//------------------------------------------------------------------------------
+/**
+  @brief Finds the shortest distance squared between a line segment and 
+         a triangle.
+         
+  @param pfSegP   t value for the line segment where the shortest distance between
+                  the segment and the triangle occurs.
+                  So the point along the segment that is the shortest distance
+                  away from the triangle can be obtained by (seg.end - seg.start) * t.
+  @param pfTriP0  Barycentric coordinate of triangle at point closest to seg (u)
+  @param pfTriP1  Barycentric coordinate of triangle at point closest to seg (v)
+  @return Shortest distance squared.
+  
+  The third Barycentric coordinate is implicit, ie. w = 1.0 - u - v
+         
+  Taken from:
+  Magic Software, Inc.
+  http://www.magic-software.com
+*/
+dReal SqrDistanceSegTri( const dVector3 segOrigin, const dVector3 segEnd, 
+                         const dVector3 triOrigin, 
+                         const dVector3 triEdge0, const dVector3 triEdge1,
+                         dReal* pfSegP, dReal* pfTriP0, dReal* pfTriP1 )
+{
+  const dReal gs_fTolerance = 1e-06f;
+  dVector3 segDirection, segNegDirection, kDiff, kNegDiff;
+  Vector3Subtract( segEnd, segOrigin, segDirection );
+  Vector3Negate( segDirection, segNegDirection );
+  Vector3Subtract( triOrigin, segOrigin, kDiff );
+  Vector3Negate( kDiff, kNegDiff );
+  dReal fA00 = dDOT( segDirection, segDirection );
+  dReal fA01 = dDOT( segNegDirection, triEdge0 );
+  dReal fA02 = dDOT( segNegDirection, triEdge1 );
+  dReal fA11 = dDOT( triEdge0, triEdge0 );
+  dReal fA12 = dDOT( triEdge0, triEdge1 );
+  dReal fA22 = dDOT( triEdge1, triEdge1 );
+  dReal fB0  = dDOT( kNegDiff, segDirection );
+  dReal fB1  = dDOT( kDiff, triEdge0 );
+  dReal fB2  = dDOT( kDiff, triEdge1 );
+
+  dVector3 kTriSegOrigin, kTriSegDirection, kPt;
+  dReal fSqrDist, fSqrDist0, fR, fS, fT, fR0, fS0, fT0;
+
+  // Set up for a relative error test on the angle between ray direction
+  // and triangle normal to determine parallel/nonparallel status.
+  dVector3 kN;
+  dCROSS( kN, =, triEdge0, triEdge1 );
+  dReal fNSqrLen = dDOT( kN, kN );
+  dReal fDot = dDOT( segDirection, kN );
+  bool bNotParallel = (fDot*fDot >= gs_fTolerance*fA00*fNSqrLen);
+
+  if ( bNotParallel )
+  {
+    dReal fCof00 = fA11*fA22-fA12*fA12;
+    dReal fCof01 = fA02*fA12-fA01*fA22;
+    dReal fCof02 = fA01*fA12-fA02*fA11;
+    dReal fCof11 = fA00*fA22-fA02*fA02;
+    dReal fCof12 = fA02*fA01-fA00*fA12;
+    dReal fCof22 = fA00*fA11-fA01*fA01;
+    dReal fInvDet = REAL(1.0)/(fA00*fCof00+fA01*fCof01+fA02*fCof02);
+    dReal fRhs0 = -fB0*fInvDet;
+    dReal fRhs1 = -fB1*fInvDet;
+    dReal fRhs2 = -fB2*fInvDet;
+
+    fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2;
+    fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2;
+    fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2;
+
+    if ( fR < REAL(0.0) )
+    {
+      if ( fS+fT <= REAL(1.0) )
+      {
+        if ( fS < REAL(0.0) )
+        {
+          if ( fT < REAL(0.0) )  // region 4m
+          {
+            // min on face s=0 or t=0 or r=0
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge1, kTriSegDirection );
+            fSqrDist = SqrDistanceSegments( segOrigin, segDirection, 
+                                            kTriSegOrigin, kTriSegDirection, 
+                                            &fR, &fT );
+            fS = REAL(0.0);
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge0, kTriSegDirection );
+            fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection, 
+                                             kTriSegOrigin, kTriSegDirection, 
+                                             &fR0, &fS0 );
+            fT0 = REAL(0.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+            fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1, 
+                                             &fS0, &fT0 );
+            fR0 = REAL(0.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+          }
+          else  // region 3m
+          {
+            // min on face s=0 or r=0
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge1, kTriSegDirection );
+            fSqrDist = SqrDistanceSegments( segOrigin, segDirection, 
+                                            kTriSegOrigin, kTriSegDirection,
+                                            &fR,&fT );
+            fS = REAL(0.0);
+            fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
+                                             &fS0, &fT0 );
+            fR0 = REAL(0.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+          }
+        }
+        else if ( fT < REAL(0.0) )  // region 5m
+        {
+          // min on face t=0 or r=0
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection, 
+                                          kTriSegOrigin, kTriSegDirection, 
+                                          &fR, &fS );
+          fT = REAL(0.0);
+          fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(0.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else  // region 0m
+        {
+          // min on face r=0
+          fSqrDist = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1, 
+                                          &fS, &fT );
+          fR = REAL(0.0);
+        }
+      }
+      else
+      {
+        if ( fS < REAL(0.0) )  // region 2m
+        {
+          // min on face s=0 or s+t=1 or r=0
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge1, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fT );
+          fS = REAL(0.0);
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection, 
+                                           kTriSegOrigin, kTriSegDirection,
+                                           &fR0, &fT0 );
+          fS0 = REAL(1.0) - fT0;
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+          fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(0.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else if ( fT < REAL(0.0) )  // region 6m
+        {
+          // min on face t=0 or s+t=1 or r=0
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection, 
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fS );
+          fT = REAL(0.0);
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                           kTriSegOrigin, kTriSegDirection,
+                                           &fR0, &fT0 );
+          fS0 = REAL(1.0) - fT0;
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+          fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(0.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else  // region 1m
+        {
+          // min on face s+t=1 or r=0
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fT );
+          fS = REAL(1.0) - fT;
+          fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(0.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+      }
+    }
+    else if ( fR <= REAL(1.0) )
+    {
+      if ( fS+fT <= REAL(1.0) )
+      {
+        if ( fS < REAL(0.0) )
+        {
+          if ( fT < REAL(0.0) )  // region 4
+          {
+            // min on face s=0 or t=0
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge1, kTriSegDirection );
+            fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                            kTriSegOrigin, kTriSegDirection,
+                                            &fR, &fT );
+            fS = REAL(0.0);
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge0, kTriSegDirection );
+            fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection, 
+                                             kTriSegOrigin, kTriSegDirection,
+                                             &fR0, &fS0 );
+            fT0 = REAL(0.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+          }
+          else  // region 3
+          {
+            // min on face s=0
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge1, kTriSegDirection );
+            fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                            kTriSegOrigin, kTriSegDirection,
+                                            &fR, &fT );
+            fS = REAL(0.0);
+          }
+        }
+        else if ( fT < REAL(0.0) )  // region 5
+        {
+          // min on face t=0
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fS );
+          fT = REAL(0.0);
+        }
+        else  // region 0
+        {
+          // global minimum is interior, done
+          fSqrDist = REAL(0.0);
+        }
+      }
+      else
+      {
+        if ( fS < REAL(0.0) )  // region 2
+        {
+          // min on face s=0 or s+t=1
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge1, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fT );
+          fS = REAL(0.0);
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                           kTriSegOrigin, kTriSegDirection,
+                                           &fR0, &fT0 );
+          fS0 = REAL(1.0) - fT0;
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else if ( fT < REAL(0.0) )  // region 6
+        {
+          // min on face t=0 or s+t=1
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fS );
+          fT = REAL(0.0);
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                           kTriSegOrigin, kTriSegDirection,
+                                           &fR0, &fT0 );
+          fS0 = REAL(1.0) - fT0;
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else  // region 1
+        {
+          // min on face s+t=1
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fT );
+          fS = REAL(1.0) - fT;
+        }
+      }
+    }
+    else  // fR > 1
+    {
+      if ( fS+fT <= REAL(1.0) )
+      {
+        if ( fS < REAL(0.0) )
+        {
+          if ( fT < REAL(0.0) )  // region 4p
+          {
+            // min on face s=0 or t=0 or r=1
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge1, kTriSegDirection );
+            fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                            kTriSegOrigin, kTriSegDirection,
+                                            &fR, &fT );
+            fS = REAL(0.0);
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge0, kTriSegDirection );
+            fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                             kTriSegOrigin, kTriSegDirection,
+                                             &fR0, &fS0 );
+            fT0 = REAL(0.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+            Vector3Add( segOrigin, segDirection, kPt );
+            fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
+                                             &fS0, &fT0 );
+            fR0 = REAL(1.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+          }
+          else  // region 3p
+          {
+            // min on face s=0 or r=1
+            Vector3Copy( triOrigin, kTriSegOrigin );
+            Vector3Copy( triEdge1, kTriSegDirection );
+            fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                            kTriSegOrigin, kTriSegDirection,
+                                            &fR, &fT );
+            fS = REAL(0.0);
+            Vector3Add( segOrigin, segDirection, kPt );
+            fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
+                                             &fS0, &fT0 );
+            fR0 = REAL(1.0);
+            if ( fSqrDist0 < fSqrDist )
+            {
+              fSqrDist = fSqrDist0;
+              fR = fR0;
+              fS = fS0;
+              fT = fT0;
+            }
+          }
+        }
+        else if ( fT < REAL(0.0) )  // region 5p
+        {
+          // min on face t=0 or r=1
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fS );
+          fT = REAL(0.0);
+          Vector3Add( segOrigin, segDirection, kPt );
+          fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(1.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else  // region 0p
+        {
+          // min face on r=1
+          Vector3Add( segOrigin, segDirection, kPt );
+          fSqrDist = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
+                                          &fS, &fT );
+          fR = REAL(1.0);
+        }
+      }
+      else
+      {
+        if ( fS < REAL(0.0) )  // region 2p
+        {
+          // min on face s=0 or s+t=1 or r=1
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge1, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fT );
+          fS = REAL(0.0);
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                           kTriSegOrigin, kTriSegDirection,
+                                           &fR0, &fT0 );
+          fS0 = REAL(1.0) - fT0;
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+          Vector3Add( segOrigin, segDirection, kPt );
+          fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(1.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else if ( fT < REAL(0.0) )  // region 6p
+        {
+          // min on face t=0 or s+t=1 or r=1
+          Vector3Copy( triOrigin, kTriSegOrigin );
+          Vector3Copy( triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fS );
+          fT = REAL(0.0);
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                           kTriSegOrigin, kTriSegDirection,
+                                           &fR0, &fT0 );
+          fS0 = REAL(1.0) - fT0;
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+          Vector3Add( segOrigin, segDirection, kPt );
+          fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1,
+                                           &fS0, &fT0 );
+          fR0 = REAL(1.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+        else  // region 1p
+        {
+          // min on face s+t=1 or r=1
+          Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+          Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+          fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                          kTriSegOrigin, kTriSegDirection,
+                                          &fR, &fT );
+          fS = REAL(1.0) - fT;
+          Vector3Add( segOrigin, segDirection, kPt );
+          fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1, 
+                                           &fS0, &fT0 );
+          fR0 = REAL(1.0);
+          if ( fSqrDist0 < fSqrDist )
+          {
+            fSqrDist = fSqrDist0;
+            fR = fR0;
+            fS = fS0;
+            fT = fT0;
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    // segment and triangle are parallel
+    Vector3Copy( triOrigin, kTriSegOrigin );
+    Vector3Copy( triEdge0, kTriSegDirection );
+    fSqrDist = SqrDistanceSegments( segOrigin, segDirection,
+                                    kTriSegOrigin, kTriSegDirection, &fR, &fS );
+    fT = REAL(0.0);
+
+    Vector3Copy( triEdge1, kTriSegDirection );
+    fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                     kTriSegOrigin, kTriSegDirection,
+                                     &fR0, &fT0 );
+    fS0 = REAL(0.0);
+    if ( fSqrDist0 < fSqrDist )
+    {
+      fSqrDist = fSqrDist0;
+      fR = fR0;
+      fS = fS0;
+      fT = fT0;
+    }
+
+    Vector3Add( triOrigin, triEdge0, kTriSegOrigin );
+    Vector3Subtract( triEdge1, triEdge0, kTriSegDirection );
+    fSqrDist0 = SqrDistanceSegments( segOrigin, segDirection,
+                                     kTriSegOrigin, kTriSegDirection, &fR0, &fT0 );
+    fS0 = REAL(1.0) - fT0;
+    if ( fSqrDist0 < fSqrDist )
+    {
+      fSqrDist = fSqrDist0;
+      fR = fR0;
+      fS = fS0;
+      fT = fT0;
+    }
+
+    fSqrDist0 = SqrDistancePointTri( segOrigin, triOrigin, triEdge0, triEdge1, 
+                                     &fS0, &fT0 );
+    fR0 = REAL(0.0);
+    if ( fSqrDist0 < fSqrDist )
+    {
+      fSqrDist = fSqrDist0;
+      fR = fR0;
+      fS = fS0;
+      fT = fT0;
+    }
+
+    Vector3Add( segOrigin, segDirection, kPt );
+    fSqrDist0 = SqrDistancePointTri( kPt, triOrigin, triEdge0, triEdge1, 
+                                     &fS0, &fT0 );
+    fR0 = REAL(1.0);
+    if ( fSqrDist0 < fSqrDist )
+    {
+      fSqrDist = fSqrDist0;
+      fR = fR0;
+      fS = fS0;
+      fT = fT0;
+    }
+  }
+
+  if ( pfSegP )
+    *pfSegP = fR;
+
+  if ( pfTriP0 )
+    *pfTriP0 = fS;
+
+  if ( pfTriP1 )
+    *pfTriP1 = fT;
+
+  return fSqrDist;
+}
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_gimpact.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_gimpact.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_gimpact.cpp	(revision 216)
@@ -0,0 +1,456 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+
+#if dTRIMESH_ENABLED
+
+#include "collision_util.h"
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_GIMPACT
+
+void dxTriMeshData::Preprocess(){	// stub
+}
+
+dTriMeshDataID dGeomTriMeshDataCreate(){
+    return new dxTriMeshData();
+}
+
+void dGeomTriMeshDataDestroy(dTriMeshDataID g){
+    delete g;
+}
+
+void dGeomTriMeshSetLastTransform( dxGeom* g, dMatrix4 last_trans ) { //stub
+}
+
+dReal* dGeomTriMeshGetLastTransform( dxGeom* g ) {
+	return NULL; // stub
+}
+
+void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void* in_data) { //stub
+}
+
+void*  dGeomTriMeshDataGet(dTriMeshDataID g, int data_id) {
+    dUASSERT(g, "argument not trimesh data");
+	return NULL; // stub
+}
+
+void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g,
+                                  const void* Vertices, int VertexStride, int VertexCount,
+                                  const void* Indices, int IndexCount, int TriStride,
+                                  const void* Normals)
+{
+    dUASSERT(g, "argument not trimesh data");
+    dIASSERT(Vertices);
+    dIASSERT(Indices);
+
+    g->Build(Vertices, VertexStride, VertexCount,
+             Indices, IndexCount, TriStride,
+             Normals,
+             true);
+}
+
+
+void dGeomTriMeshDataBuildSingle(dTriMeshDataID g,
+                                 const void* Vertices, int VertexStride, int VertexCount,
+                                 const void* Indices, int IndexCount, int TriStride)
+{
+    dGeomTriMeshDataBuildSingle1(g, Vertices, VertexStride, VertexCount,
+                                 Indices, IndexCount, TriStride, (void*)NULL);
+}
+
+
+void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g,
+                                  const void* Vertices, int VertexStride, int VertexCount,
+                                 const void* Indices, int IndexCount, int TriStride,
+				 const void* Normals)
+{
+    dUASSERT(g, "argument not trimesh data");
+
+    g->Build(Vertices, VertexStride, VertexCount,
+             Indices, IndexCount, TriStride,
+             Normals,
+             false);
+}
+
+
+void dGeomTriMeshDataBuildDouble(dTriMeshDataID g,
+				 const void* Vertices, int VertexStride, int VertexCount,
+                                 const void* Indices, int IndexCount, int TriStride) {
+    dGeomTriMeshDataBuildDouble1(g, Vertices, VertexStride, VertexCount,
+                                 Indices, IndexCount, TriStride, NULL);
+}
+
+
+void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g,
+                                  const dReal* Vertices, int VertexCount,
+                                 const int* Indices, int IndexCount,
+                                 const int* Normals){
+#ifdef dSINGLE
+    dGeomTriMeshDataBuildSingle1(g,
+				Vertices, 4 * sizeof(dReal), VertexCount,
+				Indices, IndexCount, 3 * sizeof(unsigned int),
+				Normals);
+#else
+    dGeomTriMeshDataBuildDouble1(g, Vertices, 4 * sizeof(dReal), VertexCount,
+				Indices, IndexCount, 3 * sizeof(unsigned int),
+				Normals);
+#endif
+}
+
+
+void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
+                                 const dReal* Vertices, int VertexCount,
+                                 const int* Indices, int IndexCount) {
+    dGeomTriMeshDataBuildSimple1(g,
+                                 Vertices, VertexCount, Indices, IndexCount,
+                                 (const int*)NULL);
+}
+
+void dGeomTriMeshDataPreprocess(dTriMeshDataID g)
+{
+    dUASSERT(g, "argument not trimesh data");
+	g->Preprocess();
+}
+
+void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char** buf, int* bufLen)
+{
+    dUASSERT(g, "argument not trimesh data");
+	*buf = NULL;
+	*bufLen = 0;
+}
+
+void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf)
+{
+    dUASSERT(g, "argument not trimesh data");
+//	g->UseFlags = buf;
+}
+
+
+// Trimesh
+
+dxTriMesh::dxTriMesh(dSpaceID Space, dTriMeshDataID Data) : dxGeom(Space, 1){
+    type = dTriMeshClass;
+
+    dGeomTriMeshSetData(this,Data);
+
+	/* TC has speed/space 'issues' that don't make it a clear
+	   win by default on spheres/boxes. */
+	this->doSphereTC = true;
+	this->doBoxTC = true;
+	this->doCapsuleTC = true;
+
+}
+
+dxTriMesh::~dxTriMesh(){
+
+    //Terminate Trimesh
+    gim_trimesh_destroy(&m_collision_trimesh);
+}
+
+
+void dxTriMesh::ClearTCCache(){
+
+}
+
+
+int dxTriMesh::AABBTest(dxGeom* g, dReal aabb[6]){
+    return 1;
+}
+
+
+void dxTriMesh::computeAABB()
+{
+    //update trimesh transform
+    mat4f transform;
+    IDENTIFY_MATRIX_4X4(transform);
+    MakeMatrix(this, transform);
+    gim_trimesh_set_tranform(&m_collision_trimesh,transform);
+
+    //Update trimesh boxes
+    gim_trimesh_update(&m_collision_trimesh);
+
+    memcpy(aabb,&m_collision_trimesh.m_aabbset.m_global_bound,6*sizeof(GREAL));
+}
+
+
+void dxTriMeshData::UpdateData()
+{
+//  BVTree.Refit();
+}
+
+
+dGeomID dCreateTriMesh(dSpaceID space,
+		       dTriMeshDataID Data,
+		       dTriCallback* Callback,
+		       dTriArrayCallback* ArrayCallback,
+		       dTriRayCallback* RayCallback)
+{
+    dxTriMesh* Geom = new dxTriMesh(space, Data);
+    Geom->Callback = Callback;
+    Geom->ArrayCallback = ArrayCallback;
+    Geom->RayCallback = RayCallback;
+
+    return Geom;
+}
+
+void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->Callback = Callback;
+}
+
+dTriCallback* dGeomTriMeshGetCallback(dGeomID g)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	return ((dxTriMesh*)g)->Callback;
+}
+
+void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->ArrayCallback = ArrayCallback;
+}
+
+dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	return ((dxTriMesh*)g)->ArrayCallback;
+}
+
+void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->RayCallback = Callback;
+}
+
+dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	return ((dxTriMesh*)g)->RayCallback;
+}
+
+void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	dxTriMesh* mesh = (dxTriMesh*) g;
+	mesh->Data = Data;
+        // I changed my data -- I know nothing about my own AABB anymore.
+        ((dxTriMesh*)g)->gflags |= (GEOM_DIRTY|GEOM_AABB_BAD);
+
+	// GIMPACT only supports stride 12, so we need to catch the error early.
+	dUASSERT
+	(
+	  Data->m_VertexStride == 3*sizeof(dReal) && Data->m_TriStride == 3*sizeof(int),
+          "Gimpact trimesh only supports a stride of 3 dReal/int\n"
+	  "This means that you cannot use dGeomTriMeshDataBuildSimple() with Gimpact.\n"
+	  "Change the stride, or use Opcode trimeshes instead.\n"
+	);
+
+	//Create trimesh
+	if ( Data->m_Vertices )
+	  gim_trimesh_create_from_data
+	  (
+	    &mesh->m_collision_trimesh,		// gimpact mesh
+	    ( vec3f *)(&Data->m_Vertices[0]),	// vertices
+	    Data->m_VertexCount,		// nr of verts
+	    0,					// copy verts?
+	    ( GUINT *)(&Data->m_Indices[0]),	// indices
+	    Data->m_TriangleCount*3,		// nr of indices
+	    0,					// copy indices?
+	    1					// transformed reply
+	  );
+}
+
+dTriMeshDataID dGeomTriMeshGetData(dGeomID g)
+{
+  dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+  return ((dxTriMesh*)g)->Data;
+}
+
+
+
+void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+	switch (geomClass)
+	{
+		case dSphereClass:
+			((dxTriMesh*)g)->doSphereTC = (1 == enable);
+			break;
+		case dBoxClass:
+			((dxTriMesh*)g)->doBoxTC = (1 == enable);
+			break;
+		case dCapsuleClass:
+//		case dCCylinderClass:
+			((dxTriMesh*)g)->doCapsuleTC = (1 == enable);
+			break;
+	}
+}
+
+int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+	switch (geomClass)
+	{
+		case dSphereClass:
+			if (((dxTriMesh*)g)->doSphereTC)
+				return 1;
+			break;
+		case dBoxClass:
+			if (((dxTriMesh*)g)->doBoxTC)
+				return 1;
+			break;
+		case dCapsuleClass:
+			if (((dxTriMesh*)g)->doCapsuleTC)
+				return 1;
+			break;
+	}
+	return 0;
+}
+
+void dGeomTriMeshClearTCCache(dGeomID g){
+    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+    dxTriMesh* Geom = (dxTriMesh*)g;
+    Geom->ClearTCCache();
+}
+
+/*
+ * returns the TriMeshDataID
+ */
+dTriMeshDataID
+dGeomTriMeshGetTriMeshDataID(dGeomID g)
+{
+    dxTriMesh* Geom = (dxTriMesh*) g;
+    return Geom->Data;
+}
+
+// Getting data
+void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2)
+{
+    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+    dxTriMesh* Geom = (dxTriMesh*)g;
+	gim_trimesh_locks_work_data(&Geom->m_collision_trimesh);	
+	gim_trimesh_get_triangle_vertices(&Geom->m_collision_trimesh, Index, (*v0),(*v1),(*v2));	
+	gim_trimesh_unlocks_work_data(&Geom->m_collision_trimesh);
+ 
+}
+
+void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
+    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+    dxTriMesh* Geom = (dxTriMesh*)g;
+    dVector3 dv[3];
+	gim_trimesh_locks_work_data(&Geom->m_collision_trimesh);	
+	gim_trimesh_get_triangle_vertices(&Geom->m_collision_trimesh, Index, dv[0],dv[1],dv[2]);
+    GetPointFromBarycentric(dv, u, v, Out);
+	gim_trimesh_unlocks_work_data(&Geom->m_collision_trimesh);
+}
+
+int dGeomTriMeshGetTriangleCount (dGeomID g)
+{
+    dxTriMesh* Geom = (dxTriMesh*)g;	
+	return gim_trimesh_get_triangle_count(&Geom->m_collision_trimesh);
+}
+
+void dGeomTriMeshDataUpdate(dTriMeshDataID g) {
+    dUASSERT(g, "argument not trimesh data");
+    g->UpdateData();
+}
+
+
+//
+// GIMPACT TRIMESH-TRIMESH COLLIDER
+//
+
+int dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride)
+{
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (g2->type == dTriMeshClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+
+    dxTriMesh* TriMesh1 = (dxTriMesh*) g1;
+    dxTriMesh* TriMesh2 = (dxTriMesh*) g2;
+    //Create contact list
+    GDYNAMIC_ARRAY trimeshcontacts;
+    GIM_CREATE_CONTACT_LIST(trimeshcontacts);
+
+    //Collide trimeshes
+    gim_trimesh_trimesh_collision(&TriMesh1->m_collision_trimesh,&TriMesh2->m_collision_trimesh,&trimeshcontacts);
+
+    if(trimeshcontacts.m_size == 0)
+    {
+        GIM_DYNARRAY_DESTROY(trimeshcontacts);
+        return 0;
+    }
+
+    GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
+
+
+	unsigned contactcount = trimeshcontacts.m_size;
+	unsigned maxcontacts = (unsigned)(Flags & NUMC_MASK);
+	if (contactcount > maxcontacts)
+	{
+		contactcount = maxcontacts;
+	}
+
+    dContactGeom* pcontact;
+	unsigned i;
+
+	for (i=0;i<contactcount;i++)
+	{
+        pcontact = SAFECONTACT(Flags, Contacts, i, Stride);
+
+        pcontact->pos[0] = ptrimeshcontacts->m_point[0];
+        pcontact->pos[1] = ptrimeshcontacts->m_point[1];
+        pcontact->pos[2] = ptrimeshcontacts->m_point[2];
+        pcontact->pos[3] = 1.0f;
+
+        pcontact->normal[0] = ptrimeshcontacts->m_normal[0];
+        pcontact->normal[1] = ptrimeshcontacts->m_normal[1];
+        pcontact->normal[2] = ptrimeshcontacts->m_normal[2];
+        pcontact->normal[3] = 0;
+
+        pcontact->depth = ptrimeshcontacts->m_depth;
+        pcontact->g1 = g1;
+        pcontact->g2 = g2;
+
+        ptrimeshcontacts++;
+	}
+
+	GIM_DYNARRAY_DESTROY(trimeshcontacts);
+
+    return (int)contactcount;
+}
+
+#endif // dTRIMESH_GIMPACT
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_internal.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_internal.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_internal.h	(revision 216)
@@ -0,0 +1,495 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// TriMesh code by Erwin de Vries.
+// Modified for FreeSOLID Compatibility by Rodrigo Hernandez
+
+#ifndef _ODE_COLLISION_TRIMESH_INTERNAL_H_
+#define _ODE_COLLISION_TRIMESH_INTERNAL_H_
+
+int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideTrimeshPlane(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+
+int dCollideSTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideBTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideRTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideTTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip);
+
+PURE_INLINE int dCollideRayTrimesh( dxGeom *ray, dxGeom *trimesh, int flags,
+									dContactGeom *contact, int skip )
+{
+	// Swapped case, for code that needs it (heightfield initially)
+	// The other ray-geom colliders take geoms in a swapped order to the
+	// dCollideRTL function which is annoying when using function pointers.
+	return dCollideRTL( trimesh, ray, flags, contact, skip );
+}
+
+//****************************************************************************
+// dxTriMesh class
+
+#ifdef TRIMESH_INTERNAL
+
+#include "collision_kernel.h"
+#include <ode/collision_trimesh.h>
+
+#if dTRIMESH_OPCODE
+#define BAN_OPCODE_AUTOLINK
+#include "Opcode.h"
+using namespace Opcode;
+#endif // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+#include <GIMPACT/gimpact.h>
+#endif
+
+struct dxTriMeshData  : public dBase 
+{
+    /* Array of flags for which edges and verts should be used on each triangle */
+    enum UseFlags
+    {
+        kEdge0 = 0x1,
+        kEdge1 = 0x2,
+        kEdge2 = 0x4,
+        kVert0 = 0x8,
+        kVert1 = 0x10,
+        kVert2 = 0x20,
+
+        kUseAll = 0xFF,
+    };
+
+    /* Setup the UseFlags array */
+    void Preprocess();
+    /* For when app changes the vertices */
+    void UpdateData();
+
+#if dTRIMESH_OPCODE
+	Model BVTree;
+	MeshInterface Mesh;
+
+    dxTriMeshData();
+    ~dxTriMeshData();
+    
+    void Build(const void* Vertices, int VertexStide, int VertexCount, 
+	       const void* Indices, int IndexCount, int TriStride, 
+	       const void* Normals, 
+	       bool Single);
+    
+        /* aabb in model space */
+        dVector3 AABBCenter;
+        dVector3 AABBExtents;
+
+    // data for use in collision resolution
+    const void* Normals;
+    uint8* UseFlags;
+#endif  // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+	const char* m_Vertices;
+	int m_VertexStride;
+	int m_VertexCount;
+	const char* m_Indices;
+	int m_TriangleCount;
+	int m_TriStride;
+	bool m_single;
+
+   dxTriMeshData()
+	{
+		m_Vertices=NULL;
+		m_VertexStride = 12;
+		m_VertexCount = 0;
+		m_Indices = 0;
+		m_TriangleCount = 0;
+		m_TriStride = 12;
+		m_single = true;
+	}
+
+    void Build(const void* Vertices, int VertexStride, int VertexCount,
+	       const void* Indices, int IndexCount, int TriStride,
+	       const void* Normals,
+	      bool Single)
+	{
+		dIASSERT(Vertices);
+		dIASSERT(Indices);
+ 		dIASSERT(VertexStride);
+ 		dIASSERT(TriStride);
+ 		dIASSERT(IndexCount);
+		m_Vertices=(const char *)Vertices;
+		m_VertexStride = VertexStride;
+		m_VertexCount = VertexCount;
+		m_Indices = (const char *)Indices;
+		m_TriangleCount = IndexCount/3;
+		m_TriStride = TriStride;
+		m_single = Single;
+	}
+
+	inline void GetVertex(unsigned int i, dVector3 Out)
+	{
+		if(m_single)
+		{
+			const float * fverts = (const float * )(m_Vertices + m_VertexStride*i);
+			Out[0] = fverts[0];
+			Out[1] = fverts[1];
+			Out[2] = fverts[2];
+			Out[3] = 1.0f;
+		}
+		else
+		{
+			const double * dverts = (const double * )(m_Vertices + m_VertexStride*i);
+			Out[0] = (float)dverts[0];
+			Out[1] = (float)dverts[1];
+			Out[2] = (float)dverts[2];
+			Out[3] = 1.0f;
+
+		}
+	}
+
+	inline void GetTriIndices(unsigned int itriangle, unsigned int triindices[3])
+	{
+		const unsigned int * ind = (const unsigned int * )(m_Indices + m_TriStride*itriangle);
+		triindices[0] = ind[0];
+		triindices[1] = ind[1];
+		triindices[2] = ind[2];
+	}
+#endif  // dTRIMESH_GIMPACT
+};
+
+
+struct dxTriMesh : public dxGeom{
+	// Callbacks
+	dTriCallback* Callback;
+	dTriArrayCallback* ArrayCallback;
+	dTriRayCallback* RayCallback;
+
+	// Data types
+	dxTriMeshData* Data;
+
+	bool doSphereTC;
+	bool doBoxTC;
+	bool doCapsuleTC;
+
+	// Functions
+	dxTriMesh(dSpaceID Space, dTriMeshDataID Data);
+	~dxTriMesh();
+
+	void ClearTCCache();
+
+	int AABBTest(dxGeom* g, dReal aabb[6]);
+	void computeAABB();
+
+#if dTRIMESH_OPCODE
+	// Instance data for last transform.
+    dMatrix4 last_trans;
+
+	// Colliders
+	static PlanesCollider _PlanesCollider;
+	static SphereCollider _SphereCollider;
+	static OBBCollider _OBBCollider;
+	static RayCollider _RayCollider;
+	static AABBTreeCollider _AABBTreeCollider;
+	static LSSCollider _LSSCollider;
+
+	// Some constants
+	static CollisionFaces Faces;
+	// Temporal coherence
+	struct SphereTC : public SphereCache{
+		dxGeom* Geom;
+	};
+	dArray<SphereTC> SphereTCCache;
+	static SphereCache defaultSphereCache;
+
+	struct BoxTC : public OBBCache{
+		dxGeom* Geom;
+	};
+	dArray<BoxTC> BoxTCCache;
+	static OBBCache defaultBoxCache;
+	
+	struct CapsuleTC : public LSSCache{
+		dxGeom* Geom;
+	};
+	dArray<CapsuleTC> CapsuleTCCache;
+	static LSSCache defaultCapsuleCache;
+#endif // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+    GIM_TRIMESH  m_collision_trimesh;
+#endif  // dTRIMESH_GIMPACT
+};
+
+#if 0
+#include "collision_kernel.h"
+// Fetches a contact
+inline dContactGeom* SAFECONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){
+	dIASSERT(Index >= 0 && Index < (Flags & NUMC_MASK));
+	return ((dContactGeom*)(((char*)Contacts) + (Index * Stride)));
+}
+#endif
+
+#if dTRIMESH_OPCODE
+inline void FetchTriangle(dxTriMesh* TriMesh, int Index, dVector3 Out[3]){
+	VertexPointers VP;
+	TriMesh->Data->Mesh.GetTriangle(VP, Index);
+	for (int i = 0; i < 3; i++){
+		Out[i][0] = VP.Vertex[i]->x;
+		Out[i][1] = VP.Vertex[i]->y;
+		Out[i][2] = VP.Vertex[i]->z;
+		Out[i][3] = 0;
+	}
+}
+
+inline void FetchTriangle(dxTriMesh* TriMesh, int Index, const dVector3 Position, const dMatrix3 Rotation, dVector3 Out[3]){
+	VertexPointers VP;
+	TriMesh->Data->Mesh.GetTriangle(VP, Index);
+	for (int i = 0; i < 3; i++){
+		dVector3 v;
+		v[0] = VP.Vertex[i]->x;
+		v[1] = VP.Vertex[i]->y;
+		v[2] = VP.Vertex[i]->z;
+		v[3] = 0;
+
+		dMULTIPLY0_331(Out[i], Rotation, v);
+		Out[i][0] += Position[0];
+		Out[i][1] += Position[1];
+		Out[i][2] += Position[2];
+		Out[i][3] = 0;
+	}
+}
+
+inline Matrix4x4& MakeMatrix(const dVector3 Position, const dMatrix3 Rotation, Matrix4x4& Out){
+	Out.m[0][0] = (float) Rotation[0];
+	Out.m[1][0] = (float) Rotation[1];
+	Out.m[2][0] = (float) Rotation[2];
+
+	Out.m[0][1] = (float) Rotation[4];
+	Out.m[1][1] = (float) Rotation[5];
+	Out.m[2][1] = (float) Rotation[6];
+
+	Out.m[0][2] = (float) Rotation[8];
+	Out.m[1][2] = (float) Rotation[9];
+	Out.m[2][2] = (float) Rotation[10];
+
+	Out.m[3][0] = (float) Position[0];
+	Out.m[3][1] = (float) Position[1];
+	Out.m[3][2] = (float) Position[2];
+
+	Out.m[0][3] = 0.0f;
+	Out.m[1][3] = 0.0f;
+	Out.m[2][3] = 0.0f;
+	Out.m[3][3] = 1.0f;
+
+	return Out;
+}
+
+inline Matrix4x4& MakeMatrix(dxGeom* g, Matrix4x4& Out){
+	const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
+	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
+	return MakeMatrix(Position, Rotation, Out);
+}
+#endif // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+inline void FetchTriangle(dxTriMesh* TriMesh, int Index, const dVector3 Position, const dMatrix3 Rotation, dVector3 Out[3]){
+	// why is this not implemented?
+	dAASSERT(false);
+}
+
+inline void MakeMatrix(const dVector3 Position, const dMatrix3 Rotation, mat4f m)
+{
+	m[0][0] = (float) Rotation[0];
+	m[0][1] = (float) Rotation[1];
+	m[0][2] = (float) Rotation[2];
+
+	m[1][0] = (float) Rotation[4];
+	m[1][1] = (float) Rotation[5];
+	m[1][2] = (float) Rotation[6];
+
+	m[2][0] = (float) Rotation[8];
+	m[2][1] = (float) Rotation[9];
+	m[2][2] = (float) Rotation[10];
+
+	m[0][3] = (float) Position[0];
+	m[1][3] = (float) Position[1];
+	m[2][3] = (float) Position[2];
+
+}
+
+inline void MakeMatrix(dxGeom* g, mat4f Out){
+	const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
+	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
+	MakeMatrix(Position, Rotation, Out);
+}
+#endif // dTRIMESH_GIMPACT
+
+// Outputs a matrix to 3 vectors
+inline void Decompose(const dMatrix3 Matrix, dVector3 Right, dVector3 Up, dVector3 Direction){
+	Right[0] = Matrix[0 * 4 + 0];
+	Right[1] = Matrix[1 * 4 + 0];
+	Right[2] = Matrix[2 * 4 + 0];
+	Right[3] = REAL(0.0);
+	Up[0] = Matrix[0 * 4 + 1];
+	Up[1] = Matrix[1 * 4 + 1];
+	Up[2] = Matrix[2 * 4 + 1];
+	Up[3] = REAL(0.0);
+	Direction[0] = Matrix[0 * 4 + 2];
+	Direction[1] = Matrix[1 * 4 + 2];
+	Direction[2] = Matrix[2 * 4 + 2];
+	Direction[3] = REAL(0.0);
+}
+
+// Outputs a matrix to 3 vectors
+inline void Decompose(const dMatrix3 Matrix, dVector3 Vectors[3]){
+	Decompose(Matrix, Vectors[0], Vectors[1], Vectors[2]);
+}
+
+// Finds barycentric
+inline void GetPointFromBarycentric(const dVector3 dv[3], dReal u, dReal v, dVector3 Out){
+	dReal w = REAL(1.0) - u - v;
+
+	Out[0] = (dv[0][0] * w) + (dv[1][0] * u) + (dv[2][0] * v);
+	Out[1] = (dv[0][1] * w) + (dv[1][1] * u) + (dv[2][1] * v);
+	Out[2] = (dv[0][2] * w) + (dv[1][2] * u) + (dv[2][2] * v);
+	Out[3] = (dv[0][3] * w) + (dv[1][3] * u) + (dv[2][3] * v);
+}
+
+// Performs a callback
+inline bool Callback(dxTriMesh* TriMesh, dxGeom* Object, int TriIndex){
+	if (TriMesh->Callback != NULL){
+		return (TriMesh->Callback(TriMesh, Object, TriIndex)!=0);
+	}
+	else return true;
+}
+
+// Some utilities
+template<class T> const T& dcMAX(const T& x, const T& y){
+	return x > y ? x : y;
+}
+
+template<class T> const T& dcMIN(const T& x, const T& y){
+	return x < y ? x : y;
+}
+
+dReal SqrDistancePointTri( const dVector3 p, const dVector3 triOrigin, 
+                           const dVector3 triEdge1, const dVector3 triEdge2,
+                           dReal* pfSParam = 0, dReal* pfTParam = 0 );
+
+dReal SqrDistanceSegments( const dVector3 seg1Origin, const dVector3 seg1Direction, 
+                           const dVector3 seg2Origin, const dVector3 seg2Direction,
+                           dReal* pfSegP0 = 0, dReal* pfSegP1 = 0 );
+
+dReal SqrDistanceSegTri( const dVector3 segOrigin, const dVector3 segEnd, 
+                         const dVector3 triOrigin, 
+                         const dVector3 triEdge1, const dVector3 triEdge2,
+                         dReal* t = 0, dReal* u = 0, dReal* v = 0 );
+
+inline
+void Vector3Subtract( const dVector3 left, const dVector3 right, dVector3 result )
+{
+    result[0] = left[0] - right[0];
+    result[1] = left[1] - right[1];
+    result[2] = left[2] - right[2];
+    result[3] = REAL(0.0);
+}
+
+inline
+void Vector3Add( const dVector3 left, const dVector3 right, dVector3 result )
+{
+    result[0] = left[0] + right[0];
+    result[1] = left[1] + right[1];
+    result[2] = left[2] + right[2];
+    result[3] = REAL(0.0);
+}
+
+inline
+void Vector3Negate( const dVector3 in, dVector3 out )
+{
+    out[0] = -in[0];
+    out[1] = -in[1];
+    out[2] = -in[2];
+    out[3] = REAL(0.0);
+}
+
+inline
+void Vector3Copy( const dVector3 in, dVector3 out )
+{
+    out[0] = in[0];
+    out[1] = in[1];
+    out[2] = in[2];
+    out[3] = REAL(0.0);
+}
+
+inline
+void Vector3Multiply( const dVector3 in, dReal scalar, dVector3 out )
+{
+    out[0] = in[0] * scalar;
+    out[1] = in[1] * scalar;
+    out[2] = in[2] * scalar;
+    out[3] = REAL(0.0);
+}
+
+inline
+void TransformVector3( const dVector3 in, 
+                       const dMatrix3 orientation, const dVector3 position, 
+                       dVector3 out )
+{
+    dMULTIPLY0_331( out, orientation, in );
+    out[0] += position[0];
+    out[1] += position[1];
+    out[2] += position[2];
+}
+
+//------------------------------------------------------------------------------
+/**
+  @brief Check for intersection between triangle and capsule.
+  
+  @param dist [out] Shortest distance squared between the triangle and 
+                    the capsule segment (central axis).
+  @param t    [out] t value of point on segment that's the shortest distance 
+                    away from the triangle, the coordinates of this point 
+                    can be found by (cap.seg.end - cap.seg.start) * t,
+                    or cap.seg.ipol(t).
+  @param u    [out] Barycentric coord on triangle.
+  @param v    [out] Barycentric coord on triangle.
+  @return True if intersection exists.
+  
+  The third Barycentric coord is implicit, ie. w = 1.0 - u - v
+  The Barycentric coords give the location of the point on the triangle
+  closest to the capsule (where the distance between the two shapes
+  is the shortest).
+*/
+inline
+bool IntersectCapsuleTri( const dVector3 segOrigin, const dVector3 segEnd, 
+                          const dReal radius, const dVector3 triOrigin, 
+                          const dVector3 triEdge0, const dVector3 triEdge1,
+                          dReal* dist, dReal* t, dReal* u, dReal* v )
+{
+    dReal sqrDist = SqrDistanceSegTri( segOrigin, segEnd, triOrigin, triEdge0, triEdge1, 
+                                       t, u, v );
+  
+    if ( dist )
+      *dist = sqrDist;
+    
+    return ( sqrDist <= (radius * radius) );
+}
+
+#endif	//TRIMESH_INTERNAL
+
+#endif	//_ODE_COLLISION_TRIMESH_INTERNAL_H_
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_opcode.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_opcode.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_opcode.cpp	(revision 216)
@@ -0,0 +1,833 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// TriMesh code by Erwin de Vries.
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_ENABLED
+#if dTRIMESH_OPCODE
+
+// Trimesh data
+dxTriMeshData::dxTriMeshData() : UseFlags( NULL )
+{
+#if !dTRIMESH_ENABLED
+  dUASSERT(false, "dTRIMESH_ENABLED is not defined. Trimesh geoms will not work");
+#endif
+}
+
+dxTriMeshData::~dxTriMeshData()
+{
+	if ( UseFlags )
+		delete [] UseFlags;
+}
+
+void 
+dxTriMeshData::Build(const void* Vertices, int VertexStide, int VertexCount,
+		     const void* Indices, int IndexCount, int TriStride,
+		     const void* in_Normals,
+		     bool Single)
+{
+#if dTRIMESH_ENABLED
+
+    Mesh.SetNbTriangles(IndexCount / 3);
+    Mesh.SetNbVertices(VertexCount);
+    Mesh.SetPointers((IndexedTriangle*)Indices, (Point*)Vertices);
+    Mesh.SetStrides(TriStride, VertexStide);
+    Mesh.Single = Single;
+    
+    // Build tree
+    BuildSettings Settings;
+    // recommended in Opcode User Manual
+    //Settings.mRules = SPLIT_COMPLETE | SPLIT_SPLATTERPOINTS | SPLIT_GEOMCENTER;
+    // used in ODE, why?
+    //Settings.mRules = SPLIT_BEST_AXIS;
+
+    // best compromise?
+    Settings.mRules = SPLIT_BEST_AXIS | SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER;
+
+
+    OPCODECREATE TreeBuilder;
+    TreeBuilder.mIMesh = &Mesh;
+
+    TreeBuilder.mSettings = Settings;
+    TreeBuilder.mNoLeaf = true;
+    TreeBuilder.mQuantized = false;
+
+    TreeBuilder.mKeepOriginal = false;
+    TreeBuilder.mCanRemap = false;
+
+
+
+    BVTree.Build(TreeBuilder);
+
+    // compute model space AABB
+    dVector3 AABBMax, AABBMin;
+    AABBMax[0] = AABBMax[1] = AABBMax[2] = (dReal) -dInfinity;
+    AABBMin[0] = AABBMin[1] = AABBMin[2] = (dReal) dInfinity;
+    if( Single ) {
+        const char* verts = (const char*)Vertices;
+        for( int i = 0; i < VertexCount; ++i ) {
+        const float* v = (const float*)verts;
+        if( v[0] > AABBMax[0] ) AABBMax[0] = v[0];
+        if( v[1] > AABBMax[1] ) AABBMax[1] = v[1];
+        if( v[2] > AABBMax[2] ) AABBMax[2] = v[2];
+        if( v[0] < AABBMin[0] ) AABBMin[0] = v[0];
+        if( v[1] < AABBMin[1] ) AABBMin[1] = v[1];
+        if( v[2] < AABBMin[2] ) AABBMin[2] = v[2];
+        verts += VertexStide;
+        }
+    } else {
+        const char* verts = (const char*)Vertices;
+        for( int i = 0; i < VertexCount; ++i ) {
+        const double* v = (const double*)verts;
+        if( v[0] > AABBMax[0] ) AABBMax[0] = (dReal) v[0];
+        if( v[1] > AABBMax[1] ) AABBMax[1] = (dReal) v[1];
+        if( v[2] > AABBMax[2] ) AABBMax[2] = (dReal) v[2];
+        if( v[0] < AABBMin[0] ) AABBMin[0] = (dReal) v[0];
+        if( v[1] < AABBMin[1] ) AABBMin[1] = (dReal) v[1];
+        if( v[2] < AABBMin[2] ) AABBMin[2] = (dReal) v[2];
+        verts += VertexStide;
+        }
+    }
+    AABBCenter[0] = (AABBMin[0] + AABBMax[0]) * REAL(0.5);
+    AABBCenter[1] = (AABBMin[1] + AABBMax[1]) * REAL(0.5);
+    AABBCenter[2] = (AABBMin[2] + AABBMax[2]) * REAL(0.5);
+    AABBExtents[0] = AABBMax[0] - AABBCenter[0];
+    AABBExtents[1] = AABBMax[1] - AABBCenter[1];
+    AABBExtents[2] = AABBMax[2] - AABBCenter[2];
+
+    // user data (not used by OPCODE)
+    Normals = (dReal *) in_Normals;
+
+	UseFlags = 0;
+
+#endif // dTRIMESH_ENABLED
+}
+
+struct EdgeRecord
+{
+	int VertIdx1;	// Index into vertex array for this edges vertices
+	int VertIdx2;
+	int TriIdx;		// Index into triangle array for triangle this edge belongs to
+
+	uint8 EdgeFlags;	
+	uint8 Vert1Flags;
+	uint8 Vert2Flags;
+	bool Concave;
+};
+
+// Edge comparison function for qsort
+static int EdgeCompare(const void* edge1, const void* edge2)
+{
+	EdgeRecord* e1 = (EdgeRecord*)edge1;
+	EdgeRecord* e2 = (EdgeRecord*)edge2;
+
+	if (e1->VertIdx1 == e2->VertIdx1)
+		return e1->VertIdx2 - e2->VertIdx2;
+	else
+		return e1->VertIdx1 - e2->VertIdx1;
+}
+
+void SetupEdge(EdgeRecord* edge, int edgeIdx, int triIdx, const unsigned int* vertIdxs)
+{
+	if (edgeIdx == 0)
+	{
+		edge->EdgeFlags  = dxTriMeshData::kEdge0;
+		edge->Vert1Flags = dxTriMeshData::kVert0;
+		edge->Vert2Flags = dxTriMeshData::kVert1;
+		edge->VertIdx1 = vertIdxs[0];
+		edge->VertIdx2 = vertIdxs[1];
+	}
+	else if (edgeIdx == 1)
+	{
+		edge->EdgeFlags  = dxTriMeshData::kEdge1;
+		edge->Vert1Flags = dxTriMeshData::kVert1;
+		edge->Vert2Flags = dxTriMeshData::kVert2;
+		edge->VertIdx1 = vertIdxs[1];
+		edge->VertIdx2 = vertIdxs[2];
+	}
+	else if (edgeIdx == 2)
+	{
+		edge->EdgeFlags  = dxTriMeshData::kEdge2;
+		edge->Vert1Flags = dxTriMeshData::kVert2;
+		edge->Vert2Flags = dxTriMeshData::kVert0;
+		edge->VertIdx1 = vertIdxs[2];
+		edge->VertIdx2 = vertIdxs[0];
+	}
+
+	// Make sure vert index 1 is less than index 2 (for easier sorting)
+	if (edge->VertIdx1 > edge->VertIdx2)
+	{
+		unsigned int tempIdx = edge->VertIdx1;
+		edge->VertIdx1 = edge->VertIdx2;
+		edge->VertIdx2 = tempIdx;
+
+		uint8 tempFlags = edge->Vert1Flags;
+		edge->Vert1Flags = edge->Vert2Flags;
+		edge->Vert2Flags = tempFlags;
+	}
+
+	edge->TriIdx = triIdx;
+	edge->Concave = false;
+}
+
+#if dTRIMESH_ENABLED
+
+// Get the vertex opposite this edge in the triangle
+inline Point GetOppositeVert(EdgeRecord* edge, const Point* vertices[])
+{
+	if ((edge->Vert1Flags == dxTriMeshData::kVert0 && edge->Vert2Flags == dxTriMeshData::kVert1) ||
+		(edge->Vert1Flags == dxTriMeshData::kVert1 && edge->Vert2Flags == dxTriMeshData::kVert0))
+	{
+		return *vertices[2];
+	}
+	else if ((edge->Vert1Flags == dxTriMeshData::kVert1 && edge->Vert2Flags == dxTriMeshData::kVert2) ||
+		(edge->Vert1Flags == dxTriMeshData::kVert2 && edge->Vert2Flags == dxTriMeshData::kVert1))
+	{
+		return *vertices[0];
+	}
+	else
+		return *vertices[1];
+}
+
+#endif // dTRIMESH_ENABLED
+
+void dxTriMeshData::Preprocess()
+{
+
+#if dTRIMESH_ENABLED
+
+	// If this mesh has already been preprocessed, exit
+	if (UseFlags)
+		return;
+
+	udword numTris = Mesh.GetNbTriangles();
+	udword numEdges = numTris * 3;
+
+	UseFlags = new uint8[numTris];
+	memset(UseFlags, 0, sizeof(uint8) * numTris);
+
+	EdgeRecord* records = new EdgeRecord[numEdges];
+
+	// Make a list of every edge in the mesh
+	const IndexedTriangle* tris = Mesh.GetTris();
+    for (unsigned int i = 0; i < numTris; i++)
+	{
+		SetupEdge(&records[i*3],   0, i, tris->mVRef);
+		SetupEdge(&records[i*3+1], 1, i, tris->mVRef);
+		SetupEdge(&records[i*3+2], 2, i, tris->mVRef);
+
+		tris = (const IndexedTriangle*)(((uint8*)tris) + Mesh.GetTriStride());
+	}
+
+	// Sort the edges, so the ones sharing the same verts are beside each other
+	qsort(records, numEdges, sizeof(EdgeRecord), EdgeCompare);
+
+	// Go through the sorted list of edges and flag all the edges and vertices that we need to use
+	for (unsigned int i = 0; i < numEdges; i++)
+	{
+		EdgeRecord* rec1 = &records[i];
+		EdgeRecord* rec2 = 0;
+		if (i < numEdges - 1)
+			rec2 = &records[i+1];
+
+		if (rec2 &&
+			rec1->VertIdx1 == rec2->VertIdx1 &&
+			rec1->VertIdx2 == rec2->VertIdx2)
+		{
+			VertexPointers vp;
+			Mesh.GetTriangle(vp, rec1->TriIdx);
+
+			// Get the normal of the first triangle
+			Point triNorm = (*vp.Vertex[2] - *vp.Vertex[1]) ^ (*vp.Vertex[0] - *vp.Vertex[1]);
+			triNorm.Normalize();
+
+			// Get the vert opposite this edge in the first triangle
+			Point oppositeVert1 = GetOppositeVert(rec1, vp.Vertex);
+
+			// Get the vert opposite this edge in the second triangle
+			Mesh.GetTriangle(vp, rec2->TriIdx);
+			Point oppositeVert2 = GetOppositeVert(rec2, vp.Vertex);
+
+			float dot = triNorm.Dot((oppositeVert2 - oppositeVert1).Normalize());
+
+			// We let the dot threshold for concavity get slightly negative to allow for rounding errors
+			static const float kConcaveThresh = -0.000001f;
+
+			// This is a concave edge, leave it for the next pass
+			if (dot >= kConcaveThresh)
+				rec1->Concave = true;
+			// If this is a convex edge, mark its vertices and edge as used
+			else
+				UseFlags[rec1->TriIdx] |= rec1->Vert1Flags | rec1->Vert2Flags | rec1->EdgeFlags;
+
+			// Skip the second edge
+			i++;
+		}
+		// This is a boundary edge
+		else
+		{
+			UseFlags[rec1->TriIdx] |= rec1->Vert1Flags | rec1->Vert2Flags | rec1->EdgeFlags;
+		}
+	}
+
+	// Go through the list once more, and take any edge we marked as concave and
+	// clear it's vertices flags in any triangles they're used in
+	for (unsigned int i = 0; i < numEdges; i++)
+	{
+		EdgeRecord& er = records[i];
+
+		if (er.Concave)
+		{
+			for (unsigned int j = 0; j < numEdges; j++)
+			{
+				EdgeRecord& curER = records[j];
+
+				if (curER.VertIdx1 == er.VertIdx1 ||
+					curER.VertIdx1 == er.VertIdx2)
+					UseFlags[curER.TriIdx] &= ~curER.Vert1Flags;
+
+				if (curER.VertIdx2 == er.VertIdx1 ||
+					curER.VertIdx2 == er.VertIdx2)
+					UseFlags[curER.TriIdx] &= ~curER.Vert2Flags;
+			}
+		}
+	}
+
+	delete [] records;
+
+#endif // dTRIMESH_ENABLED
+
+}
+
+dTriMeshDataID dGeomTriMeshDataCreate(){
+    return new dxTriMeshData();
+}
+
+void dGeomTriMeshDataDestroy(dTriMeshDataID g){
+    delete g;
+}
+
+
+
+
+void dGeomTriMeshSetLastTransform( dxGeom* g, dMatrix4 last_trans )
+{
+	dAASSERT(g)
+    dUASSERT(g->type == dTriMeshClass, "geom not trimesh");
+
+    for (int i=0; i<16; i++)
+        (((dxTriMesh*)g)->last_trans)[ i ] = last_trans[ i ];
+
+    return;
+}
+
+
+dReal* dGeomTriMeshGetLastTransform( dxGeom* g )
+{
+	dAASSERT(g)
+    dUASSERT(g->type == dTriMeshClass, "geom not trimesh");
+
+    return (dReal*)(((dxTriMesh*)g)->last_trans);
+}
+
+
+
+
+void dGeomTriMeshDataSet(dTriMeshDataID g, int data_id, void* in_data)
+{
+    dUASSERT(g, "argument not trimesh data");
+
+    switch (data_id)
+	{
+    case TRIMESH_FACE_NORMALS:
+		g->Normals = (dReal *) in_data;
+		break;
+
+    default:
+		dUASSERT(data_id, "invalid data type");
+		break;
+    }
+
+    return;
+}
+
+
+
+void*  dGeomTriMeshDataGet(dTriMeshDataID g, int data_id)
+{
+    dUASSERT(g, "argument not trimesh data");
+
+    switch (data_id)
+	{
+    case TRIMESH_FACE_NORMALS:
+        return (void *) g->Normals;
+        break;
+
+	default:
+        dUASSERT(data_id, "invalid data type");
+        break;
+    }
+    
+    return NULL;
+}
+
+
+void dGeomTriMeshDataBuildSingle1(dTriMeshDataID g,
+                                  const void* Vertices, int VertexStride, int VertexCount, 
+                                  const void* Indices, int IndexCount, int TriStride,
+                                  const void* Normals)
+{
+    dUASSERT(g, "argument not trimesh data");
+    
+    g->Build(Vertices, VertexStride, VertexCount, 
+             Indices, IndexCount, TriStride, 
+             Normals, 
+             true);
+}
+
+
+void dGeomTriMeshDataBuildSingle(dTriMeshDataID g,
+                                 const void* Vertices, int VertexStride, int VertexCount, 
+                                 const void* Indices, int IndexCount, int TriStride)
+{
+    dGeomTriMeshDataBuildSingle1(g, Vertices, VertexStride, VertexCount,
+                                 Indices, IndexCount, TriStride, (void*)NULL);
+}
+
+
+void dGeomTriMeshDataBuildDouble1(dTriMeshDataID g,
+                                  const void* Vertices, int VertexStride, int VertexCount, 
+                                 const void* Indices, int IndexCount, int TriStride,
+				 const void* Normals)
+{
+    dUASSERT(g, "argument not trimesh data");
+    
+    g->Build(Vertices, VertexStride, VertexCount, 
+             Indices, IndexCount, TriStride, 
+             Normals, 
+             false);
+}
+
+
+void dGeomTriMeshDataBuildDouble(dTriMeshDataID g,
+				 const void* Vertices, int VertexStride, int VertexCount, 
+                                 const void* Indices, int IndexCount, int TriStride) {
+    dGeomTriMeshDataBuildDouble1(g, Vertices, VertexStride, VertexCount,
+                                 Indices, IndexCount, TriStride, NULL);
+}
+
+
+void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g,
+                                  const dReal* Vertices, int VertexCount, 
+                                 const int* Indices, int IndexCount,
+                                 const int* Normals){
+#ifdef dSINGLE
+    dGeomTriMeshDataBuildSingle1(g,
+				Vertices, 4 * sizeof(dReal), VertexCount, 
+				Indices, IndexCount, 3 * sizeof(unsigned int),
+				Normals);
+#else
+    dGeomTriMeshDataBuildDouble1(g, Vertices, 4 * sizeof(dReal), VertexCount, 
+				Indices, IndexCount, 3 * sizeof(unsigned int),
+				Normals);
+#endif
+}
+
+
+void dGeomTriMeshDataBuildSimple(dTriMeshDataID g,
+                                 const dReal* Vertices, int VertexCount, 
+                                 const int* Indices, int IndexCount) {
+    dGeomTriMeshDataBuildSimple1(g,
+                                 Vertices, VertexCount, Indices, IndexCount,
+                                 (const int*)NULL);
+}
+
+void dGeomTriMeshDataPreprocess(dTriMeshDataID g)
+{
+    dUASSERT(g, "argument not trimesh data");
+	g->Preprocess();
+}
+
+void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char** buf, int* bufLen)
+{
+    dUASSERT(g, "argument not trimesh data");
+#if dTRIMESH_ENABLED
+	*buf = g->UseFlags;
+	*bufLen = g->Mesh.GetNbTriangles();
+#endif // dTRIMESH_ENABLED
+}
+
+void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf)
+{
+    dUASSERT(g, "argument not trimesh data");
+	g->UseFlags = buf;
+}
+
+
+#if dTRIMESH_ENABLED
+
+// Trimesh Class Statics
+PlanesCollider dxTriMesh::_PlanesCollider;
+SphereCollider dxTriMesh::_SphereCollider;
+OBBCollider dxTriMesh::_OBBCollider;
+RayCollider dxTriMesh::_RayCollider;
+AABBTreeCollider dxTriMesh::_AABBTreeCollider;
+LSSCollider dxTriMesh::_LSSCollider;
+
+SphereCache dxTriMesh::defaultSphereCache;
+OBBCache dxTriMesh::defaultBoxCache;
+LSSCache dxTriMesh::defaultCapsuleCache;
+
+CollisionFaces dxTriMesh::Faces;
+
+#endif // dTRIMESH_ENABLED
+
+
+dxTriMesh::dxTriMesh(dSpaceID Space, dTriMeshDataID Data) : dxGeom(Space, 1)
+{
+    type = dTriMeshClass;
+
+    this->Data = Data;
+
+#if dTRIMESH_ENABLED
+
+	_RayCollider.SetDestination(&Faces);
+
+    _PlanesCollider.SetTemporalCoherence(true);
+
+	_SphereCollider.SetTemporalCoherence(true);
+        _SphereCollider.SetPrimitiveTests(false);
+
+    _OBBCollider.SetTemporalCoherence(true);
+
+    // no first-contact test (i.e. return full contact info)
+	_AABBTreeCollider.SetFirstContact( false );     
+    // temporal coherence only works with "first conact" tests
+    _AABBTreeCollider.SetTemporalCoherence(false);
+    // Perform full BV-BV tests (true) or SAT-lite tests (false)
+	_AABBTreeCollider.SetFullBoxBoxTest( true );
+    // Perform full Primitive-BV tests (true) or SAT-lite tests (false)
+	_AABBTreeCollider.SetFullPrimBoxTest( true );
+	_LSSCollider.SetTemporalCoherence(false);
+
+#endif // dTRIMESH_ENABLED
+
+	/* TC has speed/space 'issues' that don't make it a clear
+	   win by default on spheres/boxes. */
+	this->doSphereTC = false;
+	this->doBoxTC = false;
+	this->doCapsuleTC = false;
+
+#if dTRIMESH_ENABLED
+
+    const char* msg;
+    if ((msg =_AABBTreeCollider.ValidateSettings()))
+        dDebug (d_ERR_UASSERT, msg, " (%s:%d)", __FILE__,__LINE__);
+	_LSSCollider.SetPrimitiveTests(false);
+	_LSSCollider.SetFirstContact(false);
+
+#endif // dTRIMESH_ENABLED
+
+    for (int i=0; i<16; i++)
+        last_trans[i] = REAL( 0.0 );
+}
+
+dxTriMesh::~dxTriMesh(){
+    //
+}
+
+// Cleanup for allocations when shutting down ODE
+void opcode_collider_cleanup()
+{
+#if dTRIMESH_ENABLED
+	
+	// Clear TC caches
+	dxTriMesh::Faces.Empty();
+	dxTriMesh::defaultSphereCache.TouchedPrimitives.Empty();
+	dxTriMesh::defaultBoxCache.TouchedPrimitives.Empty();
+	dxTriMesh::defaultCapsuleCache.TouchedPrimitives.Empty();
+
+#endif // dTRIMESH_ENABLED
+}
+
+
+
+void dxTriMesh::ClearTCCache()
+{
+#if dTRIMESH_ENABLED
+  /* dxTriMesh::ClearTCCache uses dArray's setSize(0) to clear the caches -
+     but the destructor isn't called when doing this, so we would leak.
+     So, call the previous caches' containers' destructors by hand first. */
+    int i, n;
+    n = SphereTCCache.size();
+    for( i = 0; i < n; ++i ) {
+        SphereTCCache[i].~SphereTC();
+    }
+    SphereTCCache.setSize(0);
+    n = BoxTCCache.size();
+    for( i = 0; i < n; ++i ) {
+        BoxTCCache[i].~BoxTC();
+    }
+    BoxTCCache.setSize(0);
+	n = CapsuleTCCache.size();
+	for( i = 0; i < n; ++i ) {
+	  CapsuleTCCache[i].~CapsuleTC();
+	}
+	CapsuleTCCache.setSize(0);
+#endif // dTRIMESH_ENABLED
+}
+
+
+int dxTriMesh::AABBTest(dxGeom* g, dReal aabb[6]){
+    return 1;
+}
+
+
+void dxTriMesh::computeAABB() {
+    const dxTriMeshData* d = Data;
+    dVector3 c;
+    const dMatrix3& R = final_posr->R;
+    const dVector3& pos = final_posr->pos;
+    
+    dMULTIPLY0_331( c, R, d->AABBCenter );
+    
+    dReal xrange = dFabs(R[0] * Data->AABBExtents[0]) +
+        dFabs(R[1] * Data->AABBExtents[1]) + 
+        dFabs(R[2] * Data->AABBExtents[2]);
+    dReal yrange = dFabs(R[4] * Data->AABBExtents[0]) +
+        dFabs(R[5] * Data->AABBExtents[1]) + 
+        dFabs(R[6] * Data->AABBExtents[2]);
+    dReal zrange = dFabs(R[8] * Data->AABBExtents[0]) +
+        dFabs(R[9] * Data->AABBExtents[1]) + 
+        dFabs(R[10] * Data->AABBExtents[2]);
+
+    aabb[0] = c[0] + pos[0] - xrange;
+    aabb[1] = c[0] + pos[0] + xrange;
+    aabb[2] = c[1] + pos[1] - yrange;
+    aabb[3] = c[1] + pos[1] + yrange;
+    aabb[4] = c[2] + pos[2] - zrange;
+    aabb[5] = c[2] + pos[2] + zrange;
+}
+
+
+void dxTriMeshData::UpdateData()
+{
+#if  dTRIMESH_ENABLED
+	BVTree.Refit();
+#endif // dTRIMESH_ENABLED
+}
+
+
+dGeomID dCreateTriMesh(dSpaceID space, 
+		       dTriMeshDataID Data,
+		       dTriCallback* Callback,
+		       dTriArrayCallback* ArrayCallback,
+		       dTriRayCallback* RayCallback)
+{
+    dxTriMesh* Geom = new dxTriMesh(space, Data);
+    Geom->Callback = Callback;
+    Geom->ArrayCallback = ArrayCallback;
+    Geom->RayCallback = RayCallback;
+
+    return Geom;
+}
+
+void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->Callback = Callback;
+}
+
+dTriCallback* dGeomTriMeshGetCallback(dGeomID g)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	return ((dxTriMesh*)g)->Callback;
+}
+
+void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->ArrayCallback = ArrayCallback;
+}
+
+dTriArrayCallback* dGeomTriMeshGetArrayCallback(dGeomID g)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	return ((dxTriMesh*)g)->ArrayCallback;
+}
+
+void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->RayCallback = Callback;
+}
+
+dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");	
+	return ((dxTriMesh*)g)->RayCallback;
+}
+
+void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+	((dxTriMesh*)g)->Data = Data;
+	// I changed my data -- I know nothing about my own AABB anymore.
+	((dxTriMesh*)g)->gflags |= (GEOM_DIRTY|GEOM_AABB_BAD);
+}
+
+dTriMeshDataID dGeomTriMeshGetData(dGeomID g)
+{
+  dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+  return ((dxTriMesh*)g)->Data;
+}
+
+
+
+void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+  
+	switch (geomClass)
+	{
+		case dSphereClass: 
+			((dxTriMesh*)g)->doSphereTC = (1 == enable);
+			break;
+		case dBoxClass:
+			((dxTriMesh*)g)->doBoxTC = (1 == enable);
+			break;
+		case dCapsuleClass:
+			((dxTriMesh*)g)->doCapsuleTC = (1 == enable);
+			break;
+	}
+}
+
+int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass)
+{
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+  
+	switch (geomClass)
+	{
+		case dSphereClass:
+			if (((dxTriMesh*)g)->doSphereTC)
+				return 1;
+			break;
+		case dBoxClass:
+			if (((dxTriMesh*)g)->doBoxTC)
+				return 1;
+			break;
+		case dCapsuleClass:
+			if (((dxTriMesh*)g)->doCapsuleTC)
+				return 1;
+			break;
+	}
+	return 0;
+}
+
+void dGeomTriMeshClearTCCache(dGeomID g){
+    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+    dxTriMesh* Geom = (dxTriMesh*)g;
+    Geom->ClearTCCache();
+}
+
+/*
+ * returns the TriMeshDataID
+ */
+dTriMeshDataID
+dGeomTriMeshGetTriMeshDataID(dGeomID g)
+{
+    dxTriMesh* Geom = (dxTriMesh*) g;
+    return Geom->Data;
+}
+
+// Getting data
+void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2){
+    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+    dxTriMesh* Geom = (dxTriMesh*)g;
+
+    const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
+    const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
+
+    dVector3 v[3];
+	FetchTriangle(Geom, Index, Position, Rotation, v);
+
+    if (v0){
+        (*v0)[0] = v[0][0];
+        (*v0)[1] = v[0][1];
+        (*v0)[2] = v[0][2];
+        (*v0)[3] = v[0][3];
+    }
+    if (v1){
+        (*v1)[0] = v[1][0];
+        (*v1)[1] = v[1][1];
+        (*v1)[2] = v[1][2];
+        (*v1)[3] = v[1][3];
+    }
+    if (v2){
+        (*v2)[0] = v[2][0];
+        (*v2)[1] = v[2][1];
+        (*v2)[2] = v[2][2];
+        (*v2)[3] = v[2][3];
+    }
+}
+
+void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
+    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+    dxTriMesh* Geom = (dxTriMesh*)g;
+
+    const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
+    const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);
+
+    dVector3 dv[3];
+    FetchTriangle(Geom, Index, Position, Rotation, dv);
+
+    GetPointFromBarycentric(dv, u, v, Out);
+}
+
+int dGeomTriMeshGetTriangleCount (dGeomID g)	 	
+{	 	
+#if dTRIMESH_ENABLED
+    dxTriMesh* Geom = (dxTriMesh*)g;	 	
+    return Geom->Data->Mesh.GetNbTriangles();	 	
+#else
+	return 0;
+#endif // dTRIMESH_ENABLED
+}
+
+void dGeomTriMeshDataUpdate(dTriMeshDataID g) {
+    dUASSERT(g, "argument not trimesh data");
+    g->UpdateData();
+}
+
+#endif // dTRIMESH_OPCODE
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_plane.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_plane.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_plane.cpp	(revision 216)
@@ -0,0 +1,213 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// TriMesh - Plane collider by David Walters, July 2006
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+
+#if dTRIMESH_ENABLED
+
+#include "collision_util.h"
+#include "collision_std.h"
+
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_OPCODE
+int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip )
+{
+	dIASSERT( skip >= (int)sizeof( dContactGeom ) );
+	dIASSERT( o1->type == dTriMeshClass );
+	dIASSERT( o2->type == dPlaneClass );
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	// Alias pointers to the plane and trimesh
+	dxTriMesh* trimesh = (dxTriMesh*)( o1 );
+	dxPlane* plane = (dxPlane*)( o2 );
+
+	int contact_count = 0;
+
+	// Cache the maximum contact count.
+	const int contact_max = ( flags & NUMC_MASK );
+
+	// Cache trimesh position and rotation.
+	const dVector3& trimesh_pos = *(const dVector3*)dGeomGetPosition( trimesh );
+	const dMatrix3& trimesh_R = *(const dMatrix3*)dGeomGetRotation( trimesh );
+
+	//
+	// For all triangles.
+	//
+
+	// Cache the triangle count.
+	const int tri_count = trimesh->Data->Mesh.GetNbTriangles();
+
+	VertexPointers VP;
+	dReal alpha;
+	dVector3 vertex;
+
+#if !defined(dSINGLE) || 1
+	dVector3 int_vertex;		// Intermediate vertex for double precision mode.
+#endif // dSINGLE
+
+	// For each triangle
+	for ( int t = 0; t < tri_count; ++t )
+	{
+		// Get triangle, which should also use callback.
+		trimesh->Data->Mesh.GetTriangle( VP, t );
+
+		// For each vertex.
+		for ( int v = 0; v < 3; ++v )
+		{
+			//
+			// Get Vertex
+			//
+
+#if defined(dSINGLE) && 0 // Always assign via intermediate array as otherwise it is an incapsulation violation
+
+			dMULTIPLY0_331( vertex, trimesh_R, (float*)( VP.Vertex[ v ] ) );
+
+#else // dDOUBLE || 1
+
+			// OPCODE data is in single precision format.
+			int_vertex[ 0 ] = VP.Vertex[ v ]->x;
+			int_vertex[ 1 ] = VP.Vertex[ v ]->y;
+			int_vertex[ 2 ] = VP.Vertex[ v ]->z;
+
+			dMULTIPLY0_331( vertex, trimesh_R, int_vertex );
+
+#endif // dSINGLE/dDOUBLE
+			
+			vertex[ 0 ] += trimesh_pos[ 0 ];
+			vertex[ 1 ] += trimesh_pos[ 1 ];
+			vertex[ 2 ] += trimesh_pos[ 2 ];
+
+
+			//
+			// Collision?
+			//
+
+			// If alpha < 0 then point is if front of plane. i.e. no contact
+			// If alpha = 0 then the point is on the plane
+			alpha = plane->p[ 3 ] - dDOT( plane->p, vertex );
+      
+			// If alpha > 0 the point is behind the plane. CONTACT!
+			if ( alpha > 0 )
+			{
+				// Alias the contact
+                dContactGeom* contact = SAFECONTACT( flags, contacts, contact_count, skip );
+
+				contact->pos[ 0 ] = vertex[ 0 ];
+				contact->pos[ 1 ] = vertex[ 1 ];
+				contact->pos[ 2 ] = vertex[ 2 ];
+
+				contact->normal[ 0 ] = plane->p[ 0 ];
+				contact->normal[ 1 ] = plane->p[ 1 ];
+				contact->normal[ 2 ] = plane->p[ 2 ];
+
+				contact->depth = alpha;
+				contact->g1 = plane;
+				contact->g2 = trimesh;
+
+				++contact_count;
+
+				// All contact slots are full?
+				if ( contact_count >= contact_max )
+					return contact_count; // <=== STOP HERE
+			}
+		}
+	}
+
+	// Return contact count.
+	return contact_count;
+}
+#endif // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip )
+{
+	dIASSERT( skip >= (int)sizeof( dContactGeom ) );
+	dIASSERT( o1->type == dTriMeshClass );
+	dIASSERT( o2->type == dPlaneClass );
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	// Alias pointers to the plane and trimesh
+	dxTriMesh* trimesh = (dxTriMesh*)( o1 );
+	vec4f plane;
+	dGeomPlaneGetParams(o2, plane);
+
+	//Find collision
+
+	GDYNAMIC_ARRAY collision_result;
+	GIM_CREATE_TRIMESHPLANE_CONTACTS(collision_result);
+
+	gim_trimesh_plane_collision(&trimesh->m_collision_trimesh,plane,&collision_result);
+
+	if(collision_result.m_size == 0 )
+	{
+	    GIM_DYNARRAY_DESTROY(collision_result);
+	    return 0;
+	}
+
+
+	unsigned int contactcount = collision_result.m_size;
+	unsigned int contactmax = (unsigned int)(flags & NUMC_MASK);
+	if (contactcount > contactmax)
+	{
+		contactcount = contactmax;
+	}
+
+	dContactGeom* pcontact;
+	vec4f * planecontact_results = GIM_DYNARRAY_POINTER(vec4f,collision_result);
+
+    for(unsigned int i = 0; i < contactcount; i++ )
+	{
+        pcontact = SAFECONTACT(flags, contacts, i, skip);
+
+        pcontact->pos[0] = (*planecontact_results)[0];
+        pcontact->pos[1] = (*planecontact_results)[1];
+        pcontact->pos[2] = (*planecontact_results)[2];
+        pcontact->pos[3] = REAL(1.0);
+
+        pcontact->normal[0] = plane[0];
+        pcontact->normal[1] = plane[1];
+        pcontact->normal[2] = plane[2];
+        pcontact->normal[3] = 0;
+
+        pcontact->depth = (*planecontact_results)[3];
+        pcontact->g1 = o1;
+        pcontact->g2 = o2;
+
+        planecontact_results++;
+	 }
+
+	 GIM_DYNARRAY_DESTROY(collision_result);
+
+	return (int)contactcount;
+}
+#endif // dTRIMESH_GIMPACT
+
+
+#endif // dTRIMESH_ENABLED
+
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_ray.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_ray.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_ray.cpp	(revision 216)
@@ -0,0 +1,198 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// TriMesh code by Erwin de Vries.
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+
+#if dTRIMESH_ENABLED
+
+#include "collision_util.h"
+
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_OPCODE
+int dCollideRTL(dxGeom* g1, dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride){
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (RayGeom->type == dRayClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+
+	dxTriMesh* TriMesh = (dxTriMesh*)g1;
+
+	const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh);
+	const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh);
+
+	RayCollider& Collider = TriMesh->_RayCollider;
+
+	dReal Length = dGeomRayGetLength(RayGeom);
+
+	int FirstContact, BackfaceCull;
+	dGeomRayGetParams(RayGeom, &FirstContact, &BackfaceCull);
+	int ClosestHit = dGeomRayGetClosestHit(RayGeom);
+
+	Collider.SetFirstContact(FirstContact != 0);
+	Collider.SetClosestHit(ClosestHit != 0);
+	Collider.SetCulling(BackfaceCull != 0);
+	Collider.SetMaxDist(Length);
+
+	dVector3 Origin, Direction;
+	dGeomRayGet(RayGeom, Origin, Direction);
+
+	/* Make Ray */
+	Ray WorldRay;
+	WorldRay.mOrig.x = Origin[0];
+	WorldRay.mOrig.y = Origin[1];
+	WorldRay.mOrig.z = Origin[2];
+	WorldRay.mDir.x = Direction[0];
+	WorldRay.mDir.y = Direction[1];
+	WorldRay.mDir.z = Direction[2];
+
+	/* Intersect */
+	Matrix4x4 amatrix;
+        int TriCount = 0;
+        if (Collider.Collide(WorldRay, TriMesh->Data->BVTree, &MakeMatrix(TLPosition, TLRotation, amatrix))) {
+                TriCount = TriMesh->Faces.GetNbFaces();
+        }
+
+        if (TriCount == 0) {
+                return 0;
+        }
+	
+	const CollisionFace* Faces = TriMesh->Faces.GetFaces();
+
+	int OutTriCount = 0;
+	for (int i = 0; i < TriCount; i++) {
+		if (TriMesh->RayCallback == null ||
+                    TriMesh->RayCallback(TriMesh, RayGeom, Faces[i].mFaceID,
+                                         Faces[i].mU, Faces[i].mV)) {
+			const int& TriIndex = Faces[i].mFaceID;
+			if (!Callback(TriMesh, RayGeom, TriIndex)) {
+                                continue;
+                        }
+
+			dContactGeom* Contact = SAFECONTACT(Flags, Contacts, OutTriCount, Stride);
+
+			dVector3 dv[3];
+			FetchTriangle(TriMesh, TriIndex, TLPosition, TLRotation, dv);
+
+			// No sense to save on single type conversion in algorithm of this size.
+			// If there would be a custom typedef for distance type it could be used 
+			// instead of dReal. However using float directly is the loss of abstraction 
+			// and possible loss of precision in future.
+			/*float*/ dReal T = Faces[i].mDistance;
+			Contact->pos[0] = Origin[0] + (Direction[0] * T);
+			Contact->pos[1] = Origin[1] + (Direction[1] * T);
+			Contact->pos[2] = Origin[2] + (Direction[2] * T);
+			Contact->pos[3] = REAL(0.0);
+				
+			dVector3 vu;
+			vu[0] = dv[1][0] - dv[0][0];
+			vu[1] = dv[1][1] - dv[0][1];
+			vu[2] = dv[1][2] - dv[0][2];
+			vu[3] = REAL(0.0);
+				
+			dVector3 vv;
+			vv[0] = dv[2][0] - dv[0][0];
+			vv[1] = dv[2][1] - dv[0][1];
+			vv[2] = dv[2][2] - dv[0][2];
+			vv[3] = REAL(0.0);
+
+			dCROSS(Contact->normal, =, vv, vu);	// Reversed
+
+			dNormalize3(Contact->normal);
+
+			Contact->depth = T;
+			Contact->g1 = TriMesh;
+			Contact->g2 = RayGeom;
+				
+			OutTriCount++;
+
+			// Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
+			if (OutTriCount >= (Flags & NUMC_MASK)) {
+				break;
+			}
+		}
+	}
+	return OutTriCount;
+}
+#endif // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+int dCollideRTL(dxGeom* g1, dxGeom* RayGeom, int Flags, dContactGeom* Contacts, int Stride)
+{
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (RayGeom->type == dRayClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+	
+	dxTriMesh* TriMesh = (dxTriMesh*)g1;
+
+    dReal Length = dGeomRayGetLength(RayGeom);
+	int FirstContact, BackfaceCull;
+	dGeomRayGetParams(RayGeom, &FirstContact, &BackfaceCull);
+	int ClosestHit = dGeomRayGetClosestHit(RayGeom);
+	dVector3 Origin, Direction;
+	dGeomRayGet(RayGeom, Origin, Direction);
+
+    char intersect=0;
+    GIM_TRIANGLE_RAY_CONTACT_DATA contact_data;
+
+	if(ClosestHit)
+	{
+		intersect = gim_trimesh_ray_closest_collision(&TriMesh->m_collision_trimesh,Origin,Direction,Length,&contact_data);
+	}
+	else
+	{
+	    intersect = gim_trimesh_ray_collision(&TriMesh->m_collision_trimesh,Origin,Direction,Length,&contact_data);
+	}
+
+    if(intersect == 0)
+	{
+        return 0;
+    }
+
+	int OutTriCount = 0;
+
+	if(!TriMesh->RayCallback || 
+		TriMesh->RayCallback(TriMesh, RayGeom, contact_data.m_face_id, contact_data.u , contact_data.v))
+	{
+		dContactGeom* Contact = SAFECONTACT(Flags, Contacts, (OutTriCount-1), Stride);
+        VEC_COPY(Contact->pos,contact_data.m_point);
+        VEC_COPY(Contact->normal,contact_data.m_normal);
+        Contact->depth = contact_data.tparam;
+        Contact->g1 = TriMesh;
+        Contact->g2 = RayGeom;
+		
+		OutTriCount = 1;
+	}
+
+	return OutTriCount;
+}
+#endif  // dTRIMESH_GIMPACT
+
+#endif // dTRIMESH_ENABLED
+
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_sphere.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_sphere.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_sphere.cpp	(revision 216)
@@ -0,0 +1,573 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// TriMesh code by Erwin de Vries.
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+
+#if dTRIMESH_ENABLED
+
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_OPCODE
+#define MERGECONTACTS
+
+// Ripped from Opcode 1.1.
+static bool GetContactData(const dVector3& Center, dReal Radius, const dVector3 Origin, const dVector3 Edge0, const dVector3 Edge1, dReal& Dist, dReal& u, dReal& v){
+  
+        // now onto the bulk of the collision...
+
+	dVector3 Diff;
+	Diff[0] = Origin[0] - Center[0];
+	Diff[1] = Origin[1] - Center[1];
+	Diff[2] = Origin[2] - Center[2];
+	Diff[3] = Origin[3] - Center[3];
+
+	dReal A00 = dDOT(Edge0, Edge0);
+	dReal A01 = dDOT(Edge0, Edge1);
+	dReal A11 = dDOT(Edge1, Edge1);
+
+	dReal B0 = dDOT(Diff, Edge0);
+	dReal B1 = dDOT(Diff, Edge1);
+
+	dReal C = dDOT(Diff, Diff);
+
+	dReal Det = dFabs(A00 * A11 - A01 * A01);
+	u = A01 * B1 - A11 * B0;
+	v = A01 * B0 - A00 * B1;
+
+	dReal DistSq;
+
+	if (u + v <= Det){
+		if(u < REAL(0.0)){
+			if(v < REAL(0.0)){  // region 4
+				if(B0 < REAL(0.0)){
+					v = REAL(0.0);
+					if (-B0 >= A00){
+						u = REAL(1.0);
+						DistSq = A00 + REAL(2.0) * B0 + C;
+					}
+					else{
+						u = -B0 / A00;
+						DistSq = B0 * u + C;
+					}
+				}
+				else{
+					u = REAL(0.0);
+					if(B1 >= REAL(0.0)){
+						v = REAL(0.0);
+						DistSq = C;
+					}
+					else if(-B1 >= A11){
+						v = REAL(1.0);
+						DistSq = A11 + REAL(2.0) * B1 + C;
+					}
+					else{
+						v = -B1 / A11;
+						DistSq = B1 * v + C;
+					}
+				}
+			}
+			else{  // region 3
+				u = REAL(0.0);
+				if(B1 >= REAL(0.0)){
+					v = REAL(0.0);
+					DistSq = C;
+				}
+				else if(-B1 >= A11){
+					v = REAL(1.0);
+					DistSq = A11 + REAL(2.0) * B1 + C;
+				}
+				else{
+					v = -B1 / A11;
+					DistSq = B1 * v + C;
+				}
+			}
+		}
+		else if(v < REAL(0.0)){  // region 5
+			v = REAL(0.0);
+			if (B0 >= REAL(0.0)){
+				u = REAL(0.0);
+				DistSq = C;
+			}
+			else if (-B0 >= A00){
+				u = REAL(1.0);
+				DistSq = A00 + REAL(2.0) * B0 + C;
+			}
+			else{
+				u = -B0 / A00;
+				DistSq = B0 * u + C;
+			}
+		}
+		else{  // region 0
+			// minimum at interior point
+			if (Det == REAL(0.0)){
+				u = REAL(0.0);
+				v = REAL(0.0);
+				DistSq = FLT_MAX;
+			}
+			else{
+				dReal InvDet = REAL(1.0) / Det;
+				u *= InvDet;
+				v *= InvDet;
+				DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
+			}
+		}
+	}
+	else{
+		dReal Tmp0, Tmp1, Numer, Denom;
+
+		if(u < REAL(0.0)){  // region 2
+			Tmp0 = A01 + B0;
+			Tmp1 = A11 + B1;
+			if (Tmp1 > Tmp0){
+				Numer = Tmp1 - Tmp0;
+				Denom = A00 - REAL(2.0) * A01 + A11;
+				if (Numer >= Denom){
+					u = REAL(1.0);
+					v = REAL(0.0);
+					DistSq = A00 + REAL(2.0) * B0 + C;
+				}
+				else{
+					u = Numer / Denom;
+					v = REAL(1.0) - u;
+					DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
+				}
+			}
+			else{
+				u = REAL(0.0);
+				if(Tmp1 <= REAL(0.0)){
+					v = REAL(1.0);
+					DistSq = A11 + REAL(2.0) * B1 + C;
+				}
+				else if(B1 >= REAL(0.0)){
+					v = REAL(0.0);
+					DistSq = C;
+				}
+				else{
+					v = -B1 / A11;
+					DistSq = B1 * v + C;
+				}
+			}
+		}
+		else if(v < REAL(0.0)){  // region 6
+			Tmp0 = A01 + B1;
+			Tmp1 = A00 + B0;
+			if (Tmp1 > Tmp0){
+				Numer = Tmp1 - Tmp0;
+				Denom = A00 - REAL(2.0) * A01 + A11;
+				if (Numer >= Denom){
+					v = REAL(1.0);
+					u = REAL(0.0);
+					DistSq = A11 + REAL(2.0) * B1 + C;
+				}
+				else{
+					v = Numer / Denom;
+					u = REAL(1.0) - v;
+					DistSq =  u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
+				}
+			}
+			else{
+				v = REAL(0.0);
+				if (Tmp1 <= REAL(0.0)){
+					u = REAL(1.0);
+					DistSq = A00 + REAL(2.0) * B0 + C;
+				}
+				else if(B0 >= REAL(0.0)){
+					u = REAL(0.0);
+					DistSq = C;
+				}
+				else{
+					u = -B0 / A00;
+					DistSq = B0 * u + C;
+				}
+			}
+		}
+		else{  // region 1
+			Numer = A11 + B1 - A01 - B0;
+			if (Numer <= REAL(0.0)){
+				u = REAL(0.0);
+				v = REAL(1.0);
+				DistSq = A11 + REAL(2.0) * B1 + C;
+			}
+			else{
+				Denom = A00 - REAL(2.0) * A01 + A11;
+				if (Numer >= Denom){
+					u = REAL(1.0);
+					v = REAL(0.0);
+					DistSq = A00 + REAL(2.0) * B0 + C;
+				}
+				else{
+					u = Numer / Denom;
+					v = REAL(1.0) - u;
+					DistSq = u * (A00 * u + A01 * v + REAL(2.0) * B0) + v * (A01 * u + A11 * v + REAL(2.0) * B1) + C;
+				}
+			}
+		}
+	}
+
+	Dist = dSqrt(dFabs(DistSq));
+
+	if (Dist <= Radius){
+		Dist = Radius - Dist;
+		return true;
+	}
+	else return false;
+}
+
+int dCollideSTL(dxGeom* g1, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride){
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (SphereGeom->type == dSphereClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+
+	dxTriMesh* TriMesh = (dxTriMesh*)g1;
+
+	// Init
+	const dVector3& TLPosition = *(const dVector3*)dGeomGetPosition(TriMesh);
+	const dMatrix3& TLRotation = *(const dMatrix3*)dGeomGetRotation(TriMesh);
+
+	SphereCollider& Collider = TriMesh->_SphereCollider;
+
+	const dVector3& Position = *(const dVector3*)dGeomGetPosition(SphereGeom);
+	dReal Radius = dGeomSphereGetRadius(SphereGeom);
+
+	// Sphere
+	Sphere Sphere;
+	Sphere.mCenter.x = Position[0];
+	Sphere.mCenter.y = Position[1];
+	Sphere.mCenter.z = Position[2];
+	Sphere.mRadius = Radius;
+
+	Matrix4x4 amatrix;
+
+	// TC results
+	if (TriMesh->doSphereTC) {
+		dxTriMesh::SphereTC* sphereTC = 0;
+		for (int i = 0; i < TriMesh->SphereTCCache.size(); i++){
+			if (TriMesh->SphereTCCache[i].Geom == SphereGeom){
+				sphereTC = &TriMesh->SphereTCCache[i];
+				break;
+			}
+		}
+
+		if (!sphereTC){
+			TriMesh->SphereTCCache.push(dxTriMesh::SphereTC());
+
+			sphereTC = &TriMesh->SphereTCCache[TriMesh->SphereTCCache.size() - 1];
+			sphereTC->Geom = SphereGeom;
+		}
+		
+		// Intersect
+		Collider.SetTemporalCoherence(true);
+		Collider.Collide(*sphereTC, Sphere, TriMesh->Data->BVTree, null, 
+						 &MakeMatrix(TLPosition, TLRotation, amatrix));
+	}
+	else {
+		Collider.SetTemporalCoherence(false);
+		Collider.Collide(dxTriMesh::defaultSphereCache, Sphere, TriMesh->Data->BVTree, null, 
+						 &MakeMatrix(TLPosition, TLRotation, amatrix));
+ 	}
+
+	if (! Collider.GetContactStatus()) {
+		// no collision occurred
+		return 0;
+	}
+
+	// get results
+	int TriCount = Collider.GetNbTouchedPrimitives();
+	const int* Triangles = (const int*)Collider.GetTouchedPrimitives();
+
+	if (TriCount != 0){
+		if (TriMesh->ArrayCallback != null){
+			TriMesh->ArrayCallback(TriMesh, SphereGeom, Triangles, TriCount);
+		}
+
+		int OutTriCount = 0;
+		for (int i = 0; i < TriCount; i++){
+			if (OutTriCount == (Flags & NUMC_MASK)){
+				break;
+			}
+
+			const int TriIndex = Triangles[i];
+
+			dVector3 dv[3];
+			if (!Callback(TriMesh, SphereGeom, TriIndex))
+				continue;
+			FetchTriangle(TriMesh, TriIndex, TLPosition, TLRotation, dv);
+
+			dVector3& v0 = dv[0];
+			dVector3& v1 = dv[1];
+			dVector3& v2 = dv[2];
+
+			dVector3 vu;
+			vu[0] = v1[0] - v0[0];
+			vu[1] = v1[1] - v0[1];
+			vu[2] = v1[2] - v0[2];
+			vu[3] = REAL(0.0);
+
+			dVector3 vv;
+			vv[0] = v2[0] - v0[0];
+			vv[1] = v2[1] - v0[1];
+			vv[2] = v2[2] - v0[2];
+			vv[3] = REAL(0.0);
+
+			// Get plane coefficients
+			dVector4 Plane;
+			dCROSS(Plane, =, vu, vv);
+
+			dReal Area = dSqrt(dDOT(Plane, Plane));	// We can use this later
+			Plane[0] /= Area;
+			Plane[1] /= Area;
+			Plane[2] /= Area;
+
+			Plane[3] = dDOT(Plane, v0);	
+
+			/* If the center of the sphere is within the positive halfspace of the
+				* triangle's plane, allow a contact to be generated.
+				* If the center of the sphere made it into the positive halfspace of a
+				* back-facing triangle, then the physics update and/or velocity needs
+				* to be adjusted (penetration has occured anyway).
+				*/
+		  
+			dReal side = dDOT(Plane,Position) - Plane[3];
+
+			if(side < REAL(0.0)) {
+				continue;
+			}
+
+			dReal Depth;
+			dReal u, v;
+			if (!GetContactData(Position, Radius, v0, vu, vv, Depth, u, v)){
+				continue;	// Sphere doesn't hit triangle
+			}
+
+			if (Depth < REAL(0.0)){
+				Depth = REAL(0.0);
+			}
+
+			dContactGeom* Contact = SAFECONTACT(Flags, Contacts, OutTriCount, Stride);
+
+			dReal w = REAL(1.0) - u - v;
+			Contact->pos[0] = (v0[0] * w) + (v1[0] * u) + (v2[0] * v);
+			Contact->pos[1] = (v0[1] * w) + (v1[1] * u) + (v2[1] * v);
+			Contact->pos[2] = (v0[2] * w) + (v1[2] * u) + (v2[2] * v);
+			Contact->pos[3] = REAL(0.0);
+
+			// Using normal as plane (reversed)
+			Contact->normal[0] = -Plane[0];
+			Contact->normal[1] = -Plane[1];
+			Contact->normal[2] = -Plane[2];
+			Contact->normal[3] = REAL(0.0);
+
+			// Depth returned from GetContactData is depth along 
+			// contact point - sphere center direction
+			// we'll project it to contact normal
+			dVector3 dir;
+			dir[0] = Position[0]-Contact->pos[0];
+			dir[1] = Position[1]-Contact->pos[1];
+			dir[2] = Position[2]-Contact->pos[2];
+			dReal dirProj = dDOT(dir, Plane) / dSqrt(dDOT(dir, dir));
+			Contact->depth = Depth * dirProj;
+			//Contact->depth = Radius - side; // (mg) penetration depth is distance along normal not shortest distance
+			Contact->side1 = TriIndex;
+
+			//Contact->g1 = TriMesh;
+			//Contact->g2 = SphereGeom;
+			
+			OutTriCount++;
+		}
+#ifdef MERGECONTACTS	// Merge all contacts into 1
+		if (OutTriCount != 0){
+			dContactGeom* Contact = SAFECONTACT(Flags, Contacts, 0, Stride);
+			
+			if (OutTriCount != 1 && !(Flags & CONTACTS_UNIMPORTANT)){
+				Contact->normal[0] *= Contact->depth;
+				Contact->normal[1] *= Contact->depth;
+				Contact->normal[2] *= Contact->depth;
+				Contact->normal[3] *= Contact->depth;
+
+				for (int i = 1; i < OutTriCount; i++){
+					dContactGeom* TempContact = SAFECONTACT(Flags, Contacts, i, Stride);
+					
+					Contact->pos[0] += TempContact->pos[0];
+					Contact->pos[1] += TempContact->pos[1];
+					Contact->pos[2] += TempContact->pos[2];
+					Contact->pos[3] += TempContact->pos[3];
+					
+					Contact->normal[0] += TempContact->normal[0] * TempContact->depth;
+					Contact->normal[1] += TempContact->normal[1] * TempContact->depth;
+					Contact->normal[2] += TempContact->normal[2] * TempContact->depth;
+					Contact->normal[3] += TempContact->normal[3] * TempContact->depth;
+				}
+			
+				Contact->pos[0] /= OutTriCount;
+				Contact->pos[1] /= OutTriCount;
+				Contact->pos[2] /= OutTriCount;
+				Contact->pos[3] /= OutTriCount;
+				
+				// Remember to divide in square space.
+				Contact->depth = dSqrt(dDOT(Contact->normal, Contact->normal) / OutTriCount);
+
+				dNormalize3(Contact->normal);
+			}
+
+			Contact->g1 = TriMesh;
+			Contact->g2 = SphereGeom;
+
+			// TODO:
+			// Side1 now contains index of triangle that gave first hit
+			// Probably we should find index of triangle with deepest penetration
+
+			return 1;
+		}
+		else return 0;
+#elif defined MERGECONTACTNORMALS	// Merge all normals, and distribute between all contacts
+		if (OutTriCount != 0){
+			if (OutTriCount != 1 && !(Flags & CONTACTS_UNIMPORTANT)){
+				dVector3& Normal = SAFECONTACT(Flags, Contacts, 0, Stride)->normal;
+				Normal[0] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
+				Normal[1] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
+				Normal[2] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
+				Normal[3] *= SAFECONTACT(Flags, Contacts, 0, Stride)->depth;
+
+				for (int i = 1; i < OutTriCount; i++){
+					dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride);
+
+					Normal[0] += Contact->normal[0] * Contact->depth;
+					Normal[1] += Contact->normal[1] * Contact->depth;
+					Normal[2] += Contact->normal[2] * Contact->depth;
+					Normal[3] += Contact->normal[3] * Contact->depth;
+				}
+				dNormalize3(Normal);
+
+				for (int i = 1; i < OutTriCount; i++){
+					dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride);
+
+					Contact->normal[0] = Normal[0];
+					Contact->normal[1] = Normal[1];
+					Contact->normal[2] = Normal[2];
+					Contact->normal[3] = Normal[3];
+
+					Contact->g1 = TriMesh;
+					Contact->g2 = SphereGeom;
+				}
+			}
+			else{
+				SAFECONTACT(Flags, Contacts, 0, Stride)->g1 = TriMesh;
+				SAFECONTACT(Flags, Contacts, 0, Stride)->g2 = SphereGeom;
+			}
+
+			return OutTriCount;
+		}
+		else return 0;
+#else	//MERGECONTACTNORMALS	// Just gather penetration depths and return
+		for (int i = 0; i < OutTriCount; i++){
+			dContactGeom* Contact = SAFECONTACT(Flags, Contacts, i, Stride);
+
+			//Contact->depth = dSqrt(dDOT(Contact->normal, Contact->normal));
+
+			/*Contact->normal[0] /= Contact->depth;
+			Contact->normal[1] /= Contact->depth;
+			Contact->normal[2] /= Contact->depth;
+			Contact->normal[3] /= Contact->depth;*/
+
+			Contact->g1 = TriMesh;
+			Contact->g2 = SphereGeom;
+		}
+
+		return OutTriCount;
+#endif	// MERGECONTACTS
+	}
+	else return 0;
+}
+#endif // dTRIMESH_OPCODE
+
+#if dTRIMESH_GIMPACT
+int dCollideSTL(dxGeom* g1, dxGeom* SphereGeom, int Flags, dContactGeom* Contacts, int Stride)
+{
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (SphereGeom->type == dSphereClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+	
+	dxTriMesh* TriMesh = (dxTriMesh*)g1;
+    dVector3& Position = *(dVector3*)dGeomGetPosition(SphereGeom);
+	dReal Radius = dGeomSphereGetRadius(SphereGeom);
+ //Create contact list
+    GDYNAMIC_ARRAY trimeshcontacts;
+    GIM_CREATE_CONTACT_LIST(trimeshcontacts);
+
+    //Collide trimeshes
+    gim_trimesh_sphere_collision(&TriMesh->m_collision_trimesh,Position,Radius,&trimeshcontacts);
+
+    if(trimeshcontacts.m_size == 0)
+    {
+        GIM_DYNARRAY_DESTROY(trimeshcontacts);
+        return 0;
+    }
+
+    GIM_CONTACT * ptrimeshcontacts = GIM_DYNARRAY_POINTER(GIM_CONTACT,trimeshcontacts);
+
+	unsigned contactcount = trimeshcontacts.m_size;
+	unsigned maxcontacts = (unsigned)(Flags & NUMC_MASK);
+	if (contactcount > maxcontacts)
+	{
+		contactcount = maxcontacts;
+	}
+
+    dContactGeom* pcontact;
+	unsigned i;
+	
+	for (i=0;i<contactcount;i++)
+	{
+        pcontact = SAFECONTACT(Flags, Contacts, i, Stride);
+
+        pcontact->pos[0] = ptrimeshcontacts->m_point[0];
+        pcontact->pos[1] = ptrimeshcontacts->m_point[1];
+        pcontact->pos[2] = ptrimeshcontacts->m_point[2];
+        pcontact->pos[3] = REAL(1.0);
+
+        pcontact->normal[0] = ptrimeshcontacts->m_normal[0];
+        pcontact->normal[1] = ptrimeshcontacts->m_normal[1];
+        pcontact->normal[2] = ptrimeshcontacts->m_normal[2];
+        pcontact->normal[3] = 0;
+
+        pcontact->depth = ptrimeshcontacts->m_depth;
+        pcontact->g1 = g1;
+        pcontact->g2 = SphereGeom;
+
+        ptrimeshcontacts++;
+	}
+
+	GIM_DYNARRAY_DESTROY(trimeshcontacts);
+
+    return (int)contactcount;
+}
+#endif // dTRIMESH_GIMPACT
+
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_trimesh.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_trimesh.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_trimesh.cpp	(revision 216)
@@ -0,0 +1,2033 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// OPCODE TriMesh/TriMesh collision code by Jeff Smith (c) 2004
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+
+// Classic Implementation
+#if !dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER
+
+#if dTRIMESH_ENABLED
+
+#include "collision_util.h"
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_OPCODE
+
+#define SMALL_ELT           REAL(2.5e-4)
+#define EXPANDED_ELT_THRESH REAL(1.0e-3)
+#define DISTANCE_EPSILON    REAL(1.0e-8)
+#define VELOCITY_EPSILON    REAL(1.0e-5)
+#define TINY_PENETRATION    REAL(5.0e-6)
+
+struct LineContactSet
+{
+	enum
+	{
+		MAX_POINTS = 8
+	};
+
+    dVector3 Points[MAX_POINTS];
+    int      Count;
+};
+
+
+static void GetTriangleGeometryCallback(udword, VertexPointers&, udword);
+static void GenerateContact(int, dContactGeom*, int, dxTriMesh*,  dxTriMesh*, 
+                            const dVector3, const dVector3, dReal, int&);
+static int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3],
+                                        dReal U0[3],dReal U1[3],dReal U2[3],int *coplanar,
+                                        dReal isectpt1[3],dReal isectpt2[3]);
+inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B);
+static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv );
+static int IntersectLineSegmentRay(dVector3, dVector3, dVector3, dVector3,  dVector3);
+static bool FindTriSolidIntrsection(const dVector3 Tri[3], 
+                                    const dVector4 Planes[6], int numSides,
+                                    LineContactSet& ClippedPolygon );
+static void ClipConvexPolygonAgainstPlane( const dVector3, dReal, LineContactSet& );
+static bool SimpleUnclippedTest(dVector3 in_CoplanarPt, dVector3 in_v, dVector3 in_elt,
+                                dVector3 in_n, dVector3* in_col_v, dReal &out_depth);
+static int ExamineContactPoint(dVector3* v_col, dVector3 in_n, dVector3 in_point);
+static int RayTriangleIntersect(const dVector3 orig, const dVector3 dir,
+                                const dVector3 vert0, const dVector3 vert1,const dVector3 vert2,
+                                dReal *t,dReal *u,dReal *v);
+
+
+
+
+/* some math macros */
+#define CROSS(dest,v1,v2) { dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
+                            dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
+                            dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; }
+
+#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
+
+#define SUB(dest,v1,v2) { dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2]; }
+
+#define ADD(dest,v1,v2) { dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2]; }
+
+#define MULT(dest,v,factor) { dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2]; }
+
+#define SET(dest,src) { dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2]; }
+
+#define SMULT(p,q,s) { p[0]=q[0]*s; p[1]=q[1]*s; p[2]=q[2]*s; }
+
+#define COMBO(combo,p,t,q) { combo[0]=p[0]+t*q[0]; combo[1]=p[1]+t*q[1]; combo[2]=p[2]+t*q[2]; }
+
+#define LENGTH(x)  ((dReal) dSqrt(dDOT(x, x)))
+
+#define DEPTH(d, p, q, n) d = (p[0] - q[0])*n[0] +  (p[1] - q[1])*n[1] +  (p[2] - q[2])*n[2];
+
+inline const dReal dMin(const dReal x, const dReal y)
+{
+    return x < y ? x : y;
+}
+
+
+inline void
+SwapNormals(dVector3 *&pen_v, dVector3 *&col_v, dVector3* v1, dVector3* v2,
+            dVector3 *&pen_elt, dVector3 *elt_f1, dVector3 *elt_f2,
+            dVector3 n, dVector3 n1, dVector3 n2)
+{
+    if (pen_v == v1) {
+        pen_v = v2;
+        pen_elt = elt_f2;
+        col_v = v1;
+        SET(n, n1);
+    }
+    else {
+        pen_v = v1;
+        pen_elt = elt_f1;
+        col_v = v2;
+        SET(n, n2);
+    }
+}
+
+
+
+
+int 
+dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride)
+{
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (g2->type == dTriMeshClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+
+    dxTriMesh* TriMesh1 = (dxTriMesh*) g1;
+    dxTriMesh* TriMesh2 = (dxTriMesh*) g2;
+
+    dReal * TriNormals1 = (dReal *) TriMesh1->Data->Normals;
+    dReal * TriNormals2 = (dReal *) TriMesh2->Data->Normals;
+
+    const dVector3& TLPosition1 = *(const dVector3*) dGeomGetPosition(TriMesh1);
+    // TLRotation1 = column-major order
+    const dMatrix3& TLRotation1 = *(const dMatrix3*) dGeomGetRotation(TriMesh1);
+
+    const dVector3& TLPosition2 = *(const dVector3*) dGeomGetPosition(TriMesh2);
+    // TLRotation2 = column-major order
+    const dMatrix3& TLRotation2 = *(const dMatrix3*) dGeomGetRotation(TriMesh2);
+
+    AABBTreeCollider& Collider = TriMesh1->_AABBTreeCollider;
+
+    static BVTCache ColCache;
+    ColCache.Model0 = &TriMesh1->Data->BVTree;
+    ColCache.Model1 = &TriMesh2->Data->BVTree;
+
+    // Collision query
+    Matrix4x4 amatrix, bmatrix;
+    BOOL IsOk = Collider.Collide(ColCache,
+                                 &MakeMatrix(TLPosition1, TLRotation1, amatrix),
+                                 &MakeMatrix(TLPosition2, TLRotation2, bmatrix) );
+    
+
+    // Make "double" versions of these matrices, if appropriate
+    dMatrix4 A, B;
+    dMakeMatrix4(TLPosition1, TLRotation1, A);
+    dMakeMatrix4(TLPosition2, TLRotation2, B);
+
+
+    if (IsOk) {
+        // Get collision status => if true, objects overlap
+        if ( Collider.GetContactStatus() ) {
+            // Number of colliding pairs and list of pairs
+            int TriCount = Collider.GetNbPairs();
+            const Pair* CollidingPairs = Collider.GetPairs();
+
+            if (TriCount > 0) {
+                // step through the pairs, adding contacts
+                int             id1, id2;
+                int             OutTriCount = 0;
+                dVector3        v1[3], v2[3], CoplanarPt;
+                dVector3        e1, e2, e3, n1, n2, n, ContactNormal;
+                dReal           depth;
+                dVector3        orig_pos, old_pos1, old_pos2, elt1, elt2, elt_sum;
+                dVector3        elt_f1[3], elt_f2[3];
+                dReal          contact_elt_length = SMALL_ELT;
+                LineContactSet  firstClippedTri, secondClippedTri;
+                dVector3       *firstClippedElt = new dVector3[LineContactSet::MAX_POINTS];
+                dVector3       *secondClippedElt = new dVector3[LineContactSet::MAX_POINTS];
+                
+
+                // only do these expensive inversions once
+                dMatrix4 InvMatrix1, InvMatrix2;
+                dInvertMatrix4(A, InvMatrix1);
+                dInvertMatrix4(B, InvMatrix2);
+
+                
+                for (int i = 0; i < TriCount; i++) {
+                        
+                        id1 = CollidingPairs[i].id0;
+                        id2 = CollidingPairs[i].id1;
+                        
+                        // grab the colliding triangles
+                        FetchTriangle((dxTriMesh*) g1, id1, TLPosition1, TLRotation1, v1);
+                        FetchTriangle((dxTriMesh*) g2, id2, TLPosition2, TLRotation2, v2);
+                        // Since we'll be doing matrix transfomrations, we need to
+                        //  make sure that all vertices have four elements
+                        for (int j=0; j<3; j++) {
+                            v1[j][3] = 1.0;
+                            v2[j][3] = 1.0;
+                        }
+                            
+                        
+                        int IsCoplanar = 0;
+                        dReal IsectPt1[3], IsectPt2[3];
+
+                        // Sometimes OPCODE makes mistakes, so we look at the return
+                        //  value for TriTriIntersectWithIsectLine.  A retcode of "0"
+                        //  means no intersection took place
+                        if ( TriTriIntersectWithIsectLine( v1[0], v1[1], v1[2], v2[0], v2[1], v2[2],
+                                                           &IsCoplanar,
+                                                           IsectPt1, IsectPt2) ) {
+                            
+                            // Compute the normals of the colliding faces
+                            //
+                            if (TriNormals1 == NULL) {
+                                SUB( e1, v1[1], v1[0] );
+                                SUB( e2, v1[2], v1[0] );
+                                CROSS( n1, e1, e2 );
+                                dNormalize3(n1);
+                            }
+                            else {
+                                // If we were passed normals, we need to adjust them to take into
+                                //  account the objects' current rotations
+                                e1[0] = TriNormals1[id1*3];
+                                e1[1] = TriNormals1[id1*3 + 1];
+                                e1[2] = TriNormals1[id1*3 + 2];
+                                e1[3] = 0.0;
+                                
+                                //dMultiply1(n1, TLRotation1, e1, 3, 3, 1);
+                                dMultiply0(n1, TLRotation1, e1, 3, 3, 1);
+                                n1[3] = 1.0;
+                            }
+                            
+                            if (TriNormals2 == NULL)  {
+                                SUB( e1, v2[1], v2[0] );
+                                SUB( e2, v2[2], v2[0] );
+                                CROSS( n2, e1, e2);
+                                dNormalize3(n2);
+                            }
+                            else {
+                                // If we were passed normals, we need to adjust them to take into
+                                //  account the objects' current rotations
+                                e2[0] = TriNormals2[id2*3];
+                                e2[1] = TriNormals2[id2*3 + 1];
+                                e2[2] = TriNormals2[id2*3 + 2];
+                                e2[3] = 0.0;
+                                
+                                //dMultiply1(n2, TLRotation2, e2, 3, 3, 1);
+                                dMultiply0(n2, TLRotation2, e2, 3, 3, 1);
+                                n2[3] = 1.0;
+                            }
+                            
+
+                            if (IsCoplanar) {
+                                // We can reach this case if the faces are coplanar, OR
+                                //  if they don't actually intersect.  (OPCODE can make
+                                //  mistakes)
+                                if (dFabs(dDOT(n1, n2)) > REAL(0.999)) {
+                                    // If the faces are coplanar, we declare that the point of
+                                    //  contact is at the average location of the vertices of
+                                    //  both faces
+                                    dVector3 ContactPt;
+                                    for (int j=0; j<3; j++) {
+                                        ContactPt[j] = 0.0;
+                                        for (int k=0; k<3; k++)
+                                            ContactPt[j] += v1[k][j] + v2[k][j];
+                                        ContactPt[j] /= 6.0;
+                                    }
+                                    ContactPt[3] = 1.0;
+                                    
+                                    // and the contact normal is the normal of face 2
+                                    //  (could be face 1, because they are the same)
+                                    SET(n, n2);
+                                    
+                                    // and the penetration depth is the co-normal
+                                    // distance between any two vertices A and B,
+                                    // i.e.  d = DOT(n, (A-B))
+                                    DEPTH(depth, v1[1], v2[1], n);
+                                    if (depth < 0)
+                                        depth *= -1.0;
+                                    
+                                    GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                    ContactPt, n, depth, OutTriCount);
+                                }
+                            }
+                            else {
+                                // Otherwise (in non-co-planar cases), we create a coplanar 
+                                //  point -- the middle of the line of intersection -- that
+                                //   will be used for various computations down the road
+                                for (int j=0; j<3; j++)
+                                    CoplanarPt[j] = ( (IsectPt1[j] + IsectPt2[j]) / REAL(2.0) );
+                                CoplanarPt[3] = 1.0;
+                                
+                                // Find the ELT of the coplanar point
+                                //
+                                dMultiply1(orig_pos, InvMatrix1, CoplanarPt, 4, 4, 1);
+                                dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
+                                SUB(elt1, CoplanarPt, old_pos1);
+                                
+                                dMultiply1(orig_pos, InvMatrix2, CoplanarPt, 4, 4, 1);
+                                dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
+                                SUB(elt2, CoplanarPt, old_pos2);
+                                
+                                SUB(elt_sum, elt1, elt2);  // net motion of the coplanar point
+                                
+                                
+                                // Calculate how much the vertices of each face moved in the
+                                //  direction of the opposite face's normal
+                                //
+                                dReal    total_dp1, total_dp2;
+                                total_dp1 = 0.0;
+                                total_dp2 = 0.0;
+                                
+                                for (int ii=0; ii<3; ii++) {
+                                    // find the estimated linear translation (ELT) of the vertices
+                                    //  on face 1, wrt to the center of face 2. 
+                                    
+                                    // un-transform this vertex by the current transform
+                                    dMultiply1(orig_pos, InvMatrix1, v1[ii], 4, 4, 1 );
+                                    
+                                    // re-transform this vertex by last_trans (to get its old
+                                    //  position)
+                                    dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
+                                    
+                                    // Then subtract this position from our current one to find
+                                    //  the elapsed linear translation (ELT)
+                                    for (int k=0; k<3; k++) {
+                                        elt_f1[ii][k] = (v1[ii][k] - old_pos1[k]) - elt2[k];
+                                    }
+                                    
+                                    // Take the dot product of the ELT  for each vertex (wrt the
+                                    //  center of face2)
+                                    total_dp1 += dFabs( dDOT(elt_f1[ii], n2) );
+                                }
+                                
+                                for (int ii=0; ii<3; ii++) {
+                                    // find the estimated linear translation (ELT) of the vertices
+                                    //  on face 2, wrt to the center of face 1. 
+                                    dMultiply1(orig_pos, InvMatrix2, v2[ii], 4, 4, 1);
+                                    dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
+                                    for (int k=0; k<3; k++) {
+                                        elt_f2[ii][k] = (v2[ii][k] - old_pos2[k]) - elt1[k];
+                                    }
+                                    
+                                    // Take the dot product of the ELT  for each vertex (wrt the
+                                    //  center of face2) and add them
+                                    total_dp2 += dFabs( dDOT(elt_f2[ii], n1) );
+                                }
+                                
+                                
+                                ////////
+                                // Estimate the penetration depth.  
+                                //                            
+                                dReal    dp;
+                                BOOL      badPen = true;
+                                dVector3 *pen_v;   // the "penetrating vertices"
+                                dVector3 *pen_elt; // the elt_f of the penetrating face
+                                dVector3 *col_v;   // the "collision vertices" (the penetrated face)
+                                
+                                SMULT(n2, n2, -1.0); // SF PATCH #1335183
+                                depth = 0.0;
+                                if ((total_dp1 > DISTANCE_EPSILON) || (total_dp2 > DISTANCE_EPSILON)) {
+                                    ////////
+                                    // Find the collision normal, by finding the face
+                                    //  that is pointed "most" in the direction of travel
+                                    //  of the two triangles
+                                    //
+                                    if (total_dp2 > total_dp1) {
+                                        pen_v = v2;
+                                        pen_elt = elt_f2;
+                                        col_v = v1;
+                                        SET(n, n1);
+                                    }
+                                    else {
+                                        pen_v = v1;
+                                        pen_elt = elt_f1;
+                                        col_v = v2;
+                                        SET(n, n2);
+                                    }
+                                }
+                                else {
+                                    // the total_dp is very small, so let's fall back
+                                    //  to a different test
+                                    if (LENGTH(elt2) > LENGTH(elt1)) {
+                                        pen_v = v2;
+                                        pen_elt = elt_f2;
+                                        col_v = v1;
+                                        SET(n, n1);
+                                    }
+                                    else {
+                                        pen_v = v1;
+                                        pen_elt = elt_f1;
+                                        col_v = v2;
+                                        SET(n, n2);
+                                    }
+                                }
+                                
+
+                                for (int j=0; j<3; j++)
+                                    if (SimpleUnclippedTest(CoplanarPt, pen_v[j], pen_elt[j], n, col_v, depth)) {
+                                        GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                        pen_v[j], n, depth, OutTriCount);
+                                        badPen = false;
+
+										if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+											break;
+										}
+                                    }
+                                
+
+                                if (badPen) {
+                                    // try the other normal
+                                    SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
+
+                                    for (int j=0; j<3; j++)
+                                        if (SimpleUnclippedTest(CoplanarPt, pen_v[j], pen_elt[j], n, col_v, depth)) {
+                                            GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                            pen_v[j], n, depth, OutTriCount);
+                                            badPen = false;
+
+											if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+												break;
+											}
+                                    }
+                                }
+
+
+
+                                ////////////////////////////////////////
+                                //
+                                // If we haven't found a good penetration, then we're probably straddling
+                                //  the edge of one of the objects, or the penetraing face is big
+                                //  enough that all of its vertices are outside the bounds of the
+                                //  penetrated face.
+                                // In these cases, we do a more expensive test. We clip the penetrating
+                                //  triangle with a solid defined by the penetrated triangle, and repeat
+                                //  the tests above on this new polygon
+                                if (badPen) {
+      
+                                    // Switch pen_v and n back again
+                                    SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
+                                    
+                                    
+                                    // Find the three sides (no top or bottom) of the solid defined by 
+                                    //  the edges of the penetrated triangle.
+                                    
+                                    // The dVector4 "plane" structures contain the following information:
+                                    //  [0]-[2]: The normal of the face, pointing INWARDS (i.e.
+                                    //           the inverse normal
+                                    //  [3]: The distance between the face and the center of the
+                                    //       solid, along the normal
+                                    dVector4 SolidPlanes[3];
+                                    dVector3 tmp1;
+                                    dVector3 sn;
+
+                                    for (int j=0; j<3; j++) {
+                                        e1[j] = col_v[1][j] - col_v[0][j];
+                                        e2[j] = col_v[0][j] - col_v[2][j];
+                                        e3[j] = col_v[2][j] - col_v[1][j];
+                                    }
+                                    
+                                    // side 1
+                                    CROSS(sn, e1, n);
+                                    dNormalize3(sn);
+                                    SMULT( SolidPlanes[0], sn, -1.0 );
+                                    
+                                    ADD(tmp1, col_v[0], col_v[1]); 
+                                    SMULT(tmp1, tmp1, 0.5); // center of edge
+                                    // distance from center to edge along normal
+                                    SolidPlanes[0][3] = dDOT(tmp1, SolidPlanes[0]);
+                                    
+                                    
+                                    // side 2
+                                    CROSS(sn, e2, n);
+                                    dNormalize3(sn);
+                                    SMULT( SolidPlanes[1], sn, -1.0 );
+                                    
+                                    ADD(tmp1, col_v[0], col_v[2]); 
+                                    SMULT(tmp1, tmp1, 0.5); // center of edge
+                                    // distance from center to edge along normal
+                                    SolidPlanes[1][3] = dDOT(tmp1, SolidPlanes[1]);
+                                    
+                                    
+                                    // side 3
+                                    CROSS(sn, e3, n);
+                                    dNormalize3(sn);
+                                    SMULT( SolidPlanes[2], sn, -1.0 );
+                                    
+                                    ADD(tmp1, col_v[2], col_v[1]); 
+                                    SMULT(tmp1, tmp1, 0.5); // center of edge
+                                    // distance from center to edge along normal
+                                    SolidPlanes[2][3] = dDOT(tmp1, SolidPlanes[2]);
+                                    
+
+                                    FindTriSolidIntrsection(pen_v, SolidPlanes, 3, firstClippedTri);
+
+                                    for (int j=0; j<firstClippedTri.Count; j++) {
+                                        firstClippedTri.Points[j][3] = 1.0; // because we will be doing matrix mults
+
+                                        DEPTH(dp, CoplanarPt, firstClippedTri.Points[j], n);
+                                        
+                                        // if the penetration depth (calculated above) is more than the contact
+                                        //  point's ELT, then we've chosen the wrong face and should switch faces
+                                        if (pen_v == v1) {
+                                            dMultiply1(orig_pos, InvMatrix1, firstClippedTri.Points[j], 4, 4, 1);
+                                            dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
+                                            for (int k=0; k<3; k++) {
+                                                firstClippedElt[j][k] = (firstClippedTri.Points[j][k] - old_pos1[k]) - elt2[k];
+                                            }
+                                        }
+                                        else {
+                                            dMultiply1(orig_pos, InvMatrix2, firstClippedTri.Points[j], 4, 4, 1);
+                                            dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
+                                            for (int k=0; k<3; k++) {
+                                                firstClippedElt[j][k] = (firstClippedTri.Points[j][k] - old_pos2[k]) - elt1[k];
+                                            }
+                                        }
+
+                                        if (dp >= 0.0) {
+	                                        contact_elt_length = dFabs(dDOT(firstClippedElt[j], n));
+                                        
+                                            depth = dp;
+                                            if (depth == 0.0)
+                                                depth = dMin(DISTANCE_EPSILON, contact_elt_length);
+                                            
+                                            if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
+                                                depth = contact_elt_length;
+                                            
+                                            if (depth <= contact_elt_length) {
+                                                // Add a contact
+                                                GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                firstClippedTri.Points[j], n, depth, OutTriCount);
+                                                badPen = false;
+
+												if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+													break;
+												}
+                                            }
+                                        }
+
+                                    }
+                                }
+                                
+                                if (badPen) {
+                                    // Switch pen_v and n (again!)
+                                    SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
+                                    
+                                    
+                                    // Find the three sides (no top or bottom) of the solid created by 
+                                    //  the penetrated triangle.
+                                    // The dVector4 "plane" structures contain the following information:
+                                    //  [0]-[2]: The normal of the face, pointing INWARDS (i.e.
+                                    //           the inverse normal
+                                    //  [3]: The distance between the face and the center of the
+                                    //       solid, along the normal
+                                    dVector4 SolidPlanes[3];
+                                    dVector3 tmp1;
+                                
+                                    dVector3 sn;
+                                    for (int j=0; j<3; j++) {
+                                        e1[j] = col_v[1][j] - col_v[0][j];
+                                        e2[j] = col_v[0][j] - col_v[2][j];
+                                        e3[j] = col_v[2][j] - col_v[1][j];
+                                    }
+                                    
+                                    // side 1
+                                    CROSS(sn, e1, n);
+                                    dNormalize3(sn);
+                                    SMULT( SolidPlanes[0], sn, -1.0 );
+                                    
+                                    ADD(tmp1, col_v[0], col_v[1]); 
+                                    SMULT(tmp1, tmp1, 0.5); // center of edge
+                                    // distance from center to edge along normal
+                                    SolidPlanes[0][3] = dDOT(tmp1, SolidPlanes[0]);
+                                    
+                                    
+                                    // side 2
+                                    CROSS(sn, e2, n);
+                                    dNormalize3(sn);
+                                    SMULT( SolidPlanes[1], sn, -1.0 );
+                                    
+                                    ADD(tmp1, col_v[0], col_v[2]); 
+                                    SMULT(tmp1, tmp1, 0.5); // center of edge
+                                    // distance from center to edge along normal
+                                    SolidPlanes[1][3] = dDOT(tmp1, SolidPlanes[1]);
+                                    
+                                    
+                                    // side 3
+                                    CROSS(sn, e3, n);
+                                    dNormalize3(sn);
+                                    SMULT( SolidPlanes[2], sn, -1.0 );
+                                    
+                                    ADD(tmp1, col_v[2], col_v[1]); 
+                                    SMULT(tmp1, tmp1, 0.5); // center of edge
+                                    // distance from center to edge along normal
+                                    SolidPlanes[2][3] = dDOT(tmp1, SolidPlanes[2]);
+                                    
+                                    FindTriSolidIntrsection(pen_v, SolidPlanes, 3, secondClippedTri);
+                                    
+                                    for (int j=0; j<secondClippedTri.Count; j++) {
+                                        secondClippedTri.Points[j][3] = 1.0; // because we will be doing matrix mults
+                                        
+                                        DEPTH(dp, CoplanarPt, secondClippedTri.Points[j], n);
+                                        
+                                        if (pen_v == v1) {
+                                            dMultiply1(orig_pos, InvMatrix1, secondClippedTri.Points[j], 4, 4, 1);
+                                            dMultiply1(old_pos1, ((dxTriMesh*)g1)->last_trans, orig_pos, 4, 4, 1);
+                                            for (int k=0; k<3; k++) {
+                                                secondClippedElt[j][k] = (secondClippedTri.Points[j][k] - old_pos1[k]) - elt2[k];
+                                            }
+                                        }
+                                        else {
+                                            dMultiply1(orig_pos, InvMatrix2, secondClippedTri.Points[j], 4, 4, 1);
+                                            dMultiply1(old_pos2, ((dxTriMesh*)g2)->last_trans, orig_pos, 4, 4, 1);
+                                            for (int k=0; k<3; k++) {
+                                                secondClippedElt[j][k] = (secondClippedTri.Points[j][k] - old_pos2[k]) - elt1[k];
+                                            }
+                                        }
+
+
+                                        if (dp >= 0.0) {
+											contact_elt_length = dFabs(dDOT(secondClippedElt[j],n));
+											
+                                            depth = dp;
+                                            if (depth == 0.0)
+                                                depth = dMin(DISTANCE_EPSILON, contact_elt_length);
+                                            
+                                            if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
+                                                depth = contact_elt_length;
+                                            
+                                            if (depth <= contact_elt_length) {
+                                                // Add a contact
+                                                GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                secondClippedTri.Points[j], n, depth, OutTriCount);
+                                                badPen = false;
+
+												if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+													break;
+												}
+                                            }
+                                        }
+                                        
+                                        
+                                    }
+                                }
+
+
+                                
+                                /////////////////
+                                // All conventional tests have failed at this point, so now we deal with
+                                //  cases on a more "heuristic" basis
+                                //
+
+                                if (badPen) {
+                                    // Switch pen_v and n (for the fourth time, so they're
+                                    //  what my original guess said they were)
+                                    SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
+                                    
+									if (dFabs(dDOT(n1, n2)) < REAL(0.01)) {
+                                        // If we reach this point, we have (close to) perpindicular
+                                        //  faces, either resting on each other or sliding in a
+                                        // direction orthogonal to both surface normals.
+                                        if (LENGTH(elt_sum) < DISTANCE_EPSILON) {
+                                            depth = dFabs(dDOT(n, elt_sum));
+                                            
+                                            if (depth > REAL(1e-12)) {
+                                                dNormalize3(n);
+                                                GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                CoplanarPt, n, depth, OutTriCount);
+                                                badPen = false;
+                                            }
+                                            else {
+                                                // If the two faces are (nearly) perfectly at rest with
+                                                //  respect to each other, then we ignore the contact,
+                                                //  allowing the objects to slip a little in the hopes
+                                                //  that next frame, they'll give us something to work
+                                                //  with.
+                                                badPen = false;
+                                            }
+                                        }
+                                        else {
+                                            // The faces are perpindicular, but moving significantly
+                                            //  This can be sliding, or an unusual edge-straddling 
+                                            //  penetration.
+                                            dVector3 cn;
+                                            
+                                            CROSS(cn, n1, n2);
+                                            dNormalize3(cn);
+                                            SET(n, cn);
+                                            
+                                            // The shallowest ineterpenetration of the faces
+                                            //  is the depth
+                                            dVector3 ContactPt;
+                                            dVector3 dvTmp;
+                                            dReal    rTmp;
+                                            depth = dInfinity;
+                                            for (int j=0; j<3; j++) {
+                                                for (int k=0; k<3; k++) {
+                                                    SUB(dvTmp, col_v[k], pen_v[j]);
+                                                    
+                                                    rTmp = dDOT(dvTmp, n);
+                                                    if ( dFabs(rTmp) < dFabs(depth) ) {
+                                                        depth = rTmp;
+                                                        SET( ContactPt, pen_v[j] );
+                                                        contact_elt_length = dFabs(dDOT(pen_elt[j], n));
+                                                    }
+                                                }
+                                            }
+                                            if (depth < 0.0) {
+                                                SMULT(n, n, -1.0);
+                                                depth *= -1.0;
+                                            }
+                                            
+                                            if ((depth > 0.0) && (depth <= contact_elt_length)) {
+                                                GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                ContactPt, n, depth, OutTriCount);
+                                                badPen = false;
+                                            }
+                                            
+                                        }
+                                    }
+                                }
+                                
+
+                                if (badPen) {
+                                    // Use as the normal the direction of travel, rather than any particular
+                                    //  face normal
+                                    //
+                                    dVector3 esn;
+                                    
+                                    if (pen_v == v1) {
+                                        SMULT(esn, elt_sum, -1.0);
+                                    }
+                                    else {
+                                        SET(esn, elt_sum);
+                                    }
+                                    dNormalize3(esn);
+
+
+                                    // The shallowest ineterpenetration of the faces
+                                    //  is the depth
+                                    dVector3 ContactPt;
+                                    depth = dInfinity;
+                                    for (int j=0; j<3; j++) {
+                                        for (int k=0; k<3; k++) {
+                                            DEPTH(dp, col_v[k], pen_v[j], esn);
+                                            if ( (ExamineContactPoint(col_v, esn, pen_v[j])) &&
+                                                 ( dFabs(dp) < dFabs(depth)) ) {
+                                                depth = dp;
+                                                SET( ContactPt, pen_v[j] );
+                                                contact_elt_length = dFabs(dDOT(pen_elt[j], esn));
+                                            }
+                                        }
+                                    }
+                                    
+                                    if ((depth > 0.0) && (depth <= contact_elt_length)) {
+                                        GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                        ContactPt, esn, depth, OutTriCount);
+                                        badPen = false;
+                                    }
+                                }
+
+                                
+                                if (badPen) {
+                                    // If the direction of motion is perpindicular to both normals
+                                    if ( (dFabs(dDOT(n1, elt_sum)) < REAL(0.01)) && (dFabs(dDOT(n2, elt_sum)) < REAL(0.01)) ) {
+                                        dVector3 esn;
+                                        if (pen_v == v1) {
+                                            SMULT(esn, elt_sum, -1.0);
+                                        }
+                                        else {
+                                            SET(esn, elt_sum);
+                                        }
+                                        
+                                        dNormalize3(esn);
+
+                                        
+                                        // Look at the clipped points again, checking them against this
+                                        //  new normal
+                                        for (int j=0; j<firstClippedTri.Count; j++) {
+                                            DEPTH(dp, CoplanarPt, firstClippedTri.Points[j], esn);
+                                            
+                                            if (dp >= 0.0) {
+                                                contact_elt_length = dFabs(dDOT(firstClippedElt[j], esn));
+                                                
+                                                depth = dp;
+                                                //if (depth == 0.0)
+                                                //depth = dMin(DISTANCE_EPSILON, contact_elt_length);
+                                                
+                                                if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
+                                                    depth = contact_elt_length;
+                                                
+                                                if (depth <= contact_elt_length) {
+                                                    // Add a contact
+                                                    GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                    firstClippedTri.Points[j], esn, depth, OutTriCount);
+                                                    badPen = false;
+
+													if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+														break;
+													}
+                                                }
+                                            }
+                                        }
+                                        
+                                        if (badPen) {
+                                            // If this test failed, try it with the second set of clipped faces
+                                            for (int j=0; j<secondClippedTri.Count; j++) {
+                                                DEPTH(dp, CoplanarPt, secondClippedTri.Points[j], esn);
+                                                
+                                                if (dp >= 0.0) {
+                                                    contact_elt_length = dFabs(dDOT(secondClippedElt[j], esn));
+                                                    
+                                                    depth = dp;
+                                                    //if (depth == 0.0)
+                                                    //depth = dMin(DISTANCE_EPSILON, contact_elt_length);
+                                                    
+                                                    if ((contact_elt_length < SMALL_ELT) && (depth < EXPANDED_ELT_THRESH))
+                                                        depth = contact_elt_length;
+                                                    
+                                                    if (depth <= contact_elt_length) {
+                                                        // Add a contact
+                                                        GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                        secondClippedTri.Points[j], esn, depth, OutTriCount);
+                                                        badPen = false;
+
+														if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+															break;
+														}
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+
+
+                                
+                                if (badPen) {
+                                    // if we have very little motion, we're dealing with resting contact
+                                    //  and shouldn't reference the ELTs at all
+                                    //
+                                    if (LENGTH(elt_sum) < VELOCITY_EPSILON) {
+                                        
+                                        // instead of a "contact_elt_length" threshhold, we'll use an
+                                        //  arbitrary, small one
+                                        for (int j=0; j<3; j++) {
+                                            DEPTH(dp, CoplanarPt, pen_v[j], n);
+                                            
+                                            if (dp == 0.0)
+                                                dp = TINY_PENETRATION;
+                                            
+                                            if ( (dp > 0.0) && (dp <= SMALL_ELT)) {
+                                                // Add a contact
+                                                GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                pen_v[j], n, dp, OutTriCount);
+                                                badPen = false;
+
+												if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+													break;
+												}
+                                            }
+                                        }
+                                        
+
+                                        if (badPen) {
+                                            // try the other normal
+                                            SwapNormals(pen_v, col_v, v1, v2, pen_elt, elt_f1, elt_f2, n, n1, n2);
+
+                                            for (int j=0; j<3; j++) {
+                                                DEPTH(dp, CoplanarPt, pen_v[j], n);
+                                                
+                                                if (dp == 0.0)
+                                                    dp = TINY_PENETRATION;
+
+                                                if ( (dp > 0.0) && (dp <= SMALL_ELT)) {
+                                                    GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                                    pen_v[j], n, dp, OutTriCount);
+                                                    badPen = false;
+
+													if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+														break;
+													}
+                                                }
+                                            }
+                                        }
+                                        
+                                        
+
+                                    }
+                                }
+                                    
+                                if (badPen) {
+                                    // find the nearest existing contact, and replicate it's
+                                    //  normal and depth
+                                    //
+                                    dContactGeom*  Contact;
+                                    dVector3       pos_diff;
+                                    dReal          min_dist, dist;
+
+                                    min_dist = dInfinity;
+                                    depth = 0.0;
+                                    for (int j=0; j<OutTriCount; j++) {
+                                        Contact = SAFECONTACT(Flags, Contacts, j, Stride);
+                                        
+                                        SUB(pos_diff,  Contact->pos, CoplanarPt);
+
+                                        dist = dDOT(pos_diff, pos_diff);
+                                        if (dist < min_dist) {
+                                            min_dist = dist;
+                                            depth = Contact->depth;
+                                            SMULT(ContactNormal, Contact->normal, -1.0);
+                                        }
+                                    }
+                                 
+                                    if (depth > 0.0) {
+                                        // Add a tiny contact at the coplanar point
+                                        GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                        CoplanarPt, ContactNormal, depth, OutTriCount);
+                                        badPen = false;
+                                    }
+                                }
+
+
+                                if (badPen) {
+                                    // Add a tiny contact at the coplanar point                                    
+                                    if (-dDOT(elt_sum, n1) > -dDOT(elt_sum, n2)) {
+                                        SET(ContactNormal, n1);
+                                    }
+                                    else {
+                                        SET(ContactNormal, n2);
+                                    }
+
+                                    GenerateContact(Flags, Contacts, Stride,  TriMesh1,  TriMesh2,
+                                                    CoplanarPt, ContactNormal, TINY_PENETRATION, OutTriCount);
+                                    badPen = false;
+                                }
+
+                                
+                            } // not coplanar (main loop)
+                        } // TriTriIntersectWithIsectLine
+                
+						if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT))) {
+							break;
+						}
+              }
+
+				// Free memory
+				delete[] firstClippedElt;
+				delete[] secondClippedElt;	
+
+			  // Return the number of contacts
+                return OutTriCount; 
+            }
+        }
+    }
+
+    
+    // There was some kind of failure during the Collide call or
+    // there are no faces overlapping
+    return 0;    
+}
+
+
+
+static void
+GetTriangleGeometryCallback(udword triangleindex, VertexPointers& triangle, udword user_data)
+{
+    dVector3 Out[3];
+
+    FetchTriangle((dxTriMesh*) user_data, (int) triangleindex, Out);
+
+    for (int i = 0; i < 3; i++)
+        triangle.Vertex[i] =  (const Point*) ((dReal*) Out[i]);
+}
+
+
+//
+//
+//
+#define B11   B[0]
+#define B12   B[1]
+#define B13   B[2]
+#define B14   B[3]
+#define B21   B[4]
+#define B22   B[5]
+#define B23   B[6]
+#define B24   B[7]
+#define B31   B[8]
+#define B32   B[9]
+#define B33   B[10]
+#define B34   B[11]
+#define B41   B[12]
+#define B42   B[13]
+#define B43   B[14]
+#define B44   B[15]
+
+#define Binv11   Binv[0]
+#define Binv12   Binv[1]
+#define Binv13   Binv[2]
+#define Binv14   Binv[3]
+#define Binv21   Binv[4]
+#define Binv22   Binv[5]
+#define Binv23   Binv[6]
+#define Binv24   Binv[7]
+#define Binv31   Binv[8]
+#define Binv32   Binv[9]
+#define Binv33   Binv[10]
+#define Binv34   Binv[11]
+#define Binv41   Binv[12]
+#define Binv42   Binv[13]
+#define Binv43   Binv[14]
+#define Binv44   Binv[15]
+
+inline void
+dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B)
+{
+	B11 = Rotation[0]; B21 = Rotation[1]; B31 = Rotation[2];    B41 = Position[0]; 
+	B12 = Rotation[4]; B22 = Rotation[5]; B32 = Rotation[6];    B42 = Position[1];
+	B13 = Rotation[8]; B23 = Rotation[9]; B33 = Rotation[10];   B43 = Position[2];
+
+    B14 = 0.0;         B24 = 0.0;         B34 = 0.0;            B44 = 1.0;
+}
+
+
+static void
+dInvertMatrix4( dMatrix4& B, dMatrix4& Binv )
+{
+    dReal det =  (B11 * B22 - B12 * B21) * (B33 * B44 - B34 * B43)
+        -(B11 * B23 - B13 * B21) * (B32 * B44 - B34 * B42)
+        +(B11 * B24 - B14 * B21) * (B32 * B43 - B33 * B42)
+        +(B12 * B23 - B13 * B22) * (B31 * B44 - B34 * B41)
+        -(B12 * B24 - B14 * B22) * (B31 * B43 - B33 * B41)
+        +(B13 * B24 - B14 * B23) * (B31 * B42 - B32 * B41);
+    
+    dAASSERT (det != 0.0);    
+    
+    det = 1.0 / det;
+
+    Binv11 = (dReal) (det * ((B22 * B33) - (B23 * B32)));
+    Binv12 = (dReal) (det * ((B32 * B13) - (B33 * B12)));
+    Binv13 = (dReal) (det * ((B12 * B23) - (B13 * B22)));
+    Binv14 = 0.0f;
+    Binv21 = (dReal) (det * ((B23 * B31) - (B21 * B33)));
+    Binv22 = (dReal) (det * ((B33 * B11) - (B31 * B13)));
+    Binv23 = (dReal) (det * ((B13 * B21) - (B11 * B23)));
+    Binv24 = 0.0f;
+    Binv31 = (dReal) (det * ((B21 * B32) - (B22 * B31)));
+    Binv32 = (dReal) (det * ((B31 * B12) - (B32 * B11)));
+    Binv33 = (dReal) (det * ((B11 * B22) - (B12 * B21)));
+    Binv34 = 0.0f;
+    Binv41 = (dReal) (det * (B21*(B33*B42 - B32*B43) + B22*(B31*B43 - B33*B41) + B23*(B32*B41 - B31*B42)));
+    Binv42 = (dReal) (det * (B31*(B13*B42 - B12*B43) + B32*(B11*B43 - B13*B41) + B33*(B12*B41 - B11*B42)));
+    Binv43 = (dReal) (det * (B41*(B13*B22 - B12*B23) + B42*(B11*B23 - B13*B21) + B43*(B12*B21 - B11*B22)));
+    Binv44 = 1.0f;
+}
+
+
+
+/////////////////////////////////////////////////
+//
+// Triangle/Triangle intersection utilities
+//
+// From the article "A Fast Triangle-Triangle Intersection Test",
+// Journal of Graphics Tools, 2(2), 1997
+//
+// Some of this functionality is duplicated in OPCODE (see
+//  OPC_TriTriOverlap.h) but we have replicated it here so we don't
+//  have to mess with the internals of OPCODE, as well as so we can
+//  further optimize some of the functions.
+// 
+//  This version computes the line of intersection as well (if they
+//  are not coplanar):
+//  int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3], 
+//                                   dReal U0[3],dReal U1[3],dReal U2[3],
+//                                   int *coplanar,
+//                                   dReal isectpt1[3],dReal isectpt2[3]);
+//
+//  parameters: vertices of triangle 1: V0,V1,V2
+//              vertices of triangle 2: U0,U1,U2
+//
+//  result    : returns 1 if the triangles intersect, otherwise 0
+//              "coplanar" returns whether the tris are coplanar
+//              isectpt1, isectpt2 are the endpoints of the line of
+//              intersection
+// 
+
+
+
+/* if USE_EPSILON_TEST is true then we do a check: 
+         if |dv|<EPSILON then dv=0.0;
+   else no check is done (which is less robust)
+*/
+#define USE_EPSILON_TEST TRUE  
+#define EPSILON REAL(0.000001)
+
+
+/* sort so that a<=b */
+#define SORT(a,b)       \
+             if(a>b)    \
+             {          \
+               dReal c; \
+               c=a;     \
+               a=b;     \
+               b=c;     \
+             }
+
+#define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1) \
+              isect0=VV0+(VV1-VV0)*D0/(D0-D1);    \
+              isect1=VV0+(VV2-VV0)*D0/(D0-D2);
+
+
+#define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1) \
+  if(D0D1>0.0f)                                         \
+  {                                                     \
+    /* here we know that D0D2<=0.0 */                   \
+    /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
+    ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1);          \
+  }                                                     \
+  else if(D0D2>0.0f)                                    \
+  {                                                     \
+    /* here we know that d0d1<=0.0 */                   \
+    ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1);          \
+  }                                                     \
+  else if(D1*D2>0.0f || D0!=0.0f)                       \
+  {                                                     \
+    /* here we know that d0d1<=0.0 or that D0!=0.0 */   \
+    ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1);          \
+  }                                                     \
+  else if(D1!=0.0f)                                     \
+  {                                                     \
+    ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1);          \
+  }                                                     \
+  else if(D2!=0.0f)                                     \
+  {                                                     \
+    ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1);          \
+  }                                                     \
+  else                                                  \
+  {                                                     \
+    /* triangles are coplanar */                        \
+    return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);      \
+  }
+
+
+
+/* this edge to edge test is based on Franlin Antonio's gem:
+   "Faster Line Segment Intersection", in Graphics Gems III,
+   pp. 199-202 */ 
+#define EDGE_EDGE_TEST(V0,U0,U1)                      \
+  Bx=U0[i0]-U1[i0];                                   \
+  By=U0[i1]-U1[i1];                                   \
+  Cx=V0[i0]-U0[i0];                                   \
+  Cy=V0[i1]-U0[i1];                                   \
+  f=Ay*Bx-Ax*By;                                      \
+  d=By*Cx-Bx*Cy;                                      \
+  if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f))  \
+  {                                                   \
+    e=Ax*Cy-Ay*Cx;                                    \
+    if(f>0)                                           \
+    {                                                 \
+      if(e>=0 && e<=f) return 1;                      \
+    }                                                 \
+    else                                              \
+    {                                                 \
+      if(e<=0 && e>=f) return 1;                      \
+    }                                                 \
+  }                                
+
+#define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
+{                                              \
+  dReal Ax,Ay,Bx,By,Cx,Cy,e,d,f;               \
+  Ax=V1[i0]-V0[i0];                            \
+  Ay=V1[i1]-V0[i1];                            \
+  /* test edge U0,U1 against V0,V1 */          \
+  EDGE_EDGE_TEST(V0,U0,U1);                    \
+  /* test edge U1,U2 against V0,V1 */          \
+  EDGE_EDGE_TEST(V0,U1,U2);                    \
+  /* test edge U2,U1 against V0,V1 */          \
+  EDGE_EDGE_TEST(V0,U2,U0);                    \
+}
+
+#define POINT_IN_TRI(V0,U0,U1,U2)           \
+{                                           \
+  dReal a,b,c,d0,d1,d2;                     \
+  /* is T1 completly inside T2? */          \
+  /* check if V0 is inside tri(U0,U1,U2) */ \
+  a=U1[i1]-U0[i1];                          \
+  b=-(U1[i0]-U0[i0]);                       \
+  c=-a*U0[i0]-b*U0[i1];                     \
+  d0=a*V0[i0]+b*V0[i1]+c;                   \
+                                            \
+  a=U2[i1]-U1[i1];                          \
+  b=-(U2[i0]-U1[i0]);                       \
+  c=-a*U1[i0]-b*U1[i1];                     \
+  d1=a*V0[i0]+b*V0[i1]+c;                   \
+                                            \
+  a=U0[i1]-U2[i1];                          \
+  b=-(U0[i0]-U2[i0]);                       \
+  c=-a*U2[i0]-b*U2[i1];                     \
+  d2=a*V0[i0]+b*V0[i1]+c;                   \
+  if(d0*d1>0.0)                             \
+  {                                         \
+    if(d0*d2>0.0) return 1;                 \
+  }                                         \
+}
+
+int coplanar_tri_tri(dReal N[3],dReal V0[3],dReal V1[3],dReal V2[3],
+                     dReal U0[3],dReal U1[3],dReal U2[3])
+{
+   dReal A[3];
+   short i0,i1;
+   /* first project onto an axis-aligned plane, that maximizes the area */
+   /* of the triangles, compute indices: i0,i1. */
+   A[0]= dFabs(N[0]);
+   A[1]= dFabs(N[1]);
+   A[2]= dFabs(N[2]);
+   if(A[0]>A[1])
+   {
+      if(A[0]>A[2])  
+      {
+          i0=1;      /* A[0] is greatest */
+          i1=2;
+      }
+      else
+      {
+          i0=0;      /* A[2] is greatest */
+          i1=1;
+      }
+   }
+   else   /* A[0]<=A[1] */
+   {
+      if(A[2]>A[1])
+      {
+          i0=0;      /* A[2] is greatest */
+          i1=1;                                           
+      }
+      else
+      {
+          i0=0;      /* A[1] is greatest */
+          i1=2;
+      }
+    }               
+                
+    /* test all edges of triangle 1 against the edges of triangle 2 */
+    EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
+    EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
+    EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
+                
+    /* finally, test if tri1 is totally contained in tri2 or vice versa */
+    POINT_IN_TRI(V0,U0,U1,U2);
+    POINT_IN_TRI(U0,V0,V1,V2);
+
+    return 0;
+}
+
+
+
+#define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
+{ \
+        if(D0D1>0.0f) \
+        { \
+                /* here we know that D0D2<=0.0 */ \
+            /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
+                A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
+        } \
+        else if(D0D2>0.0f)\
+        { \
+                /* here we know that d0d1<=0.0 */ \
+            A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
+        } \
+        else if(D1*D2>0.0f || D0!=0.0f) \
+        { \
+                /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
+                A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
+        } \
+        else if(D1!=0.0f) \
+        { \
+                A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
+        } \
+        else if(D2!=0.0f) \
+        { \
+                A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
+        } \
+        else \
+        { \
+                /* triangles are coplanar */ \
+                return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
+        } \
+}
+
+
+
+
+/* sort so that a<=b */
+#define SORT2(a,b,smallest)       \
+             if(a>b)       \
+             {             \
+               dReal c;    \
+               c=a;        \
+               a=b;        \
+               b=c;        \
+               smallest=1; \
+             }             \
+             else smallest=0;
+
+
+inline void isect2(dReal VTX0[3],dReal VTX1[3],dReal VTX2[3],dReal VV0,dReal VV1,dReal VV2,
+        dReal D0,dReal D1,dReal D2,dReal *isect0,dReal *isect1,dReal isectpoint0[3],dReal isectpoint1[3]) 
+{
+  dReal tmp=D0/(D0-D1);          
+  dReal diff[3];
+  *isect0=VV0+(VV1-VV0)*tmp;         
+  SUB(diff,VTX1,VTX0);              
+  MULT(diff,diff,tmp);               
+  ADD(isectpoint0,diff,VTX0);        
+  tmp=D0/(D0-D2);                    
+  *isect1=VV0+(VV2-VV0)*tmp;          
+  SUB(diff,VTX2,VTX0);                   
+  MULT(diff,diff,tmp);                 
+  ADD(isectpoint1,VTX0,diff);          
+}
+
+
+#if 0
+#define ISECT2(VTX0,VTX1,VTX2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1) \
+              tmp=D0/(D0-D1);                \
+              isect0=VV0+(VV1-VV0)*tmp;      \
+          SUB(diff,VTX1,VTX0);               \
+          MULT(diff,diff,tmp);               \
+              ADD(isectpoint0,diff,VTX0);    \
+              tmp=D0/(D0-D2);
+/*              isect1=VV0+(VV2-VV0)*tmp;          \ */
+/*              SUB(diff,VTX2,VTX0);               \ */
+/*              MULT(diff,diff,tmp);               \ */
+/*              ADD(isectpoint1,VTX0,diff);          */
+#endif
+
+inline int compute_intervals_isectline(dReal VERT0[3],dReal VERT1[3],dReal VERT2[3],
+                       dReal VV0,dReal VV1,dReal VV2,dReal D0,dReal D1,dReal D2,
+                       dReal D0D1,dReal D0D2,dReal *isect0,dReal *isect1,
+                       dReal isectpoint0[3],dReal isectpoint1[3])
+{
+  if(D0D1>0.0f)                                        
+  {                                                    
+    /* here we know that D0D2<=0.0 */                  
+    /* that is D0, D1 are on the same side, D2 on the other or on the plane */
+    isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);
+  } 
+  else if(D0D2>0.0f)                                   
+    {                                                   
+    /* here we know that d0d1<=0.0 */             
+    isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1);
+  }                                                  
+  else if(D1*D2>0.0f || D0!=0.0f)   
+  {                                   
+    /* here we know that d0d1<=0.0 or that D0!=0.0 */
+    isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1);   
+  }                                                  
+  else if(D1!=0.0f)                                  
+  {                                               
+    isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1); 
+  }                                         
+  else if(D2!=0.0f)                                  
+  {                                                   
+    isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1);     
+  }                                                 
+  else                                               
+  {                                                   
+    /* triangles are coplanar */    
+    return 1;
+  }
+  return 0;
+}
+
+#define COMPUTE_INTERVALS_ISECTLINE(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1,isectpoint0,isectpoint1) \
+  if(D0D1>0.0f)                                         \
+  {                                                     \
+    /* here we know that D0D2<=0.0 */                   \
+    /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
+    isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1);          \
+  }                                                     
+#if 0
+  else if(D0D2>0.0f)                                    \
+  {                                                     \
+    /* here we know that d0d1<=0.0 */                   \
+    isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1);          \
+  }                                                     \
+  else if(D1*D2>0.0f || D0!=0.0f)                       \
+  {                                                     \
+    /* here we know that d0d1<=0.0 or that D0!=0.0 */   \
+    isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,&isect0,&isect1,isectpoint0,isectpoint1);          \
+  }                                                     \
+  else if(D1!=0.0f)                                     \
+  {                                                     \
+    isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1);          \
+  }                                                     \
+  else if(D2!=0.0f)                                     \
+  {                                                     \
+    isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1);          \
+  }                                                     \
+  else                                                  \
+  {                                                     \
+    /* triangles are coplanar */                        \
+    coplanar=1;                                         \
+    return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);      \
+  }
+#endif
+
+
+
+static int TriTriIntersectWithIsectLine(dReal V0[3],dReal V1[3],dReal V2[3],
+                                        dReal U0[3],dReal U1[3],dReal U2[3],int *coplanar,
+                                        dReal isectpt1[3],dReal isectpt2[3])
+{
+  dReal E1[3],E2[3];
+  dReal N1[3],N2[3],d1,d2;
+  dReal du0,du1,du2,dv0,dv1,dv2;
+  dReal D[3];
+  dReal isect1[2], isect2[2];
+  dReal isectpointA1[3],isectpointA2[3];
+  dReal isectpointB1[3],isectpointB2[3];
+  dReal du0du1,du0du2,dv0dv1,dv0dv2;
+  short index;
+  dReal vp0,vp1,vp2;
+  dReal up0,up1,up2;
+  dReal b,c,max;
+  int smallest1,smallest2;
+  
+  /* compute plane equation of triangle(V0,V1,V2) */
+  SUB(E1,V1,V0);
+  SUB(E2,V2,V0);
+  CROSS(N1,E1,E2);
+  d1=-DOT(N1,V0);
+  /* plane equation 1: N1.X+d1=0 */
+
+  /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/
+  du0=DOT(N1,U0)+d1;
+  du1=DOT(N1,U1)+d1;
+  du2=DOT(N1,U2)+d1;
+
+  /* coplanarity robustness check */
+#if USE_EPSILON_TEST==TRUE
+  if(dFabs(du0)<EPSILON) du0=0.0;
+  if(dFabs(du1)<EPSILON) du1=0.0;
+  if(dFabs(du2)<EPSILON) du2=0.0;
+#endif
+  du0du1=du0*du1;
+  du0du2=du0*du2;
+
+  if(du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */
+    return 0;                    /* no intersection occurs */
+
+  /* compute plane of triangle (U0,U1,U2) */
+  SUB(E1,U1,U0);
+  SUB(E2,U2,U0);
+  CROSS(N2,E1,E2);
+  d2=-DOT(N2,U0);
+  /* plane equation 2: N2.X+d2=0 */
+
+  /* put V0,V1,V2 into plane equation 2 */
+  dv0=DOT(N2,V0)+d2;
+  dv1=DOT(N2,V1)+d2;
+  dv2=DOT(N2,V2)+d2;
+
+#if USE_EPSILON_TEST==TRUE
+  if(dFabs(dv0)<EPSILON) dv0=0.0;
+  if(dFabs(dv1)<EPSILON) dv1=0.0;
+  if(dFabs(dv2)<EPSILON) dv2=0.0;
+#endif
+
+  dv0dv1=dv0*dv1;
+  dv0dv2=dv0*dv2;
+        
+  if(dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
+    return 0;                    /* no intersection occurs */
+
+  /* compute direction of intersection line */
+  CROSS(D,N1,N2);
+
+  /* compute and index to the largest component of D */
+  max= dFabs(D[0]);
+  index=0;
+  b= dFabs(D[1]);
+  c= dFabs(D[2]);
+  if(b>max) max=b,index=1;
+  if(c>max) max=c,index=2;
+
+  /* this is the simplified projection onto L*/
+  vp0=V0[index];
+  vp1=V1[index];
+  vp2=V2[index];
+  
+  up0=U0[index];
+  up1=U1[index];
+  up2=U2[index];
+
+  /* compute interval for triangle 1 */
+  *coplanar=compute_intervals_isectline(V0,V1,V2,vp0,vp1,vp2,dv0,dv1,dv2,
+                                        dv0dv1,dv0dv2,&isect1[0],&isect1[1],isectpointA1,isectpointA2);
+  if(*coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);     
+
+
+  /* compute interval for triangle 2 */
+  compute_intervals_isectline(U0,U1,U2,up0,up1,up2,du0,du1,du2,
+                              du0du1,du0du2,&isect2[0],&isect2[1],isectpointB1,isectpointB2);
+
+  SORT2(isect1[0],isect1[1],smallest1);
+  SORT2(isect2[0],isect2[1],smallest2);
+
+  if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
+
+  /* at this point, we know that the triangles intersect */
+
+  if(isect2[0]<isect1[0])
+  {
+    if(smallest1==0) { SET(isectpt1,isectpointA1); }
+    else { SET(isectpt1,isectpointA2); }
+
+    if(isect2[1]<isect1[1])
+    {
+      if(smallest2==0) { SET(isectpt2,isectpointB2); }
+      else { SET(isectpt2,isectpointB1); }
+    }
+    else
+    {
+      if(smallest1==0) { SET(isectpt2,isectpointA2); }
+      else { SET(isectpt2,isectpointA1); }
+    }
+  }
+  else
+  {
+    if(smallest2==0) { SET(isectpt1,isectpointB1); }
+    else { SET(isectpt1,isectpointB2); }
+
+    if(isect2[1]>isect1[1])
+    {
+      if(smallest1==0) { SET(isectpt2,isectpointA2); }
+      else { SET(isectpt2,isectpointA1); }      
+    }
+    else
+    {
+      if(smallest2==0) { SET(isectpt2,isectpointB2); }
+      else { SET(isectpt2,isectpointB1); } 
+    }
+  }
+  return 1;
+}
+
+
+
+
+
+// Find the intersectiojn point between a coplanar line segement,
+// defined by X1 and X2, and a ray defined by X3 and direction N.
+//
+// This forumla for this calculation is:
+//               (c x b) . (a x b)
+//   Q = x1 + a -------------------
+//                  | a x b | ^2
+//
+// where a = x2 - x1
+//       b = x4 - x3
+//       c = x3 - x1
+// x1 and x2 are the edges of the triangle, and x3 is CoplanarPt
+//  and x4 is (CoplanarPt - n)
+static int
+IntersectLineSegmentRay(dVector3 x1, dVector3 x2, dVector3 x3, dVector3 n, 
+                        dVector3 out_pt)
+{
+    dVector3 a, b, c, x4;
+
+    ADD(x4, x3, n);  // x4 = x3 + n
+    
+    SUB(a, x2, x1);  // a = x2 - x1
+    SUB(b, x4, x3);
+    SUB(c, x3, x1);
+    
+    dVector3 tmp1, tmp2;
+    CROSS(tmp1, c, b);
+    CROSS(tmp2, a, b);
+
+    dReal num, denom;
+    num = dDOT(tmp1, tmp2);
+    denom = LENGTH( tmp2 ); 
+
+    dReal s;
+    s = num /(denom*denom);
+    
+    for (int i=0; i<3; i++)
+        out_pt[i] = x1[i] + a[i]*s;
+
+    // Test if this intersection is "behind" x3, w.r.t. n
+    SUB(a, x3, out_pt);
+    if (dDOT(a, n) > 0.0)
+        return 0;
+
+    // Test if this intersection point is outside the edge limits,
+    //  if (dot( (out_pt-x1), (out_pt-x2) ) < 0) it's inside
+    //  else outside
+    SUB(a, out_pt, x1);
+    SUB(b, out_pt, x2);
+    if (dDOT(a,b) < 0.0)
+        return 1;
+    else
+        return 0;
+}
+
+
+// FindTriSolidIntersection - Clips the input trinagle TRI with the 
+//  sides of a convex bounding solid, described by PLANES, returning
+//  the (convex) clipped polygon in CLIPPEDPOLYGON
+//
+static bool
+FindTriSolidIntrsection(const dVector3 Tri[3], 
+                        const dVector4 Planes[6], int numSides,
+                        LineContactSet& ClippedPolygon )
+{ 
+    // Set up the LineContactSet structure
+    for (int k=0; k<3; k++) {
+        SET(ClippedPolygon.Points[k], Tri[k]);
+    }
+    ClippedPolygon.Count = 3;
+
+    // Clip wrt the sides
+    for ( int i = 0; i < numSides; i++ )
+        ClipConvexPolygonAgainstPlane( Planes[i], Planes[i][3], ClippedPolygon );
+    
+    return (ClippedPolygon.Count > 0);
+}
+
+
+
+
+// ClipConvexPolygonAgainstPlane - Clip a a convex polygon, described by
+//  CONTACTS, with a plane (described by N and C).  Note:  the input 
+//  vertices are assumed to be in counterclockwise order.  
+//
+// This code is taken from The Nebula Device:
+//  http://nebuladevice.sourceforge.net/cgi-bin/twiki/view/Nebula/WebHome
+// and is licensed under the following license:
+//  http://nebuladevice.sourceforge.net/doc/source/license.txt
+//
+static void
+ClipConvexPolygonAgainstPlane( const dVector3 N, dReal C, 
+                               LineContactSet& Contacts )
+{
+    // test on which side of line are the vertices
+    int Positive = 0, Negative = 0, PIndex = -1;
+    int Quantity = Contacts.Count;
+    
+    dReal Test[8];
+    for ( int i = 0; i < Contacts.Count; i++ ) {
+        // An epsilon is used here because it is possible for the dot product
+        // and C to be exactly equal to each other (in theory), but differ
+        // slightly because of floating point problems.  Thus, add a little
+        // to the test number to push actually equal numbers over the edge
+        // towards the positive.  This should probably be somehow a relative
+        // tolerance, and I don't think multiplying by the constant is the best
+        // way to do this.
+        Test[i] = dDOT(N, Contacts.Points[i]) - C + dFabs(C)*REAL(1e-08);
+            
+        if (Test[i] >= REAL(0.0)) {
+            Positive++;
+            if (PIndex < 0) {
+                PIndex = i;
+            }
+        }
+        else Negative++;
+    }
+    
+    if (Positive > 0) {
+        if (Negative > 0) {
+            // plane transversely intersects polygon
+            dVector3 CV[8];
+            int CQuantity = 0, Cur, Prv;
+            dReal T;
+            
+            if (PIndex > 0) {
+                // first clip vertex on line
+                Cur = PIndex;
+                Prv = Cur - 1;
+                T = Test[Cur] / (Test[Cur] - Test[Prv]);
+                CV[CQuantity][0] = Contacts.Points[Cur][0] 
+                    + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
+                CV[CQuantity][1] = Contacts.Points[Cur][1] 
+                    + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
+                CV[CQuantity][2] = Contacts.Points[Cur][2] 
+                    + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
+                CV[CQuantity][3] = Contacts.Points[Cur][3] 
+                    + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
+                CQuantity++;
+                
+                // vertices on positive side of line
+                while (Cur < Quantity && Test[Cur] >= REAL(0.0)) {
+                    CV[CQuantity][0] = Contacts.Points[Cur][0];
+                    CV[CQuantity][1] = Contacts.Points[Cur][1];
+                    CV[CQuantity][2] = Contacts.Points[Cur][2];
+                    CV[CQuantity][3] = Contacts.Points[Cur][3];
+                    CQuantity++;
+                    Cur++;
+                }
+                
+                // last clip vertex on line
+                if (Cur < Quantity) {
+                    Prv = Cur - 1;
+                }
+                else {
+                    Cur = 0;
+                    Prv = Quantity - 1;
+                }
+                
+                T = Test[Cur] / (Test[Cur] - Test[Prv]);
+                CV[CQuantity][0] = Contacts.Points[Cur][0] 
+                    + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
+                CV[CQuantity][1] = Contacts.Points[Cur][1] 
+                    + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
+                CV[CQuantity][2] = Contacts.Points[Cur][2] 
+                    + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
+                CV[CQuantity][3] = Contacts.Points[Cur][3] 
+                    + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
+                CQuantity++;
+            }
+            else {
+                // iPIndex is 0
+                // vertices on positive side of line
+                Cur = 0;
+                while (Cur < Quantity && Test[Cur] >= REAL(0.0)) {
+                    CV[CQuantity][0] = Contacts.Points[Cur][0];
+                    CV[CQuantity][1] = Contacts.Points[Cur][1];
+                    CV[CQuantity][2] = Contacts.Points[Cur][2];
+                    CV[CQuantity][3] = Contacts.Points[Cur][3];
+                    CQuantity++;
+                    Cur++;
+                }
+                
+                // last clip vertex on line
+                Prv = Cur - 1;
+                T = Test[Cur] / (Test[Cur] - Test[Prv]);
+                CV[CQuantity][0] = Contacts.Points[Cur][0] 
+                    + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
+                CV[CQuantity][1] = Contacts.Points[Cur][1] 
+                    + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
+                CV[CQuantity][2] = Contacts.Points[Cur][2] 
+                    + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
+                CV[CQuantity][3] = Contacts.Points[Cur][3] 
+                    + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
+                CQuantity++;
+                
+                // skip vertices on negative side
+                while (Cur < Quantity && Test[Cur] < REAL(0.0)) {
+                    Cur++;
+                }
+          
+                // first clip vertex on line
+                if (Cur < Quantity) {
+                    Prv = Cur - 1;
+                    T = Test[Cur] / (Test[Cur] - Test[Prv]);
+                    CV[CQuantity][0] = Contacts.Points[Cur][0] 
+                        + T * (Contacts.Points[Prv][0] - Contacts.Points[Cur][0]);
+                    CV[CQuantity][1] = Contacts.Points[Cur][1] 
+                              + T * (Contacts.Points[Prv][1] - Contacts.Points[Cur][1]);
+                    CV[CQuantity][2] = Contacts.Points[Cur][2] 
+                        + T * (Contacts.Points[Prv][2] - Contacts.Points[Cur][2]);
+                    CV[CQuantity][3] = Contacts.Points[Cur][3] 
+                        + T * (Contacts.Points[Prv][3] - Contacts.Points[Cur][3]);
+                    CQuantity++;
+            
+                    // vertices on positive side of line
+                    while (Cur < Quantity && Test[Cur] >= REAL(0.0)) {
+                        CV[CQuantity][0] = Contacts.Points[Cur][0];
+                        CV[CQuantity][1] = Contacts.Points[Cur][1];
+                        CV[CQuantity][2] = Contacts.Points[Cur][2];
+                        CV[CQuantity][3] = Contacts.Points[Cur][3];
+                        CQuantity++;
+                        Cur++;
+                    }
+                }
+                else {
+                    // iCur = 0
+                    Prv = Quantity - 1;
+                    T = Test[0] / (Test[0] - Test[Prv]);
+                    CV[CQuantity][0] = Contacts.Points[0][0] 
+                        + T * (Contacts.Points[Prv][0] - Contacts.Points[0][0]);
+                    CV[CQuantity][1] = Contacts.Points[0][1] 
+                              + T * (Contacts.Points[Prv][1] - Contacts.Points[0][1]);
+                    CV[CQuantity][2] = Contacts.Points[0][2] 
+                        + T * (Contacts.Points[Prv][2] - Contacts.Points[0][2]);
+                    CV[CQuantity][3] = Contacts.Points[0][3] 
+                        + T * (Contacts.Points[Prv][3] - Contacts.Points[0][3]);
+                    CQuantity++;
+                }
+            }
+            Quantity = CQuantity;
+            memcpy( Contacts.Points, CV, CQuantity * sizeof(dVector3) );
+        }
+        // else polygon fully on positive side of plane, nothing to do    
+        Contacts.Count = Quantity;
+    }
+    else {
+        Contacts.Count = 0; // This should not happen, but for safety
+    }
+
+}
+
+
+
+// Determine if a potential collision point is 
+//
+//
+static int
+ExamineContactPoint(dVector3* v_col, dVector3 in_n, dVector3 in_point)
+{
+    // Cast a ray from in_point, along the collison normal. Does it intersect the
+    //  collision face.
+    dReal t, u, v;
+    
+    if (!RayTriangleIntersect(in_point, in_n, v_col[0], v_col[1], v_col[2],
+                              &t, &u, &v))
+        return 0;
+    else
+    return 1;
+}
+
+
+
+// RayTriangleIntersect - If an intersection is found, t contains the
+//   distance along the ray (dir) and u/v contain u/v coordinates into
+//   the triangle.  Returns 0 if no hit is found
+//   From "Real-Time Rendering," page 305
+//
+static int
+RayTriangleIntersect(const dVector3 orig, const dVector3 dir,
+                     const dVector3 vert0, const dVector3 vert1,const dVector3 vert2,
+                     dReal *t,dReal *u,dReal *v)
+
+{
+    dReal edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
+    dReal det,inv_det;
+    
+    // find vectors for two edges sharing vert0
+    SUB(edge1, vert1, vert0);
+    SUB(edge2, vert2, vert0);
+    
+    // begin calculating determinant - also used to calculate U parameter
+    CROSS(pvec, dir, edge2);
+
+    // if determinant is near zero, ray lies in plane of triangle
+    det = DOT(edge1, pvec);
+
+    if ((det > REAL(-0.001)) && (det < REAL(0.001)))
+        return 0;
+    inv_det = 1.0 / det;
+
+    // calculate distance from vert0 to ray origin 
+    SUB(tvec, orig, vert0);
+
+    // calculate U parameter and test bounds
+    *u = DOT(tvec, pvec) * inv_det;
+    if ((*u < 0.0) || (*u > 1.0))
+        return 0;
+
+    // prepare to test V parameter
+    CROSS(qvec, tvec, edge1);
+
+    // calculate V parameter and test bounds
+    *v = DOT(dir, qvec) * inv_det;
+    if ((*v < 0.0) || ((*u + *v) > 1.0))
+        return 0;
+
+    // calculate t, ray intersects triangle
+    *t = DOT(edge2, qvec) * inv_det;
+
+    return 1;
+}
+
+
+
+static bool
+SimpleUnclippedTest(dVector3 in_CoplanarPt, dVector3 in_v, dVector3 in_elt,
+                    dVector3 in_n, dVector3* in_col_v, dReal &out_depth)
+{
+    dReal dp = 0.0;
+    dReal contact_elt_length;
+
+    DEPTH(dp, in_CoplanarPt, in_v, in_n);
+    
+    if (dp >= 0.0) {
+        // if the penetration depth (calculated above) is more than
+        //  the contact point's ELT, then we've chosen the wrong face
+        //  and should switch faces
+        contact_elt_length = dFabs(dDOT(in_elt, in_n));
+        
+        if (dp == 0.0)
+            dp = dMin(DISTANCE_EPSILON, contact_elt_length);
+        
+        if ((contact_elt_length < SMALL_ELT) && (dp < EXPANDED_ELT_THRESH))
+            dp = contact_elt_length;
+        
+        if ( (dp > 0.0) && (dp <= contact_elt_length)) {
+            // Add a contact
+            
+            if ( ExamineContactPoint(in_col_v, in_n, in_v) ) {
+                out_depth = dp;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+
+
+
+// Generate a "unique" contact.  A unique contact has a unique
+//   position or normal.  If the potential contact has the same
+//   position and normal as an existing contact, but a larger
+//   penetration depth, this new depth is used instead
+//
+static void
+GenerateContact(int in_Flags, dContactGeom* in_Contacts, int in_Stride,  
+                dxTriMesh* in_TriMesh1,  dxTriMesh* in_TriMesh2,
+                const dVector3 in_ContactPos, const dVector3 in_Normal, dReal in_Depth,
+                int& OutTriCount)
+{
+	/*
+		NOTE by Oleh_Derevenko:
+		This function is called after maximal number of contacts has already been 
+		collected because it has a side effect of replacing penetration depth of
+		existing contact with larger penetration depth of another matching normal contact.
+		If this logic is not necessary any more, you can bail out on reach of contact
+		number maximum immediately in dCollideTTL(). You will also need to correct 
+		conditional statements after invocations of GenerateContact() in dCollideTTL().
+	*/
+	dIASSERT(in_Depth >= 0.0);
+    //if (in_Depth < 0.0) -- the function is always called with depth >= 0
+    //    return;
+
+	do 
+	{
+		dContactGeom* Contact;
+		dVector3 diff;
+
+		if (!(in_Flags & CONTACTS_UNIMPORTANT))
+		{
+			bool duplicate = false;
+
+			for (int i=0; i<OutTriCount; i++) 
+			{
+				Contact = SAFECONTACT(in_Flags, in_Contacts, i, in_Stride);
+
+				// same position?
+				SUB(diff, in_ContactPos, Contact->pos);
+				if (dDOT(diff, diff) < dEpsilon) 
+				{
+					// same normal?
+					if (dFabs(dDOT(in_Normal, Contact->normal)) > (REAL(1.0)-dEpsilon))
+					{
+						if (in_Depth > Contact->depth) {
+							Contact->depth = in_Depth;
+							SMULT( Contact->normal, in_Normal, -1.0);
+							Contact->normal[3] = 0.0;
+						}
+						duplicate = true;
+						/*
+							NOTE by Oleh_Derevenko:
+							There may be a case when two normals are close to each other but no duplicate
+							while third normal is detected to be duplicate for both of them.
+							This is the only reason I can think of, there is no "break" statement.
+							Perhaps author considered it to be logical that the third normal would 
+							replace the depth in both of initial contacts. 
+							However, I consider it a questionable practice which should not
+							be applied without deep understanding of underlaying physics.
+							Even more, is this situation with close normal triplet acceptable at all?
+							Should not be two initial contacts reduced to one (replaced with the latter)?
+							If you know the answers for these questions, you may want to change this code.
+							See the same statement in GenerateContact() of collision_trimesh_box.cpp
+						*/
+					}
+				}
+			}
+
+			if (duplicate || OutTriCount == (in_Flags & NUMC_MASK))
+			{
+				break;
+			}
+		}
+		else 
+		{
+			dIASSERT(OutTriCount < (in_Flags & NUMC_MASK));
+		}
+    
+		// Add a new contact
+		Contact = SAFECONTACT(in_Flags, in_Contacts, OutTriCount, in_Stride);
+
+		SET( Contact->pos, in_ContactPos );
+		Contact->pos[3] = 0.0;
+    
+		SMULT( Contact->normal, in_Normal, -1.0);
+		Contact->normal[3] = 0.0;
+    
+		Contact->depth = in_Depth;
+
+		Contact->g1 = in_TriMesh1;
+		Contact->g2 = in_TriMesh2;
+    
+		OutTriCount++;
+	}
+	while (false);
+}
+
+#endif // dTRIMESH_OPCODE
+#endif // !dTRIMESH_USE_NEW_TRIMESH_TRIMESH_COLLIDER
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_trimesh_trimesh_new.cpp	(revision 216)
@@ -0,0 +1,1304 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// OPCODE TriMesh/TriMesh collision code
+// Written at 2006-10-28 by Francisco León (http://gimpact.sourceforge.net)
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
+#endif
+
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+
+// New Implementation
+#if dTRIMESH_OPCODE_USE_NEW_TRIMESH_TRIMESH_COLLIDER
+
+#if dTRIMESH_ENABLED
+
+#include "collision_util.h"
+#define TRIMESH_INTERNAL
+#include "collision_trimesh_internal.h"
+
+#if dTRIMESH_OPCODE
+
+#define SMALL_ELT           REAL(2.5e-4)
+#define EXPANDED_ELT_THRESH REAL(1.0e-3)
+#define DISTANCE_EPSILON    REAL(1.0e-8)
+#define VELOCITY_EPSILON    REAL(1.0e-5)
+#define TINY_PENETRATION    REAL(5.0e-6)
+
+struct LineContactSet
+{
+	enum
+	{
+		MAX_POINTS = 8
+	};
+
+    dVector3 Points[MAX_POINTS];
+    int      Count;
+};
+
+
+static void GetTriangleGeometryCallback(udword, VertexPointers&, udword);
+inline void dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B);
+static void dInvertMatrix4( dMatrix4& B, dMatrix4& Binv );
+static int IntersectLineSegmentRay(dVector3, dVector3, dVector3, dVector3,  dVector3);
+static void ClipConvexPolygonAgainstPlane( const dVector3, dReal, LineContactSet& );
+static int RayTriangleIntersect(const dVector3 orig, const dVector3 dir,
+                                const dVector3 vert0, const dVector3 vert1,const dVector3 vert2,
+                                dReal *t,dReal *u,dReal *v);
+
+
+///returns the penetration depth
+static dReal MostDeepPoints(
+							LineContactSet & points,
+							const dVector3 plane_normal,
+							dReal plane_dist,
+							LineContactSet & deep_points);
+///returns the penetration depth
+static dReal FindMostDeepPointsInTetra(
+							LineContactSet contact_points,
+							const dVector3 sourcetri[3],///triangle which contains contact_points
+							const dVector3 tetra[4],
+							const dVector4 tetraplanes[4],
+							dVector3 separating_normal,
+							LineContactSet deep_points);
+
+static bool ClipTriByTetra(const dVector3 tri[3],
+						   const dVector3 tetra[4],
+						   LineContactSet& Contacts);
+static bool TriTriContacts(const dVector3 tr1[3],
+							 const dVector3 tr2[3],
+							 dxGeom* g1, dxGeom* g2, int Flags,
+							 dContactGeom* Contacts, int Stride,
+							 int &contactcount);
+
+
+/* some math macros */
+#define CROSS(dest,v1,v2) { dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
+	dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
+	dest[2]=v1[0]*v2[1]-v1[1]*v2[0]; }
+
+#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
+
+#define SUB(dest,v1,v2) { dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2]; }
+
+#define ADD(dest,v1,v2) { dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2]; }
+
+#define MULT(dest,v,factor) { dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2]; }
+
+#define SET(dest,src) { dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2]; }
+
+#define SMULT(p,q,s) { p[0]=q[0]*s; p[1]=q[1]*s; p[2]=q[2]*s; }
+
+#define COMBO(combo,p,t,q) { combo[0]=p[0]+t*q[0]; combo[1]=p[1]+t*q[1]; combo[2]=p[2]+t*q[2]; }
+
+#define LENGTH(x)  ((dReal) 1.0f/InvSqrt(dDOT(x, x)))
+
+#define DEPTH(d, p, q, n) d = (p[0] - q[0])*n[0] +  (p[1] - q[1])*n[1] +  (p[2] - q[2])*n[2];
+
+inline const dReal dMin(const dReal x, const dReal y)
+{
+    return x < y ? x : y;
+}
+
+
+inline void
+SwapNormals(dVector3 *&pen_v, dVector3 *&col_v, dVector3* v1, dVector3* v2,
+            dVector3 *&pen_elt, dVector3 *elt_f1, dVector3 *elt_f2,
+            dVector3 n, dVector3 n1, dVector3 n2)
+{
+    if (pen_v == v1) {
+        pen_v = v2;
+        pen_elt = elt_f2;
+        col_v = v1;
+        SET(n, n1);
+    }
+    else {
+        pen_v = v1;
+        pen_elt = elt_f1;
+        col_v = v2;
+        SET(n, n2);
+    }
+}
+
+///////////////////////MECHANISM FOR AVOID CONTACT REDUNDANCE///////////////////////////////
+////* Written by Francisco León (http://gimpact.sourceforge.net) *///
+#define CONTACT_DIFF_EPSILON REAL(0.00001)
+#if defined(dDOUBLE)
+#define CONTACT_NORMAL_ZERO REAL(0.0000001)
+#else // if defined(dSINGLE)
+#define CONTACT_NORMAL_ZERO REAL(0.00001)
+#endif
+#define CONTACT_POS_HASH_QUOTIENT REAL(10000.0)
+#define dSQRT3	REAL(1.7320508075688773)
+
+struct CONTACT_KEY
+{
+	dContactGeom * m_contact;
+	unsigned int m_key;
+};
+
+#define MAXCONTACT_X_NODE 4
+struct CONTACT_KEY_HASH_NODE
+{
+	CONTACT_KEY m_keyarray[MAXCONTACT_X_NODE];
+	int m_keycount;
+};
+
+#define CONTACTS_HASHSIZE 256
+CONTACT_KEY_HASH_NODE g_hashcontactset[CONTACTS_HASHSIZE];
+
+
+
+void UpdateContactKey(CONTACT_KEY & key, dContactGeom * contact)
+{
+	key.m_contact = contact;
+
+	unsigned int hash=0;
+
+	int i = 0;
+
+	while (true)
+	{
+		dReal coord = contact->pos[i];
+		coord = dFloor(coord * CONTACT_POS_HASH_QUOTIENT);
+
+		unsigned int hash_input = ((unsigned int *)&coord)[0];
+		if (sizeof(dReal) / sizeof(unsigned int) != 1)
+		{
+			dIASSERT(sizeof(dReal) / sizeof(unsigned int) == 2);
+			hash_input ^= ((unsigned int *)&coord)[1];
+		}
+
+		hash = (( hash << 4 ) + (hash_input >> 24)) ^ ( hash >> 28 );
+		hash = (( hash << 4 ) + ((hash_input >> 16) & 0xFF)) ^ ( hash >> 28 );
+		hash = (( hash << 4 ) + ((hash_input >> 8) & 0xFF)) ^ ( hash >> 28 );
+		hash = (( hash << 4 ) + (hash_input & 0xFF)) ^ ( hash >> 28 );
+
+		if (++i == 3)
+		{
+			break;
+		}
+
+		hash = (hash << 11) | (hash >> 21);
+	}
+
+	key.m_key = hash;
+}
+
+
+static inline unsigned int MakeContactIndex(unsigned int key)
+{
+	dIASSERT(CONTACTS_HASHSIZE == 256);
+
+	unsigned int index = key ^ (key >> 16);
+	index = (index ^ (index >> 8)) & 0xFF;
+	return index;
+}
+
+dContactGeom *AddContactToNode(const CONTACT_KEY * contactkey,CONTACT_KEY_HASH_NODE * node)
+{
+	for(int i=0;i<node->m_keycount;i++)
+	{
+		if(node->m_keyarray[i].m_key == contactkey->m_key)
+		{
+			dContactGeom *contactfound = node->m_keyarray[i].m_contact;
+			if (dDISTANCE(contactfound->pos, contactkey->m_contact->pos) < REAL(1.00001) /*for comp. errors*/ * dSQRT3 / CONTACT_POS_HASH_QUOTIENT /*cube diagonal*/)
+			{
+				return contactfound;
+			}
+		}
+	}
+
+	if (node->m_keycount < MAXCONTACT_X_NODE)
+	{
+		node->m_keyarray[node->m_keycount].m_contact = contactkey->m_contact;
+		node->m_keyarray[node->m_keycount].m_key = contactkey->m_key;
+		node->m_keycount++;
+	}
+	else
+	{
+		dDEBUGMSG("Trimesh-trimesh contach hash table bucket overflow - close contacts might not be culled");
+	}
+
+	return contactkey->m_contact;
+}
+
+void RemoveNewContactFromNode(const CONTACT_KEY * contactkey, CONTACT_KEY_HASH_NODE * node)
+{
+	dIASSERT(node->m_keycount > 0);
+
+	if (node->m_keyarray[node->m_keycount - 1].m_contact == contactkey->m_contact)
+	{
+		node->m_keycount -= 1;
+	}
+	else
+	{
+		dIASSERT(node->m_keycount == MAXCONTACT_X_NODE);
+	}
+}
+
+void RemoveArbitraryContactFromNode(const CONTACT_KEY *contactkey, CONTACT_KEY_HASH_NODE *node)
+{
+	dIASSERT(node->m_keycount > 0);
+
+	int keyindex, lastkeyindex = node->m_keycount - 1;
+
+	// Do not check the last contact
+	for (keyindex = 0; keyindex < lastkeyindex; keyindex++)
+	{
+		if (node->m_keyarray[keyindex].m_contact == contactkey->m_contact)
+		{
+			node->m_keyarray[keyindex] = node->m_keyarray[lastkeyindex];
+			break;
+		}
+	}
+
+	dIASSERT(keyindex < lastkeyindex || 
+		node->m_keyarray[keyindex].m_contact == contactkey->m_contact); // It has been either the break from loop or last element should match
+
+	node->m_keycount = lastkeyindex;
+}
+
+void UpdateArbitraryContactInNode(const CONTACT_KEY *contactkey, CONTACT_KEY_HASH_NODE *node,
+	dContactGeom *pwithcontact)
+{
+	dIASSERT(node->m_keycount > 0);
+
+	int keyindex, lastkeyindex = node->m_keycount - 1;
+
+	// Do not check the last contact
+	for (keyindex = 0; keyindex < lastkeyindex; keyindex++)
+	{
+		if (node->m_keyarray[keyindex].m_contact == contactkey->m_contact)
+		{
+			break;
+		}
+	}
+
+	dIASSERT(keyindex < lastkeyindex || 
+		node->m_keyarray[keyindex].m_contact == contactkey->m_contact); // It has been either the break from loop or last element should match
+
+	node->m_keyarray[keyindex].m_contact = pwithcontact;
+}
+
+void ClearContactSet()
+{
+	memset(g_hashcontactset,0,sizeof(CONTACT_KEY_HASH_NODE)*CONTACTS_HASHSIZE);
+}
+
+//return true if found
+dContactGeom *InsertContactInSet(const CONTACT_KEY &newkey)
+{
+	unsigned int index = MakeContactIndex(newkey.m_key);
+
+	return AddContactToNode(&newkey, &g_hashcontactset[index]);
+}
+
+void RemoveNewContactFromSet(const CONTACT_KEY &contactkey)
+{
+	unsigned int index = MakeContactIndex(contactkey.m_key);
+	
+	RemoveNewContactFromNode(&contactkey, &g_hashcontactset[index]);
+}
+
+void RemoveArbitraryContactFromSet(const CONTACT_KEY &contactkey)
+{
+	unsigned int index = MakeContactIndex(contactkey.m_key);
+
+	RemoveArbitraryContactFromNode(&contactkey, &g_hashcontactset[index]);
+}
+
+void UpdateArbitraryContactInSet(const CONTACT_KEY &contactkey, 
+	dContactGeom *pwithcontact)
+{
+	unsigned int index = MakeContactIndex(contactkey.m_key);
+
+	UpdateArbitraryContactInNode(&contactkey, &g_hashcontactset[index], pwithcontact);
+}
+
+bool AllocNewContact(
+			const dVector3 newpoint, dContactGeom *& out_pcontact,
+			int Flags, dContactGeom* Contacts,
+			int Stride,  int &contactcount)
+{
+	bool allocated_new = false;
+
+	dContactGeom dLocalContact;
+
+	dContactGeom * pcontact = contactcount != (Flags & NUMC_MASK) ? 
+		SAFECONTACT(Flags, Contacts, contactcount, Stride) : &dLocalContact;
+
+	pcontact->pos[0] = newpoint[0];
+	pcontact->pos[1] = newpoint[1];
+	pcontact->pos[2] = newpoint[2];
+	pcontact->pos[3] = 1.0f;
+
+	CONTACT_KEY newkey;
+	UpdateContactKey(newkey, pcontact);
+	
+	dContactGeom *pcontactfound = InsertContactInSet(newkey);
+	if (pcontactfound == pcontact)
+	{
+		if (pcontactfound != &dLocalContact)
+		{
+			contactcount++;
+		}
+		else
+		{
+			RemoveNewContactFromSet(newkey);
+			pcontactfound = NULL;
+		}
+		
+		allocated_new = true;
+	}
+
+	out_pcontact = pcontactfound;
+	return allocated_new;
+}
+
+void FreeExistingContact(dContactGeom *pcontact,
+	int Flags, dContactGeom *Contacts, 
+	int Stride, int &contactcount)
+{
+	CONTACT_KEY contactKey;
+	UpdateContactKey(contactKey, pcontact);
+
+	RemoveArbitraryContactFromSet(contactKey);
+
+	int lastContactIndex = contactcount - 1;
+	dContactGeom *plastContact = SAFECONTACT(Flags, Contacts, lastContactIndex, Stride);
+
+	if (pcontact != plastContact)
+	{
+		*pcontact = *plastContact;
+
+		CONTACT_KEY lastContactKey;
+		UpdateContactKey(lastContactKey, plastContact);
+		
+		UpdateArbitraryContactInSet(lastContactKey, pcontact);
+	}
+
+	contactcount = lastContactIndex;
+}
+
+
+dContactGeom *  PushNewContact( dxGeom* g1, dxGeom* g2,
+							   const dVector3 point,
+							   dVector3 normal,
+							   dReal  depth,
+							   int Flags,
+							 dContactGeom* Contacts, int Stride,
+							 int &contactcount)
+{
+	dIASSERT(dFabs(dVector3Length((const dVector3 &)(*normal)) - REAL(1.0)) < REAL(1e-6)); // This assumption is used in the code
+
+	dContactGeom * pcontact;
+
+	if (!AllocNewContact(point, pcontact, Flags, Contacts, Stride, contactcount))
+	{
+		const dReal depthDifference = depth - pcontact->depth;
+
+		if (depthDifference > CONTACT_DIFF_EPSILON)
+		{
+			pcontact->normal[0] = normal[0];
+			pcontact->normal[1] = normal[1];
+			pcontact->normal[2] = normal[2];
+			pcontact->normal[3] = REAL(1.0); // used to store length of vector sum for averaging
+			pcontact->depth = depth;
+
+			pcontact->g1 = g1;
+			pcontact->g2 = g2;
+		}
+		else if (depthDifference >= -CONTACT_DIFF_EPSILON) ///average
+		{
+			if(pcontact->g1 == g2)
+			{
+				MULT(normal,normal, REAL(-1.0));
+			}
+
+			const dReal oldLen = pcontact->normal[3];
+			COMBO(pcontact->normal, normal, oldLen, pcontact->normal);
+
+			const dReal len = LENGTH(pcontact->normal);
+			if (len > CONTACT_NORMAL_ZERO)
+			{
+				MULT(pcontact->normal, pcontact->normal, REAL(1.0) / len);
+				pcontact->normal[3] = len;
+			}
+			else
+			{
+				FreeExistingContact(pcontact, Flags, Contacts, Stride, contactcount);
+			}
+		}
+	}
+	// Contact can be not available if buffer is full
+	else if (pcontact)
+	{
+		pcontact->normal[0] = normal[0];
+		pcontact->normal[1] = normal[1];
+		pcontact->normal[2] = normal[2];
+		pcontact->normal[3] = REAL(1.0); // used to store length of vector sum for averaging
+		pcontact->depth = depth;
+		pcontact->g1 = g1;
+		pcontact->g2 = g2;
+	}
+
+	return pcontact;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+int
+dCollideTTL(dxGeom* g1, dxGeom* g2, int Flags, dContactGeom* Contacts, int Stride)
+{
+	dIASSERT (Stride >= (int)sizeof(dContactGeom));
+	dIASSERT (g1->type == dTriMeshClass);
+	dIASSERT (g2->type == dTriMeshClass);
+	dIASSERT ((Flags & NUMC_MASK) >= 1);
+	
+    dxTriMesh* TriMesh1 = (dxTriMesh*) g1;
+    dxTriMesh* TriMesh2 = (dxTriMesh*) g2;
+
+    dReal * TriNormals1 = (dReal *) TriMesh1->Data->Normals;
+    dReal * TriNormals2 = (dReal *) TriMesh2->Data->Normals;
+
+    const dVector3& TLPosition1 = *(const dVector3*) dGeomGetPosition(TriMesh1);
+    // TLRotation1 = column-major order
+    const dMatrix3& TLRotation1 = *(const dMatrix3*) dGeomGetRotation(TriMesh1);
+
+    const dVector3& TLPosition2 = *(const dVector3*) dGeomGetPosition(TriMesh2);
+    // TLRotation2 = column-major order
+    const dMatrix3& TLRotation2 = *(const dMatrix3*) dGeomGetRotation(TriMesh2);
+
+    AABBTreeCollider& Collider = TriMesh1->_AABBTreeCollider;
+
+
+    static BVTCache ColCache;
+    ColCache.Model0 = &TriMesh1->Data->BVTree;
+    ColCache.Model1 = &TriMesh2->Data->BVTree;
+
+	////Prepare contact list
+	ClearContactSet();
+
+    // Collision query
+    Matrix4x4 amatrix, bmatrix;
+    BOOL IsOk = Collider.Collide(ColCache,
+                                 &MakeMatrix(TLPosition1, TLRotation1, amatrix),
+                                 &MakeMatrix(TLPosition2, TLRotation2, bmatrix) );
+
+
+    // Make "double" versions of these matrices, if appropriate
+    dMatrix4 A, B;
+    dMakeMatrix4(TLPosition1, TLRotation1, A);
+    dMakeMatrix4(TLPosition2, TLRotation2, B);
+
+
+
+
+    if (IsOk) {
+        // Get collision status => if true, objects overlap
+        if ( Collider.GetContactStatus() ) {
+            // Number of colliding pairs and list of pairs
+            int TriCount = Collider.GetNbPairs();
+            const Pair* CollidingPairs = Collider.GetPairs();
+
+            if (TriCount > 0) {
+                // step through the pairs, adding contacts
+                int             id1, id2;
+                int             OutTriCount = 0;
+                dVector3        v1[3], v2[3];
+
+                // only do these expensive inversions once
+                /*dMatrix4 InvMatrix1, InvMatrix2;
+                dInvertMatrix4(A, InvMatrix1);
+                dInvertMatrix4(B, InvMatrix2);*/
+
+
+                for (int i = 0; i < TriCount; i++)
+				{
+                    id1 = CollidingPairs[i].id0;
+                    id2 = CollidingPairs[i].id1;
+
+                    // grab the colliding triangles
+                    FetchTriangle((dxTriMesh*) g1, id1, TLPosition1, TLRotation1, v1);
+                    FetchTriangle((dxTriMesh*) g2, id2, TLPosition2, TLRotation2, v2);
+                    // Since we'll be doing matrix transformations, we need to
+                    //  make sure that all vertices have four elements
+                    for (int j=0; j<3; j++) {
+                        v1[j][3] = 1.0;
+                        v2[j][3] = 1.0;
+                    }
+
+					TriTriContacts(v1,v2,
+						  g1, g2, Flags,
+						 Contacts,Stride,OutTriCount);
+					
+					// Continue loop even after contacts are full 
+					// as existing contacts' normals/depths might be updated
+					// Break only if contacts are not important
+					if ((OutTriCount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
+					{
+						break;
+					}
+				}
+
+                // Return the number of contacts
+                return OutTriCount;
+
+            }
+        }
+    }
+
+
+    // There was some kind of failure during the Collide call or
+    // there are no faces overlapping
+    return 0;
+}
+
+
+
+static void
+GetTriangleGeometryCallback(udword triangleindex, VertexPointers& triangle, udword user_data)
+{
+    dVector3 Out[3];
+
+    FetchTriangle((dxTriMesh*) user_data, (int) triangleindex, Out);
+
+    for (int i = 0; i < 3; i++)
+        triangle.Vertex[i] =  (const Point*) ((dReal*) Out[i]);
+}
+
+
+//
+//
+//
+#define B11   B[0]
+#define B12   B[1]
+#define B13   B[2]
+#define B14   B[3]
+#define B21   B[4]
+#define B22   B[5]
+#define B23   B[6]
+#define B24   B[7]
+#define B31   B[8]
+#define B32   B[9]
+#define B33   B[10]
+#define B34   B[11]
+#define B41   B[12]
+#define B42   B[13]
+#define B43   B[14]
+#define B44   B[15]
+
+#define Binv11   Binv[0]
+#define Binv12   Binv[1]
+#define Binv13   Binv[2]
+#define Binv14   Binv[3]
+#define Binv21   Binv[4]
+#define Binv22   Binv[5]
+#define Binv23   Binv[6]
+#define Binv24   Binv[7]
+#define Binv31   Binv[8]
+#define Binv32   Binv[9]
+#define Binv33   Binv[10]
+#define Binv34   Binv[11]
+#define Binv41   Binv[12]
+#define Binv42   Binv[13]
+#define Binv43   Binv[14]
+#define Binv44   Binv[15]
+
+inline void
+dMakeMatrix4(const dVector3 Position, const dMatrix3 Rotation, dMatrix4 &B)
+{
+	B11 = Rotation[0]; B21 = Rotation[1]; B31 = Rotation[2];    B41 = Position[0];
+	B12 = Rotation[4]; B22 = Rotation[5]; B32 = Rotation[6];    B42 = Position[1];
+	B13 = Rotation[8]; B23 = Rotation[9]; B33 = Rotation[10];   B43 = Position[2];
+
+    B14 = 0.0;         B24 = 0.0;         B34 = 0.0;            B44 = 1.0;
+}
+
+
+static void
+dInvertMatrix4( dMatrix4& B, dMatrix4& Binv )
+{
+    dReal det =  (B11 * B22 - B12 * B21) * (B33 * B44 - B34 * B43)
+        -(B11 * B23 - B13 * B21) * (B32 * B44 - B34 * B42)
+        +(B11 * B24 - B14 * B21) * (B32 * B43 - B33 * B42)
+        +(B12 * B23 - B13 * B22) * (B31 * B44 - B34 * B41)
+        -(B12 * B24 - B14 * B22) * (B31 * B43 - B33 * B41)
+        +(B13 * B24 - B14 * B23) * (B31 * B42 - B32 * B41);
+
+    dAASSERT (det != 0.0);
+
+    det = 1.0 / det;
+
+    Binv11 = (dReal) (det * ((B22 * B33) - (B23 * B32)));
+    Binv12 = (dReal) (det * ((B32 * B13) - (B33 * B12)));
+    Binv13 = (dReal) (det * ((B12 * B23) - (B13 * B22)));
+    Binv14 = 0.0f;
+    Binv21 = (dReal) (det * ((B23 * B31) - (B21 * B33)));
+    Binv22 = (dReal) (det * ((B33 * B11) - (B31 * B13)));
+    Binv23 = (dReal) (det * ((B13 * B21) - (B11 * B23)));
+    Binv24 = 0.0f;
+    Binv31 = (dReal) (det * ((B21 * B32) - (B22 * B31)));
+    Binv32 = (dReal) (det * ((B31 * B12) - (B32 * B11)));
+    Binv33 = (dReal) (det * ((B11 * B22) - (B12 * B21)));
+    Binv34 = 0.0f;
+    Binv41 = (dReal) (det * (B21*(B33*B42 - B32*B43) + B22*(B31*B43 - B33*B41) + B23*(B32*B41 - B31*B42)));
+    Binv42 = (dReal) (det * (B31*(B13*B42 - B12*B43) + B32*(B11*B43 - B13*B41) + B33*(B12*B41 - B11*B42)));
+    Binv43 = (dReal) (det * (B41*(B13*B22 - B12*B23) + B42*(B11*B23 - B13*B21) + B43*(B12*B21 - B11*B22)));
+    Binv44 = 1.0f;
+}
+
+
+
+// Find the intersectiojn point between a coplanar line segement,
+// defined by X1 and X2, and a ray defined by X3 and direction N.
+//
+// This forumla for this calculation is:
+//               (c x b) . (a x b)
+//   Q = x1 + a -------------------
+//                  | a x b | ^2
+//
+// where a = x2 - x1
+//       b = x4 - x3
+//       c = x3 - x1
+// x1 and x2 are the edges of the triangle, and x3 is CoplanarPt
+//  and x4 is (CoplanarPt - n)
+static int
+IntersectLineSegmentRay(dVector3 x1, dVector3 x2, dVector3 x3, dVector3 n,
+                        dVector3 out_pt)
+{
+    dVector3 a, b, c, x4;
+
+    ADD(x4, x3, n);  // x4 = x3 + n
+
+    SUB(a, x2, x1);  // a = x2 - x1
+    SUB(b, x4, x3);
+    SUB(c, x3, x1);
+
+    dVector3 tmp1, tmp2;
+    CROSS(tmp1, c, b);
+    CROSS(tmp2, a, b);
+
+    dReal num, denom;
+    num = dDOT(tmp1, tmp2);
+    denom = LENGTH( tmp2 );
+
+    dReal s;
+    s = num /(denom*denom);
+
+    for (int i=0; i<3; i++)
+        out_pt[i] = x1[i] + a[i]*s;
+
+    // Test if this intersection is "behind" x3, w.r.t. n
+    SUB(a, x3, out_pt);
+    if (dDOT(a, n) > 0.0)
+        return 0;
+
+    // Test if this intersection point is outside the edge limits,
+    //  if (dot( (out_pt-x1), (out_pt-x2) ) < 0) it's inside
+    //  else outside
+    SUB(a, out_pt, x1);
+    SUB(b, out_pt, x2);
+    if (dDOT(a,b) < 0.0)
+        return 1;
+    else
+        return 0;
+}
+
+
+
+void PlaneClipSegment( const dVector3  s1, const dVector3  s2,
+					   const dVector3  N, dReal C, dVector3  clipped)
+{
+	dReal dis1,dis2;
+	dis1 = DOT(s1,N)-C;
+	SUB(clipped,s2,s1);
+	dis2 = DOT(clipped,N);
+	MULT(clipped,clipped,-dis1/dis2);
+	ADD(clipped,clipped,s1);
+	clipped[3] = 1.0f;
+}
+
+/* ClipConvexPolygonAgainstPlane - Clip a a convex polygon, described by
+  CONTACTS, with a plane (described by N and C distance from origin).
+  Note:  the input vertices are assumed to be in invcounterclockwise order.
+   changed by Francisco Leon (http://gimpact.sourceforge.net) */
+static void
+ClipConvexPolygonAgainstPlane( const dVector3 N, dReal C,
+                               LineContactSet& Contacts )
+{
+    int  i, vi, prevclassif=32000, classif;
+	/*
+	classif 0 : back, 1 : front
+	*/
+
+	dReal d;
+	dVector3 clipped[8];
+	int clippedcount =0;
+
+	if(Contacts.Count==0)
+	{
+		return;
+	}
+	for(i=0;i<=Contacts.Count;i++)
+	{
+		vi = i%Contacts.Count;
+
+		d = DOT(N,Contacts.Points[vi]) - C;
+		////classify point
+		if(d>REAL(1.0e-8))	classif =  1;
+		else  classif =  0;
+
+		if(classif == 0)//back
+		{
+			if(i>0)
+			{
+				if(prevclassif==1)///in front
+				{
+
+					///add clipped point
+					if(clippedcount<8)
+					{
+						PlaneClipSegment(Contacts.Points[i-1],Contacts.Points[vi],
+						N,C,clipped[clippedcount]);
+						clippedcount++;
+					}
+				}
+			}
+			///add point
+			if(clippedcount<8&&i<Contacts.Count)
+			{
+				clipped[clippedcount][0] = Contacts.Points[vi][0];
+				clipped[clippedcount][1] = Contacts.Points[vi][1];
+				clipped[clippedcount][2] = Contacts.Points[vi][2];
+				clipped[clippedcount][3] = 1.0f;
+				clippedcount++;
+			}
+		}
+		else
+		{
+
+			if(i>0)
+			{
+				if(prevclassif==0)
+				{
+					///add point
+					if(clippedcount<8)
+					{
+						PlaneClipSegment(Contacts.Points[i-1],Contacts.Points[vi],
+						N,C,clipped[clippedcount]);
+						clippedcount++;
+					}
+				}
+			}
+		}
+
+		prevclassif	= classif;
+	}
+
+	if(clippedcount==0)
+	{
+		Contacts.Count = 0;
+		return;
+	}
+	Contacts.Count = clippedcount;
+	memcpy( Contacts.Points, clipped, clippedcount * sizeof(dVector3) );
+	return;
+}
+
+
+bool BuildPlane(const dVector3 s0, const dVector3 s1,const dVector3 s2,
+				dVector3 Normal, dReal & Dist)
+{
+	dVector3 e0,e1;
+	SUB(e0,s1,s0);
+	SUB(e1,s2,s0);
+
+	CROSS(Normal,e0,e1);
+
+	if (!dSafeNormalize3(Normal))
+	{
+		return false;
+	}
+
+	Dist = DOT(Normal,s0);
+	return true;
+
+}
+
+bool BuildEdgesDir(const dVector3 s0, const dVector3 s1,
+					const dVector3 t0, const dVector3 t1,
+					dVector3 crossdir)
+{
+	dVector3 e0,e1;
+
+	SUB(e0,s1,s0);
+	SUB(e1,t1,t0);
+	CROSS(crossdir,e0,e1);
+
+	if (!dSafeNormalize3(crossdir))
+	{
+		return false;
+	}
+	return true;
+}
+
+
+
+bool BuildEdgePlane(
+					const dVector3 s0, const dVector3 s1,
+					const dVector3 normal,
+					dVector3 plane_normal,
+					dReal & plane_dist)
+{
+	dVector3 e0;
+
+	SUB(e0,s1,s0);
+	CROSS(plane_normal,e0,normal);
+	if (!dSafeNormalize3(plane_normal))
+	{
+		return false;
+	}
+	plane_dist = DOT(plane_normal,s0);
+	return true;
+}
+
+
+
+
+/*
+Positive penetration
+Negative number: they are separated
+*/
+dReal IntervalPenetration(dReal &vmin1,dReal &vmax1,
+						  dReal &vmin2,dReal &vmax2)
+{
+	if(vmax1<=vmin2)
+	{
+		return -(vmin2-vmax1);
+	}
+	else
+	{
+		if(vmax2<=vmin1)
+		{
+			return -(vmin1-vmax2);
+		}
+		else
+		{
+			if(vmax1<=vmax2)
+			{
+				return vmax1-vmin2;
+			}
+
+			return vmax2-vmin1;
+		}
+
+	}
+	return 0;
+}
+
+void FindInterval(
+				  const dVector3 * vertices, int verticecount,
+				  dVector3 dir,dReal &vmin,dReal &vmax)
+{
+
+	dReal dist;
+	int i;
+	vmin = DOT(vertices[0],dir);
+	vmax = vmin;
+	for(i=1;i<verticecount;i++)
+	{
+		dist = DOT(vertices[i],dir);
+		if(vmin>dist) vmin=dist;
+		else if(vmax<dist) vmax=dist;
+	}
+}
+
+///returns the penetration depth
+dReal MostDeepPoints(
+					LineContactSet & points,
+					const dVector3 plane_normal,
+					dReal plane_dist,
+					LineContactSet & deep_points)
+{
+	int i;
+	int max_candidates[8];
+	dReal maxdeep=-dInfinity;
+	dReal dist;
+
+	deep_points.Count = 0;
+	for(i=0;i<points.Count;i++)
+	{
+		dist = DOT(plane_normal,points.Points[i]) - plane_dist;
+		dist *= -1.0f;
+		if(dist>maxdeep)
+		{
+			maxdeep = dist;
+			deep_points.Count=1;
+			max_candidates[deep_points.Count-1] = i;
+		}
+		else if(dist+REAL(0.000001)>=maxdeep)
+		{
+			deep_points.Count++;
+			max_candidates[deep_points.Count-1] = i;
+		}
+	}
+
+	for(i=0;i<deep_points.Count;i++)
+	{
+		SET(deep_points.Points[i],points.Points[max_candidates[i]]);
+	}
+	return maxdeep;
+
+}
+
+void ClipPointsByTri(
+					  const dVector3 * points, int pointcount,
+					  const dVector3 tri[3],
+					  const dVector3 triplanenormal,
+					  dReal triplanedist,
+					  LineContactSet & clipped_points,
+					  bool triplane_clips)
+{
+	///build edges planes
+	int i;
+	dVector4 plane;
+
+	clipped_points.Count = pointcount;
+	memcpy(&clipped_points.Points[0],&points[0],pointcount*sizeof(dVector3));
+	for(i=0;i<3;i++)
+	{
+		if (BuildEdgePlane(
+			tri[i],tri[(i+1)%3],triplanenormal,
+			plane,plane[3]))
+		{
+			ClipConvexPolygonAgainstPlane(
+				plane,
+				plane[3],
+				clipped_points);
+		}
+	}
+
+	if(triplane_clips)
+	{
+		ClipConvexPolygonAgainstPlane(
+			triplanenormal,
+			triplanedist,
+			clipped_points);
+	}
+}
+
+
+///returns the penetration depth
+dReal FindTriangleTriangleCollision(
+							const dVector3 tri1[3],
+							const dVector3 tri2[3],
+							dVector3 separating_normal,
+							LineContactSet & deep_points)
+{
+	dReal maxdeep=dInfinity;
+	dReal dist;
+	int mostdir=0,mostface = 0, currdir=0;
+//	dReal vmin1,vmax1,vmin2,vmax2;
+//	dVector3 crossdir, pt1,pt2;
+	dVector4 tri1plane,tri2plane;
+	separating_normal[3] = 0.0f;
+	bool bl;
+	LineContactSet clipped_points1,clipped_points2;
+	LineContactSet deep_points1,deep_points2;
+	////find interval face1
+
+	bl = BuildPlane(tri1[0],tri1[1],tri1[2],
+		tri1plane,tri1plane[3]);
+	clipped_points1.Count = 0;
+
+	if(bl)
+	{
+		ClipPointsByTri(
+					  tri2, 3,
+					  tri1,
+					  tri1plane,
+					  tri1plane[3],
+					  clipped_points1,false);
+
+
+
+		maxdeep = MostDeepPoints(
+					clipped_points1,
+					tri1plane,
+					tri1plane[3],
+					deep_points1);
+		SET(separating_normal,tri1plane);
+
+	}
+	currdir++;
+
+	////find interval face2
+
+	bl = BuildPlane(tri2[0],tri2[1],tri2[2],
+		tri2plane,tri2plane[3]);
+
+
+	clipped_points2.Count = 0;
+	if(bl)
+	{
+		ClipPointsByTri(
+					  tri1, 3,
+					  tri2,
+					  tri2plane,
+					  tri2plane[3],
+					  clipped_points2,false);
+
+
+
+		dist = MostDeepPoints(
+					clipped_points2,
+					tri2plane,
+					tri2plane[3],
+					deep_points2);
+
+
+
+		if(dist<maxdeep)
+		{
+			maxdeep = dist;
+			mostdir = currdir;
+			mostface = 1;
+			SET(separating_normal,tri2plane);
+		}
+	}
+	currdir++;
+
+
+	///find edge edge distances
+	///test each edge plane
+
+	/*for(i=0;i<3;i++)
+	{
+
+
+		for(j=0;j<3;j++)
+		{
+
+
+			bl = BuildEdgesDir(
+				tri1[i],tri1[(i+1)%3],
+				tri2[j],tri2[(j+1)%3],
+				crossdir);
+
+			////find plane distance
+
+			if(bl)
+			{
+				FindInterval(tri1,3,crossdir,vmin1,vmax1);
+				FindInterval(tri2,3,crossdir,vmin2,vmax2);
+
+				dist = IntervalPenetration(
+					vmin1,
+					vmax1,
+					vmin2,
+					vmax2);
+				if(dist<maxdeep)
+				{
+					maxdeep = dist;
+					mostdir = currdir;
+					SET(separating_normal,crossdir);
+				}
+			}
+			currdir++;
+		}
+	}*/
+
+
+	////check most dir for contacts
+	if(mostdir==0)
+	{
+		///find most deep points
+		deep_points.Count = deep_points1.Count;
+		memcpy(
+			&deep_points.Points[0],
+			&deep_points1.Points[0],
+			deep_points1.Count*sizeof(dVector3));
+
+		///invert normal for point to tri1
+		MULT(separating_normal,separating_normal,-1.0f);
+	}
+	else if(mostdir==1)
+	{
+		deep_points.Count = deep_points2.Count;
+		memcpy(
+			&deep_points.Points[0],
+			&deep_points2.Points[0],
+			deep_points2.Count*sizeof(dVector3));
+
+	}
+	/*else
+	{///edge separation
+		mostdir -= 2;
+
+		//edge 2
+		j = mostdir%3;
+		//edge 1
+		i = mostdir/3;
+
+		///find edge closest points
+		dClosestLineSegmentPoints(
+			tri1[i],tri1[(i+1)%3],
+			tri2[j],tri2[(j+1)%3],
+			pt1,pt2);
+		///find correct direction
+
+		SUB(crossdir,pt2,pt1);
+
+		vmin1 = LENGTH(crossdir);
+		if(vmin1<REAL(0.000001))
+		{
+
+			if(mostface==0)
+			{
+				vmin1 = DOT(separating_normal,tri1plane);
+				if(vmin1>0.0)
+				{
+					MULT(separating_normal,separating_normal,-1.0f);
+					deep_points.Count = 1;
+					SET(deep_points.Points[0],pt2);
+				}
+				else
+				{
+					deep_points.Count = 1;
+					SET(deep_points.Points[0],pt2);
+				}
+
+			}
+			else
+			{
+				vmin1 = DOT(separating_normal,tri2plane);
+				if(vmin1<0.0)
+				{
+					MULT(separating_normal,separating_normal,-1.0f);
+					deep_points.Count = 1;
+					SET(deep_points.Points[0],pt2);
+				}
+				else
+				{
+					deep_points.Count = 1;
+					SET(deep_points.Points[0],pt2);
+				}
+
+			}
+
+
+
+
+		}
+		else
+		{
+			MULT(separating_normal,crossdir,1.0f/vmin1);
+
+			vmin1 = DOT(separating_normal,tri1plane);
+			if(vmin1>0.0)
+			{
+				MULT(separating_normal,separating_normal,-1.0f);
+				deep_points.Count = 1;
+				SET(deep_points.Points[0],pt2);
+			}
+			else
+			{
+				deep_points.Count = 1;
+				SET(deep_points.Points[0],pt2);
+			}
+
+
+		}
+
+
+	}*/
+	return maxdeep;
+}
+
+
+
+///SUPPORT UP TO 8 CONTACTS
+bool TriTriContacts(const dVector3 tr1[3],
+							 const dVector3 tr2[3],
+							  dxGeom* g1, dxGeom* g2, int Flags,
+							 dContactGeom* Contacts, int Stride,
+							 int &contactcount)
+{
+
+
+	dVector4 normal;
+	dReal depth;
+	///Test Tri Vs Tri
+//	dContactGeom* pcontact;
+	int ccount = 0;
+	LineContactSet contactpoints;
+	contactpoints.Count = 0;
+
+
+
+	///find best direction
+
+	depth = FindTriangleTriangleCollision(
+							tr1,
+							tr2,
+							normal,
+							contactpoints);
+
+
+
+	if(depth<0.0f) return false;
+
+	ccount = 0;
+	while (ccount<contactpoints.Count)
+	{
+		PushNewContact( g1,  g2,
+					contactpoints.Points[ccount],
+					normal, depth, Flags,
+					Contacts,Stride,contactcount);
+
+		// Continue loop even after contacts are full 
+		// as existing contacts' normals/depths might be updated
+		// Break only if contacts are not important
+		if ((contactcount | CONTACTS_UNIMPORTANT) == (Flags & (NUMC_MASK | CONTACTS_UNIMPORTANT)))
+		{
+			break;
+		}
+
+		ccount++;
+	}
+	return true;
+}
+
+#endif // dTRIMESH_OPCODE
+#endif // dTRIMESH_USE_NEW_TRIMESH_TRIMESH_COLLIDER
+#endif // dTRIMESH_ENABLED
Index: /code/branches/ode/ode-0.9/ode/src/collision_util.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_util.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_util.cpp	(revision 216)
@@ -0,0 +1,612 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+some useful collision utility stuff. this includes some API utility
+functions that are defined in the public header files.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/odemath.h>
+#include "collision_util.h"
+
+//****************************************************************************
+
+int dCollideSpheres (dVector3 p1, dReal r1,
+		     dVector3 p2, dReal r2, dContactGeom *c)
+{
+  // printf ("d=%.2f  (%.2f %.2f %.2f) (%.2f %.2f %.2f) r1=%.2f r2=%.2f\n",
+  //	  d,p1[0],p1[1],p1[2],p2[0],p2[1],p2[2],r1,r2);
+
+  dReal d = dDISTANCE (p1,p2);
+  if (d > (r1 + r2)) return 0;
+  if (d <= 0) {
+    c->pos[0] = p1[0];
+    c->pos[1] = p1[1];
+    c->pos[2] = p1[2];
+    c->normal[0] = 1;
+    c->normal[1] = 0;
+    c->normal[2] = 0;
+    c->depth = r1 + r2;
+  }
+  else {
+    dReal d1 = dRecip (d);
+    c->normal[0] = (p1[0]-p2[0])*d1;
+    c->normal[1] = (p1[1]-p2[1])*d1;
+    c->normal[2] = (p1[2]-p2[2])*d1;
+    dReal k = REAL(0.5) * (r2 - r1 - d);
+    c->pos[0] = p1[0] + c->normal[0]*k;
+    c->pos[1] = p1[1] + c->normal[1]*k;
+    c->pos[2] = p1[2] + c->normal[2]*k;
+    c->depth = r1 + r2 - d;
+  }
+  return 1;
+}
+
+
+void dLineClosestApproach (const dVector3 pa, const dVector3 ua,
+			   const dVector3 pb, const dVector3 ub,
+			   dReal *alpha, dReal *beta)
+{
+  dVector3 p;
+  p[0] = pb[0] - pa[0];
+  p[1] = pb[1] - pa[1];
+  p[2] = pb[2] - pa[2];
+  dReal uaub = dDOT(ua,ub);
+  dReal q1 =  dDOT(ua,p);
+  dReal q2 = -dDOT(ub,p);
+  dReal d = 1-uaub*uaub;
+  if (d <= REAL(0.0001)) {
+    // @@@ this needs to be made more robust
+    *alpha = 0;
+    *beta  = 0;
+  }
+  else {
+    d = dRecip(d);
+    *alpha = (q1 + uaub*q2)*d;
+    *beta  = (uaub*q1 + q2)*d;
+  }
+}
+
+
+// given two line segments A and B with endpoints a1-a2 and b1-b2, return the
+// points on A and B that are closest to each other (in cp1 and cp2).
+// in the case of parallel lines where there are multiple solutions, a
+// solution involving the endpoint of at least one line will be returned.
+// this will work correctly for zero length lines, e.g. if a1==a2 and/or
+// b1==b2.
+//
+// the algorithm works by applying the voronoi clipping rule to the features
+// of the line segments. the three features of each line segment are the two
+// endpoints and the line between them. the voronoi clipping rule states that,
+// for feature X on line A and feature Y on line B, the closest points PA and
+// PB between X and Y are globally the closest points if PA is in V(Y) and
+// PB is in V(X), where V(X) is the voronoi region of X.
+
+void dClosestLineSegmentPoints (const dVector3 a1, const dVector3 a2,
+				const dVector3 b1, const dVector3 b2,
+				dVector3 cp1, dVector3 cp2)
+{
+  dVector3 a1a2,b1b2,a1b1,a1b2,a2b1,a2b2,n;
+  dReal la,lb,k,da1,da2,da3,da4,db1,db2,db3,db4,det;
+
+#define SET2(a,b) a[0]=b[0]; a[1]=b[1]; a[2]=b[2];
+#define SET3(a,b,op,c) a[0]=b[0] op c[0]; a[1]=b[1] op c[1]; a[2]=b[2] op c[2];
+
+  // check vertex-vertex features
+
+  SET3 (a1a2,a2,-,a1);
+  SET3 (b1b2,b2,-,b1);
+  SET3 (a1b1,b1,-,a1);
+  da1 = dDOT(a1a2,a1b1);
+  db1 = dDOT(b1b2,a1b1);
+  if (da1 <= 0 && db1 >= 0) {
+    SET2 (cp1,a1);
+    SET2 (cp2,b1);
+    return;
+  }
+
+  SET3 (a1b2,b2,-,a1);
+  da2 = dDOT(a1a2,a1b2);
+  db2 = dDOT(b1b2,a1b2);
+  if (da2 <= 0 && db2 <= 0) {
+    SET2 (cp1,a1);
+    SET2 (cp2,b2);
+    return;
+  }
+
+  SET3 (a2b1,b1,-,a2);
+  da3 = dDOT(a1a2,a2b1);
+  db3 = dDOT(b1b2,a2b1);
+  if (da3 >= 0 && db3 >= 0) {
+    SET2 (cp1,a2);
+    SET2 (cp2,b1);
+    return;
+  }
+
+  SET3 (a2b2,b2,-,a2);
+  da4 = dDOT(a1a2,a2b2);
+  db4 = dDOT(b1b2,a2b2);
+  if (da4 >= 0 && db4 <= 0) {
+    SET2 (cp1,a2);
+    SET2 (cp2,b2);
+    return;
+  }
+
+  // check edge-vertex features.
+  // if one or both of the lines has zero length, we will never get to here,
+  // so we do not have to worry about the following divisions by zero.
+
+  la = dDOT(a1a2,a1a2);
+  if (da1 >= 0 && da3 <= 0) {
+    k = da1 / la;
+    SET3 (n,a1b1,-,k*a1a2);
+    if (dDOT(b1b2,n) >= 0) {
+      SET3 (cp1,a1,+,k*a1a2);
+      SET2 (cp2,b1);
+      return;
+    }
+  }
+
+  if (da2 >= 0 && da4 <= 0) {
+    k = da2 / la;
+    SET3 (n,a1b2,-,k*a1a2);
+    if (dDOT(b1b2,n) <= 0) {
+      SET3 (cp1,a1,+,k*a1a2);
+      SET2 (cp2,b2);
+      return;
+    }
+  }
+
+  lb = dDOT(b1b2,b1b2);
+  if (db1 <= 0 && db2 >= 0) {
+    k = -db1 / lb;
+    SET3 (n,-a1b1,-,k*b1b2);
+    if (dDOT(a1a2,n) >= 0) {
+      SET2 (cp1,a1);
+      SET3 (cp2,b1,+,k*b1b2);
+      return;
+    }
+  }
+
+  if (db3 <= 0 && db4 >= 0) {
+    k = -db3 / lb;
+    SET3 (n,-a2b1,-,k*b1b2);
+    if (dDOT(a1a2,n) <= 0) {
+      SET2 (cp1,a2);
+      SET3 (cp2,b1,+,k*b1b2);
+      return;
+    }
+  }
+
+  // it must be edge-edge
+
+  k = dDOT(a1a2,b1b2);
+  det = la*lb - k*k;
+  if (det <= 0) {
+    // this should never happen, but just in case...
+    SET2(cp1,a1);
+    SET2(cp2,b1);
+    return;
+  }
+  det = dRecip (det);
+  dReal alpha = (lb*da1 -  k*db1) * det;
+  dReal beta  = ( k*da1 - la*db1) * det;
+  SET3 (cp1,a1,+,alpha*a1a2);
+  SET3 (cp2,b1,+,beta*b1b2);
+
+# undef SET2
+# undef SET3
+}
+
+
+// a simple root finding algorithm is used to find the value of 't' that
+// satisfies:
+//		d|D(t)|^2/dt = 0
+// where:
+//		|D(t)| = |p(t)-b(t)|
+// where p(t) is a point on the line parameterized by t:
+//		p(t) = p1 + t*(p2-p1)
+// and b(t) is that same point clipped to the boundary of the box. in box-
+// relative coordinates d|D(t)|^2/dt is the sum of three x,y,z components
+// each of which looks like this:
+//
+//	    t_lo     /
+//	      ______/    -->t
+//	     /     t_hi
+//	    /
+//
+// t_lo and t_hi are the t values where the line passes through the planes
+// corresponding to the sides of the box. the algorithm computes d|D(t)|^2/dt
+// in a piecewise fashion from t=0 to t=1, stopping at the point where
+// d|D(t)|^2/dt crosses from negative to positive.
+
+void dClosestLineBoxPoints (const dVector3 p1, const dVector3 p2,
+			    const dVector3 c, const dMatrix3 R,
+			    const dVector3 side,
+			    dVector3 lret, dVector3 bret)
+{
+  int i;
+
+  // compute the start and delta of the line p1-p2 relative to the box.
+  // we will do all subsequent computations in this box-relative coordinate
+  // system. we have to do a translation and rotation for each point.
+  dVector3 tmp,s,v;
+  tmp[0] = p1[0] - c[0];
+  tmp[1] = p1[1] - c[1];
+  tmp[2] = p1[2] - c[2];
+  dMULTIPLY1_331 (s,R,tmp);
+  tmp[0] = p2[0] - p1[0];
+  tmp[1] = p2[1] - p1[1];
+  tmp[2] = p2[2] - p1[2];
+  dMULTIPLY1_331 (v,R,tmp);
+
+  // mirror the line so that v has all components >= 0
+  dVector3 sign;
+  for (i=0; i<3; i++) {
+    if (v[i] < 0) {
+      s[i] = -s[i];
+      v[i] = -v[i];
+      sign[i] = -1;
+    }
+    else sign[i] = 1;
+  }
+
+  // compute v^2
+  dVector3 v2;
+  v2[0] = v[0]*v[0];
+  v2[1] = v[1]*v[1];
+  v2[2] = v[2]*v[2];
+
+  // compute the half-sides of the box
+  dReal h[3];
+  h[0] = REAL(0.5) * side[0];
+  h[1] = REAL(0.5) * side[1];
+  h[2] = REAL(0.5) * side[2];
+
+  // region is -1,0,+1 depending on which side of the box planes each
+  // coordinate is on. tanchor is the next t value at which there is a
+  // transition, or the last one if there are no more.
+  int region[3];
+  dReal tanchor[3];
+
+  // Denormals are a problem, because we divide by v[i], and then 
+  // multiply that by 0. Alas, infinity times 0 is infinity (!)
+  // We also use v2[i], which is v[i] squared. Here's how the epsilons 
+  // are chosen:
+  // float epsilon = 1.175494e-038 (smallest non-denormal number)
+  // double epsilon = 2.225074e-308 (smallest non-denormal number)
+  // For single precision, choose an epsilon such that v[i] squared is 
+  // not a denormal; this is for performance.
+  // For double precision, choose an epsilon such that v[i] is not a 
+  // denormal; this is for correctness. (Jon Watte on mailinglist)
+
+#if defined( dSINGLE )
+  const dReal tanchor_eps = REAL(1e-19);
+#else
+  const dReal tanchor_eps = REAL(1e-307);
+#endif
+
+  // find the region and tanchor values for p1
+  for (i=0; i<3; i++) {
+    if (v[i] > tanchor_eps) {
+      if (s[i] < -h[i]) {
+	region[i] = -1;
+	tanchor[i] = (-h[i]-s[i])/v[i];
+      }
+      else {
+	region[i] = (s[i] > h[i]);
+	tanchor[i] = (h[i]-s[i])/v[i];
+      }
+    }
+    else {
+      region[i] = 0;
+      tanchor[i] = 2;		// this will never be a valid tanchor
+    }
+  }
+
+  // compute d|d|^2/dt for t=0. if it's >= 0 then p1 is the closest point
+  dReal t=0;
+  dReal dd2dt = 0;
+  for (i=0; i<3; i++) dd2dt -= (region[i] ? v2[i] : 0) * tanchor[i];
+  if (dd2dt >= 0) goto got_answer;
+
+  do {
+    // find the point on the line that is at the next clip plane boundary
+    dReal next_t = 1;
+    for (i=0; i<3; i++) {
+      if (tanchor[i] > t && tanchor[i] < 1 && tanchor[i] < next_t)
+        next_t = tanchor[i];
+    }
+
+    // compute d|d|^2/dt for the next t
+    dReal next_dd2dt = 0;
+    for (i=0; i<3; i++) {
+      next_dd2dt += (region[i] ? v2[i] : 0) * (next_t - tanchor[i]);
+    }
+
+    // if the sign of d|d|^2/dt has changed, solution = the crossover point
+    if (next_dd2dt >= 0) {
+      dReal m = (next_dd2dt-dd2dt)/(next_t - t);
+      t -= dd2dt/m;
+      goto got_answer;
+    }
+
+    // advance to the next anchor point / region
+    for (i=0; i<3; i++) {
+      if (tanchor[i] == next_t) {
+	tanchor[i] = (h[i]-s[i])/v[i];
+	region[i]++;
+      }
+    }
+    t = next_t;
+    dd2dt = next_dd2dt;
+  }
+  while (t < 1);
+  t = 1;
+
+  got_answer:
+
+  // compute closest point on the line
+  for (i=0; i<3; i++) lret[i] = p1[i] + t*tmp[i];	// note: tmp=p2-p1
+
+  // compute closest point on the box
+  for (i=0; i<3; i++) {
+    tmp[i] = sign[i] * (s[i] + t*v[i]);
+    if (tmp[i] < -h[i]) tmp[i] = -h[i];
+    else if (tmp[i] > h[i]) tmp[i] = h[i];
+  }
+  dMULTIPLY0_331 (s,R,tmp);
+  for (i=0; i<3; i++) bret[i] = s[i] + c[i];
+}
+
+
+// given boxes (p1,R1,side1) and (p1,R1,side1), return 1 if they intersect
+// or 0 if not.
+
+int dBoxTouchesBox (const dVector3 p1, const dMatrix3 R1,
+		    const dVector3 side1, const dVector3 p2,
+		    const dMatrix3 R2, const dVector3 side2)
+{
+  // two boxes are disjoint if (and only if) there is a separating axis
+  // perpendicular to a face from one box or perpendicular to an edge from
+  // either box. the following tests are derived from:
+  //    "OBB Tree: A Hierarchical Structure for Rapid Interference Detection",
+  //    S.Gottschalk, M.C.Lin, D.Manocha., Proc of ACM Siggraph 1996.
+
+  // Rij is R1'*R2, i.e. the relative rotation between R1 and R2.
+  // Qij is abs(Rij)
+  dVector3 p,pp;
+  dReal A1,A2,A3,B1,B2,B3,R11,R12,R13,R21,R22,R23,R31,R32,R33,
+    Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p[0] = p2[0] - p1[0];
+  p[1] = p2[1] - p1[1];
+  p[2] = p2[2] - p1[2];
+  dMULTIPLY1_331 (pp,R1,p);		// get pp = p relative to body 1
+
+  // get side lengths / 2
+  A1 = side1[0]*REAL(0.5); A2 = side1[1]*REAL(0.5); A3 = side1[2]*REAL(0.5);
+  B1 = side2[0]*REAL(0.5); B2 = side2[1]*REAL(0.5); B3 = side2[2]*REAL(0.5);
+
+  // for the following tests, excluding computation of Rij, in the worst case,
+  // 15 compares, 60 adds, 81 multiplies, and 24 absolutes.
+  // notation: R1=[u1 u2 u3], R2=[v1 v2 v3]
+
+  // separating axis = u1,u2,u3
+  R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+  Q11 = dFabs(R11); Q12 = dFabs(R12); Q13 = dFabs(R13);
+  if (dFabs(pp[0]) > (A1 + B1*Q11 + B2*Q12 + B3*Q13)) return 0;
+  R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+  Q21 = dFabs(R21); Q22 = dFabs(R22); Q23 = dFabs(R23);
+  if (dFabs(pp[1]) > (A2 + B1*Q21 + B2*Q22 + B3*Q23)) return 0;
+  R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+  Q31 = dFabs(R31); Q32 = dFabs(R32); Q33 = dFabs(R33);
+  if (dFabs(pp[2]) > (A3 + B1*Q31 + B2*Q32 + B3*Q33)) return 0;
+
+  // separating axis = v1,v2,v3
+  if (dFabs(dDOT41(R2+0,p)) > (A1*Q11 + A2*Q21 + A3*Q31 + B1)) return 0;
+  if (dFabs(dDOT41(R2+1,p)) > (A1*Q12 + A2*Q22 + A3*Q32 + B2)) return 0;
+  if (dFabs(dDOT41(R2+2,p)) > (A1*Q13 + A2*Q23 + A3*Q33 + B3)) return 0;
+
+  // separating axis = u1 x (v1,v2,v3)
+  if (dFabs(pp[2]*R21-pp[1]*R31) > A2*Q31 + A3*Q21 + B2*Q13 + B3*Q12) return 0;
+  if (dFabs(pp[2]*R22-pp[1]*R32) > A2*Q32 + A3*Q22 + B1*Q13 + B3*Q11) return 0;
+  if (dFabs(pp[2]*R23-pp[1]*R33) > A2*Q33 + A3*Q23 + B1*Q12 + B2*Q11) return 0;
+
+  // separating axis = u2 x (v1,v2,v3)
+  if (dFabs(pp[0]*R31-pp[2]*R11) > A1*Q31 + A3*Q11 + B2*Q23 + B3*Q22) return 0;
+  if (dFabs(pp[0]*R32-pp[2]*R12) > A1*Q32 + A3*Q12 + B1*Q23 + B3*Q21) return 0;
+  if (dFabs(pp[0]*R33-pp[2]*R13) > A1*Q33 + A3*Q13 + B1*Q22 + B2*Q21) return 0;
+
+  // separating axis = u3 x (v1,v2,v3)
+  if (dFabs(pp[1]*R11-pp[0]*R21) > A1*Q21 + A2*Q11 + B2*Q33 + B3*Q32) return 0;
+  if (dFabs(pp[1]*R12-pp[0]*R22) > A1*Q22 + A2*Q12 + B1*Q33 + B3*Q31) return 0;
+  if (dFabs(pp[1]*R13-pp[0]*R23) > A1*Q23 + A2*Q13 + B1*Q32 + B2*Q31) return 0;
+
+  return 1;
+}
+
+//****************************************************************************
+// other utility functions
+
+void dInfiniteAABB (dxGeom *geom, dReal aabb[6])
+{
+  aabb[0] = -dInfinity;
+  aabb[1] = dInfinity;
+  aabb[2] = -dInfinity;
+  aabb[3] = dInfinity;
+  aabb[4] = -dInfinity;
+  aabb[5] = dInfinity;
+}
+
+
+//****************************************************************************
+// Helpers for Croteam's collider - by Nguyen Binh
+
+int dClipEdgeToPlane( dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane)
+{
+	// calculate distance of edge points to plane
+	dReal fDistance0 = dPointPlaneDistance(  vEpnt0 ,plPlane );
+	dReal fDistance1 = dPointPlaneDistance(  vEpnt1 ,plPlane );
+
+	// if both points are behind the plane
+	if ( fDistance0 < 0 && fDistance1 < 0 ) 
+	{
+		// do nothing
+		return 0;
+		// if both points in front of the plane
+	} 
+	else if ( fDistance0 > 0 && fDistance1 > 0 ) 
+	{
+		// accept them
+		return 1;
+		// if we have edge/plane intersection
+	} else if ((fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0)) 
+	{
+
+		// find intersection point of edge and plane
+		dVector3 vIntersectionPoint;
+		vIntersectionPoint[0]= vEpnt0[0]-(vEpnt0[0]-vEpnt1[0])*fDistance0/(fDistance0-fDistance1);
+		vIntersectionPoint[1]= vEpnt0[1]-(vEpnt0[1]-vEpnt1[1])*fDistance0/(fDistance0-fDistance1);
+		vIntersectionPoint[2]= vEpnt0[2]-(vEpnt0[2]-vEpnt1[2])*fDistance0/(fDistance0-fDistance1);
+
+		// clamp correct edge to intersection point
+		if ( fDistance0 < 0 ) 
+		{
+			dVector3Copy(vIntersectionPoint,vEpnt0);
+		} else 
+		{
+			dVector3Copy(vIntersectionPoint,vEpnt1);
+		}
+		return 1;
+	}
+	return 1;
+}
+
+// clip polygon with plane and generate new polygon points
+void		 dClipPolyToPlane( const dVector3 avArrayIn[], const int ctIn, 
+							  dVector3 avArrayOut[], int &ctOut, 
+							  const dVector4 &plPlane )
+{
+	// start with no output points
+	ctOut = 0;
+
+	int i0 = ctIn-1;
+
+	// for each edge in input polygon
+	for (int i1=0; i1<ctIn; i0=i1, i1++) {
+
+
+		// calculate distance of edge points to plane
+		dReal fDistance0 = dPointPlaneDistance(  avArrayIn[i0],plPlane );
+		dReal fDistance1 = dPointPlaneDistance(  avArrayIn[i1],plPlane );
+
+		// if first point is in front of plane
+		if( fDistance0 >= 0 ) {
+			// emit point
+			avArrayOut[ctOut][0] = avArrayIn[i0][0];
+			avArrayOut[ctOut][1] = avArrayIn[i0][1];
+			avArrayOut[ctOut][2] = avArrayIn[i0][2];
+			ctOut++;
+		}
+
+		// if points are on different sides
+		if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) {
+
+			// find intersection point of edge and plane
+			dVector3 vIntersectionPoint;
+			vIntersectionPoint[0]= avArrayIn[i0][0] - 
+				(avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1);
+			vIntersectionPoint[1]= avArrayIn[i0][1] - 
+				(avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1);
+			vIntersectionPoint[2]= avArrayIn[i0][2] - 
+				(avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1);
+
+			// emit intersection point
+			avArrayOut[ctOut][0] = vIntersectionPoint[0];
+			avArrayOut[ctOut][1] = vIntersectionPoint[1];
+			avArrayOut[ctOut][2] = vIntersectionPoint[2];
+			ctOut++;
+		}
+	}
+
+}
+
+void		 dClipPolyToCircle(const dVector3 avArrayIn[], const int ctIn, 
+							   dVector3 avArrayOut[], int &ctOut, 
+							   const dVector4 &plPlane ,dReal fRadius)
+{
+	// start with no output points
+	ctOut = 0;
+
+	int i0 = ctIn-1;
+
+	// for each edge in input polygon
+	for (int i1=0; i1<ctIn; i0=i1, i1++) 
+	{
+		// calculate distance of edge points to plane
+		dReal fDistance0 = dPointPlaneDistance(  avArrayIn[i0],plPlane );
+		dReal fDistance1 = dPointPlaneDistance(  avArrayIn[i1],plPlane );
+
+		// if first point is in front of plane
+		if( fDistance0 >= 0 ) 
+		{
+			// emit point
+			if (dVector3Length2(avArrayIn[i0]) <= fRadius*fRadius)
+			{
+				avArrayOut[ctOut][0] = avArrayIn[i0][0];
+				avArrayOut[ctOut][1] = avArrayIn[i0][1];
+				avArrayOut[ctOut][2] = avArrayIn[i0][2];
+				ctOut++;
+			}
+		}
+
+		// if points are on different sides
+		if( (fDistance0 > 0 && fDistance1 < 0) || ( fDistance0 < 0 && fDistance1 > 0) ) 
+		{
+
+			// find intersection point of edge and plane
+			dVector3 vIntersectionPoint;
+			vIntersectionPoint[0]= avArrayIn[i0][0] - 
+				(avArrayIn[i0][0]-avArrayIn[i1][0])*fDistance0/(fDistance0-fDistance1);
+			vIntersectionPoint[1]= avArrayIn[i0][1] - 
+				(avArrayIn[i0][1]-avArrayIn[i1][1])*fDistance0/(fDistance0-fDistance1);
+			vIntersectionPoint[2]= avArrayIn[i0][2] - 
+				(avArrayIn[i0][2]-avArrayIn[i1][2])*fDistance0/(fDistance0-fDistance1);
+
+			// emit intersection point
+			if (dVector3Length2(avArrayIn[i0]) <= fRadius*fRadius)
+			{
+				avArrayOut[ctOut][0] = vIntersectionPoint[0];
+				avArrayOut[ctOut][1] = vIntersectionPoint[1];
+				avArrayOut[ctOut][2] = vIntersectionPoint[2];
+				ctOut++;
+			}
+		}
+	}	
+}
+
Index: /code/branches/ode/ode-0.9/ode/src/collision_util.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/collision_util.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/collision_util.h	(revision 216)
@@ -0,0 +1,340 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+some useful collision utility stuff.
+
+*/
+
+#ifndef _ODE_COLLISION_UTIL_H_
+#define _ODE_COLLISION_UTIL_H_
+
+#include <ode/common.h>
+#include <ode/contact.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+
+
+// given a pointer `p' to a dContactGeom, return the dContactGeom at
+// p + skip bytes.
+#define CONTACT(p,skip) ((dContactGeom*) (((char*)p) + (skip)))
+
+#if 1
+#include "collision_kernel.h"
+// Fetches a contact
+inline dContactGeom* SAFECONTACT(int Flags, dContactGeom* Contacts, int Index, int Stride){
+	dIASSERT(Index >= 0 && Index < (Flags & NUMC_MASK));
+	return ((dContactGeom*)(((char*)Contacts) + (Index * Stride)));
+}
+#endif
+
+
+// if the spheres (p1,r1) and (p2,r2) collide, set the contact `c' and
+// return 1, else return 0.
+
+int dCollideSpheres (dVector3 p1, dReal r1,
+		     dVector3 p2, dReal r2, dContactGeom *c);
+
+
+// given two lines
+//    qa = pa + alpha* ua
+//    qb = pb + beta * ub
+// where pa,pb are two points, ua,ub are two unit length vectors, and alpha,
+// beta go from [-inf,inf], return alpha and beta such that qa and qb are
+// as close as possible
+
+void dLineClosestApproach (const dVector3 pa, const dVector3 ua,
+			   const dVector3 pb, const dVector3 ub,
+			   dReal *alpha, dReal *beta);
+
+
+// given a line segment p1-p2 and a box (center 'c', rotation 'R', side length
+// vector 'side'), compute the points of closest approach between the box
+// and the line. return these points in 'lret' (the point on the line) and
+// 'bret' (the point on the box). if the line actually penetrates the box
+// then the solution is not unique, but only one solution will be returned.
+// in this case the solution points will coincide.
+
+void dClosestLineBoxPoints (const dVector3 p1, const dVector3 p2,
+			    const dVector3 c, const dMatrix3 R,
+			    const dVector3 side,
+			    dVector3 lret, dVector3 bret);
+
+// 20 Apr 2004
+// Start code by Nguyen Binh
+int dClipEdgeToPlane(dVector3 &vEpnt0, dVector3 &vEpnt1, const dVector4& plPlane);
+// clip polygon with plane and generate new polygon points
+void dClipPolyToPlane(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane );
+
+void dClipPolyToCircle(const dVector3 avArrayIn[], const int ctIn, dVector3 avArrayOut[], int &ctOut, const dVector4 &plPlane ,dReal fRadius);
+
+// Some vector math
+inline void dVector3Subtract(const dVector3& a,const dVector3& b,dVector3& c)
+{
+	c[0] = a[0] - b[0];
+	c[1] = a[1] - b[1];
+	c[2] = a[2] - b[2];
+}
+
+// Some vector math
+inline void dVector3Scale(dVector3& a,dReal nScale)
+{
+	a[0] *= nScale ;
+	a[1] *= nScale ;
+	a[2] *= nScale ;
+}
+
+inline void dVector3Add(const dVector3& a,const dVector3& b,dVector3& c)
+{
+	c[0] = a[0] + b[0];
+	c[1] = a[1] + b[1];
+	c[2] = a[2] + b[2];
+}
+
+inline void dVector3Copy(const dVector3& a,dVector3& c)
+{
+	c[0] = a[0];
+	c[1] = a[1];
+	c[2] = a[2];
+}
+
+inline void dVector3Cross(const dVector3& a,const dVector3& b,dVector3& c)
+{
+	dCROSS(c,=,a,b);
+}
+
+inline dReal dVector3Length(const dVector3& a)
+{
+	return dSqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+}
+
+inline dReal dVector3Dot(const dVector3& a,const dVector3& b)
+{
+	return dDOT(a,b);
+}
+
+inline void dVector3Inv(dVector3& a)
+{
+	a[0] = -a[0];
+	a[1] = -a[1];
+	a[2] = -a[2];
+}
+
+inline dReal dVector3Length2(const dVector3& a)
+{
+	return (a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+}
+
+inline void dMat3GetCol(const dMatrix3& m,const int col, dVector3& v)
+{
+	v[0] = m[col + 0];
+	v[1] = m[col + 4];
+	v[2] = m[col + 8];
+}
+
+inline void dVector3CrossMat3Col(const dMatrix3& m,const int col,const dVector3& v,dVector3& r)
+{
+	r[0] =  v[1] * m[2*4 + col] - v[2] * m[1*4 + col]; 
+	r[1] =  v[2] * m[0*4 + col] - v[0] * m[2*4 + col]; 
+	r[2] =  v[0] * m[1*4 + col] - v[1] * m[0*4 + col];
+}
+
+inline void dMat3ColCrossVector3(const dMatrix3& m,const int col,const dVector3& v,dVector3& r)
+{
+	r[0] =   v[2] * m[1*4 + col] - v[1] * m[2*4 + col]; 
+	r[1] =   v[0] * m[2*4 + col] - v[2] * m[0*4 + col]; 
+	r[2] =   v[1] * m[0*4 + col] - v[0] * m[1*4 + col];
+}
+
+inline void dMultiplyMat3Vec3(const dMatrix3& m,const dVector3& v, dVector3& r)
+{
+	dMULTIPLY0_331(r,m,v);
+}
+
+inline dReal dPointPlaneDistance(const dVector3& point,const dVector4& plane)
+{
+	return (plane[0]*point[0] + plane[1]*point[1] + plane[2]*point[2] + plane[3]);
+}
+
+inline void dConstructPlane(const dVector3& normal,const dReal& distance, dVector4& plane)
+{
+	plane[0] = normal[0];
+	plane[1] = normal[1];
+	plane[2] = normal[2];
+	plane[3] = distance;
+}
+
+inline void dMatrix3Copy(const dReal* source,dMatrix3& dest)
+{
+	dest[0]	=	source[0];
+	dest[1]	=	source[1];
+	dest[2]	=	source[2];
+
+	dest[4]	=	source[4];
+	dest[5]	=	source[5];
+	dest[6]	=	source[6];
+
+	dest[8]	=	source[8];
+	dest[9]	=	source[9];
+	dest[10]=	source[10];
+}
+
+inline dReal dMatrix3Det( const dMatrix3& mat )
+{
+	dReal det;
+
+	det = mat[0] * ( mat[5]*mat[10] - mat[9]*mat[6] )
+		- mat[1] * ( mat[4]*mat[10] - mat[8]*mat[6] )
+		+ mat[2] * ( mat[4]*mat[9]  - mat[8]*mat[5] );
+
+	return( det );
+}
+
+
+inline void dMatrix3Inv( const dMatrix3& ma, dMatrix3& dst )
+{
+	dReal det = dMatrix3Det( ma );
+
+	if ( dFabs( det ) < REAL(0.0005) )
+	{
+		dRSetIdentity( dst );
+		return;
+	}
+
+	dst[0] =    ma[5]*ma[10] - ma[6]*ma[9]   / det;
+	dst[1] = -( ma[1]*ma[10] - ma[9]*ma[2] ) / det;
+	dst[2] =    ma[1]*ma[6]  - ma[5]*ma[2]   / det;
+
+	dst[4] = -( ma[4]*ma[10] - ma[6]*ma[8] ) / det;
+	dst[5] =    ma[0]*ma[10] - ma[8]*ma[2]   / det;
+	dst[6] = -( ma[0]*ma[6] - ma[4]*ma[2] ) / det;
+
+	dst[8] =    ma[4]*ma[9] - ma[8]*ma[5]   / det;
+	dst[9] = -( ma[0]*ma[9] - ma[8]*ma[1] ) / det;
+	dst[10] =    ma[0]*ma[5] - ma[1]*ma[4]   / det;
+}
+
+inline void dQuatTransform(const dQuaternion& quat,const dVector3& source,dVector3& dest)
+{
+
+	// Nguyen Binh : this code seem to be the fastest.
+	dReal x0 = 	source[0] * quat[0] + source[2] * quat[2] - source[1] * quat[3];
+	dReal x1 = 	source[1] * quat[0] + source[0] * quat[3] - source[2] * quat[1];
+	dReal x2 = 	source[2] * quat[0] + source[1] * quat[1] - source[0] * quat[2];
+	dReal x3 = 	source[0] * quat[1] + source[1] * quat[2] + source[2] * quat[3];
+
+	dest[0]  = 	quat[0] * x0 + quat[1] * x3 + quat[2] * x2 - quat[3] * x1;
+	dest[1]  = 	quat[0] * x1 + quat[2] * x3 + quat[3] * x0 - quat[1] * x2;
+	dest[2]  = 	quat[0] * x2 + quat[3] * x3 + quat[1] * x1 - quat[2] * x0;
+
+	/*
+	// nVidia SDK implementation
+	dVector3 uv, uuv; 
+	dVector3 qvec;
+	qvec[0] = quat[1];
+	qvec[1] = quat[2];
+	qvec[2] = quat[3];
+
+	dVector3Cross(qvec,source,uv);
+	dVector3Cross(qvec,uv,uuv);
+
+	dVector3Scale(uv,REAL(2.0)*quat[0]);
+	dVector3Scale(uuv,REAL(2.0));
+
+	dest[0] = source[0] + uv[0] + uuv[0];
+	dest[1] = source[1] + uv[1] + uuv[1];
+	dest[2] = source[2] + uv[2] + uuv[2];   
+	*/
+}
+
+inline void dQuatInvTransform(const dQuaternion& quat,const dVector3& source,dVector3& dest)
+{
+
+	dReal norm = quat[0]*quat[0] + quat[1]*quat[1] + quat[2]*quat[2] + quat[3]*quat[3];
+
+	if (norm > REAL(0.0))
+	{
+		dQuaternion invQuat;
+		invQuat[0] =  quat[0] / norm;
+		invQuat[1] = -quat[1] / norm;
+		invQuat[2] = -quat[2] / norm;
+		invQuat[3] = -quat[3] / norm;	
+		
+		dQuatTransform(invQuat,source,dest);
+
+	}
+	else
+	{
+		// Singular -> return identity
+		dVector3Copy(source,dest);
+	}
+}
+
+inline void dGetEulerAngleFromRot(const dMatrix3& mRot,dReal& rX,dReal& rY,dReal& rZ)
+{
+	rY = asin(mRot[0 * 4 + 2]);
+	if (rY < M_PI /2)
+	{
+		if (rY > -M_PI /2)
+		{
+			rX = atan2(-mRot[1*4 + 2], mRot[2*4 + 2]);
+			rZ = atan2(-mRot[0*4 + 1], mRot[0*4 + 0]);
+		}
+		else
+		{
+			// not unique
+			rX = -atan2(mRot[1*4 + 0], mRot[1*4 + 1]);
+			rZ = REAL(0.0);
+		}
+	}
+	else
+	{
+		// not unique
+		rX = atan2(mRot[1*4 + 0], mRot[1*4 + 1]);
+		rZ = REAL(0.0);
+	}
+}
+
+inline void dQuatInv(const dQuaternion& source, dQuaternion& dest)
+{
+	dReal norm = source[0]*source[0] + source[1]*source[1] + source[2]*source[2] + source[3]*source[3];
+
+	if (norm > 0.0f)
+	{
+		dest[0] = source[0] / norm;
+		dest[1] = -source[1] / norm;
+		dest[2] = -source[2] / norm;
+		dest[3] = -source[3] / norm;	
+	}
+	else
+	{
+		// Singular -> return identity
+		dest[0] = REAL(1.0);
+		dest[1] = REAL(0.0);
+		dest[2] = REAL(0.0);
+		dest[3] = REAL(0.0);
+	}
+}
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/convex.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/convex.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/convex.cpp	(revision 216)
@@ -0,0 +1,1294 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+Code for Convex Collision Detection
+By Rodrigo Hernandez
+*/
+//#include <algorithm>
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+#if _MSC_VER <= 1200
+#define dMIN(A,B)  ((A)>(B) ? B : A)
+#define dMAX(A,B)  ((A)>(B) ? A : B)
+#else
+#define dMIN(A,B)  std::min(A,B)
+#define dMAX(A,B)  std::max(A,B)
+#endif
+
+//****************************************************************************
+// Convex public API
+dxConvex::dxConvex (dSpaceID space,
+		    dReal *_planes,
+		    unsigned int _planecount,
+		    dReal *_points,
+		    unsigned int _pointcount,
+		    unsigned int *_polygons) : 
+  dxGeom (space,1)
+{
+  dAASSERT (_planes != NULL);
+  dAASSERT (_points != NULL);
+  dAASSERT (_polygons != NULL);
+  //fprintf(stdout,"dxConvex Constructor planes %X\n",_planes);
+  type = dConvexClass;
+  planes = _planes;
+  planecount = _planecount;
+  // we need points as well
+  points = _points;
+  pointcount = _pointcount;
+  polygons=_polygons;
+  FillEdges();
+}
+
+
+void dxConvex::computeAABB()
+{
+  // this can, and should be optimized
+  dVector3 point;
+  dMULTIPLY0_331 (point,final_posr->R,points);
+  aabb[0] = point[0]+final_posr->pos[0];
+  aabb[1] = point[0]+final_posr->pos[0];
+  aabb[2] = point[1]+final_posr->pos[1];
+  aabb[3] = point[1]+final_posr->pos[1];
+  aabb[4] = point[2]+final_posr->pos[2];
+  aabb[5] = point[2]+final_posr->pos[2];
+  for(unsigned int i=3;i<(pointcount*3);i+=3)
+    {
+      dMULTIPLY0_331 (point,final_posr->R,&points[i]);
+      aabb[0] = dMIN(aabb[0],point[0]+final_posr->pos[0]);
+      aabb[1] = dMAX(aabb[1],point[0]+final_posr->pos[0]);
+      aabb[2] = dMIN(aabb[2],point[1]+final_posr->pos[1]);
+      aabb[3] = dMAX(aabb[3],point[1]+final_posr->pos[1]);
+      aabb[4] = dMIN(aabb[4],point[2]+final_posr->pos[2]);
+      aabb[5] = dMAX(aabb[5],point[2]+final_posr->pos[2]);
+    }
+}
+
+/*! \brief Populates the edges set, should be called only once whenever
+  the polygon array gets updated */
+void dxConvex::FillEdges()
+{
+	unsigned int *points_in_poly=polygons;
+	unsigned int *index=polygons+1;
+	for(unsigned int i=0;i<planecount;++i)
+	{
+		//fprintf(stdout,"Points in Poly: %d\n",*points_in_poly);
+		for(unsigned int j=0;j<*points_in_poly;++j)
+		{
+			edges.insert(edge(dMIN(index[j],index[(j+1)%*points_in_poly]),
+				dMAX(index[j],index[(j+1)%*points_in_poly])));
+			//fprintf(stdout,"Insert %d-%d\n",index[j],index[(j+1)%*points_in_poly]);
+		}
+		points_in_poly+=(*points_in_poly+1);
+		index=points_in_poly+1;
+	}
+	/*
+	fprintf(stdout,"Edge Count: %d\n",edges.size());
+	for(std::set<edge>::iterator it=edges.begin();
+	it!=edges.end();
+	++it)
+	{
+	fprintf(stdout,"Edge: %d-%d\n",it->first,it->second);
+	}
+	*/
+}
+
+dGeomID dCreateConvex (dSpaceID space,dReal *_planes,unsigned int _planecount,
+		    dReal *_points,
+		       unsigned int _pointcount,
+		       unsigned int *_polygons)
+{
+  //fprintf(stdout,"dxConvex dCreateConvex\n");
+  return new dxConvex(space,_planes, _planecount,
+		      _points,
+		      _pointcount,
+		      _polygons);
+}
+
+void dGeomSetConvex (dGeomID g,dReal *_planes,unsigned int _planecount,
+		     dReal *_points,
+		     unsigned int _pointcount,
+		     unsigned int *_polygons)
+{
+  //fprintf(stdout,"dxConvex dGeomSetConvex\n");
+  dUASSERT (g && g->type == dConvexClass,"argument not a convex shape");
+  dxConvex *s = (dxConvex*) g;
+  s->planes = _planes;
+  s->planecount = _planecount;
+  s->points = _points;
+  s->pointcount = _pointcount;
+  s->polygons=_polygons;
+}
+
+//****************************************************************************
+// Helper Inlines
+//
+
+/*! \brief Returns Whether or not the segment ab intersects plane p
+  \param a origin of the segment
+  \param b segment destination
+  \param p plane to test for intersection
+  \param t returns the time "t" in the segment ray that gives us the intersecting 
+  point
+  \param q returns the intersection point
+  \return true if there is an intersection, otherwise false.
+*/
+bool IntersectSegmentPlane(dVector3 a, 
+			   dVector3 b, 
+			   dVector4 p, 
+			   dReal &t, 
+			   dVector3 q)
+{
+  // Compute the t value for the directed line ab intersecting the plane
+  dVector3 ab;
+  ab[0]= b[0] - a[0];
+  ab[1]= b[1] - a[1];
+  ab[2]= b[2] - a[2];
+  
+  t = (p[3] - dDOT(p,a)) / dDOT(p,ab);
+  
+  // If t in [0..1] compute and return intersection point
+  if (t >= 0.0 && t <= 1.0) 
+    {
+      q[0] = a[0] + t * ab[0];
+      q[1] = a[1] + t * ab[1];
+      q[2] = a[2] + t * ab[2];
+      return true;
+    }
+  // Else no intersection
+  return false;
+}
+
+/*! \brief Returns the Closest Point in Ray 1 to Ray 2
+  \param Origin1 The origin of Ray 1
+  \param Direction1 The direction of Ray 1
+  \param Origin1 The origin of Ray 2
+  \param Direction1 The direction of Ray 3
+  \param t the time "t" in Ray 1 that gives us the closest point 
+  (closest_point=Origin1+(Direction*t).
+  \return true if there is a closest point, false if the rays are paralell.
+*/
+inline bool ClosestPointInRay(const dVector3 Origin1,
+			      const dVector3 Direction1,
+			      const dVector3 Origin2,
+			      const dVector3 Direction2,
+			      dReal& t)
+{
+  dVector3 w = {Origin1[0]-Origin2[0],
+		Origin1[1]-Origin2[1],
+		Origin1[2]-Origin2[2]};
+  dReal a = dDOT(Direction1 , Direction1);
+  dReal b = dDOT(Direction1 , Direction2);
+  dReal c = dDOT(Direction2 , Direction2);
+  dReal d = dDOT(Direction1 , w);
+  dReal e = dDOT(Direction2 , w);
+  dReal denominator = (a*c)-(b*b);
+  if(denominator==0.0f)
+    {
+      return false;
+    }
+  t = ((a*e)-(b*d))/denominator;
+  return true;
+}
+
+/*! \brief Returns the Ray on which 2 planes intersect if they do.
+  \param p1 Plane 1
+  \param p2 Plane 2
+  \param p Contains the origin of the ray upon returning if planes intersect
+  \param d Contains the direction of the ray upon returning if planes intersect
+  \return true if the planes intersect, false if paralell.
+*/
+inline bool IntersectPlanes(const dVector4 p1, const dVector4 p2, dVector3 p, dVector3 d)
+{
+  // Compute direction of intersection line
+  //Cross(p1, p2,d);
+  dCROSS(d,=,p1,p2);
+  
+  // If d is (near) zero, the planes are parallel (and separated)
+  // or coincident, so they're not considered intersecting
+  dReal denom = dDOT(d, d);
+  if (denom < dEpsilon) return false;
+
+  dVector3 n;
+  n[0]=p1[3]*p2[0] - p2[3]*p1[0];
+  n[1]=p1[3]*p2[1] - p2[3]*p1[1];
+  n[2]=p1[3]*p2[2] - p2[3]*p1[2];
+  // Compute point on intersection line
+  //Cross(n, d,p);
+  dCROSS(p,=,n,d);
+  p[0]/=denom;
+  p[1]/=denom;
+  p[2]/=denom;
+  return true;
+}
+
+/*! \brief Finds out if a point lies inside a 2D polygon
+  \param p Point to test
+  \param polygon a pointer to the start of the convex polygon index buffer
+  \param out the closest point in the polygon if the point is not inside
+  \return true if the point lies inside of the polygon, false if not.
+*/
+inline bool IsPointInPolygon(dVector3 p,
+			     unsigned int *polygon,
+			     dxConvex *convex,
+			     dVector3 out)
+{
+  // p is the point we want to check,
+  // polygon is a pointer to the polygon we
+  // are checking against, remember it goes
+  // number of vertices then that many indexes
+  // out returns the closest point on the border of the
+  // polygon if the point is not inside it.
+  size_t pointcount=polygon[0];
+  dVector3 a;
+  dVector3 b;
+  dVector3 c;
+  dVector3 ab;
+  dVector3 ac;
+  dVector3 ap;
+  dVector3 bp;
+  dReal d1;
+  dReal d2;
+  dReal d3;
+  dReal d4;
+  dReal vc;
+  polygon++; // skip past pointcount
+  for(size_t i=0;i<pointcount;++i)
+    {
+      dMULTIPLY0_331 (a,convex->final_posr->R,&convex->points[(polygon[i]*3)]);
+      a[0]=convex->final_posr->pos[0]+a[0];
+      a[1]=convex->final_posr->pos[1]+a[1];
+      a[2]=convex->final_posr->pos[2]+a[2];
+
+      dMULTIPLY0_331 (b,convex->final_posr->R,
+		      &convex->points[(polygon[(i+1)%pointcount]*3)]);
+      b[0]=convex->final_posr->pos[0]+b[0];
+      b[1]=convex->final_posr->pos[1]+b[1];
+      b[2]=convex->final_posr->pos[2]+b[2];
+
+      dMULTIPLY0_331 (c,convex->final_posr->R,
+		      &convex->points[(polygon[(i+2)%pointcount]*3)]);
+      c[0]=convex->final_posr->pos[0]+c[0];
+      c[1]=convex->final_posr->pos[1]+c[1];
+      c[2]=convex->final_posr->pos[2]+c[2];
+
+      ab[0] = b[0] - a[0];
+      ab[1] = b[1] - a[1];
+      ab[2] = b[2] - a[2];
+      ac[0] = c[0] - a[0];
+      ac[1] = c[1] - a[1];
+      ac[2] = c[2] - a[2];
+      ap[0] = p[0] - a[0];
+      ap[1] = p[1] - a[1];
+      ap[2] = p[2] - a[2];
+      d1 = dDOT(ab,ap);
+      d2 = dDOT(ac,ap);
+      if (d1 <= 0.0f && d2 <= 0.0f)
+	{
+	  out[0]=a[0];
+	  out[1]=a[1];
+	  out[2]=a[2];
+	  return false;
+	}
+      bp[0] = p[0] - b[0];
+      bp[1] = p[1] - b[1];
+      bp[2] = p[2] - b[2];
+      d3 = dDOT(ab,bp);
+      d4 = dDOT(ac,bp);
+      if (d3 >= 0.0f && d4 <= d3)
+	{
+	  out[0]=b[0];
+	  out[1]=b[1];
+	  out[2]=b[2];
+	  return false;
+	}      
+      vc = d1*d4 - d3*d2;
+      if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) 
+	{
+	  dReal v = d1 / (d1 - d3);
+	  out[0] = a[0] + (ab[0]*v);
+	  out[1] = a[1] + (ab[1]*v);
+	  out[2] = a[2] + (ab[2]*v);
+	  return false;
+	}
+    }
+  return true;
+}
+
+int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags,
+						 dContactGeom *contact, int skip)
+{
+	dIASSERT (skip >= (int)sizeof(dContactGeom));
+	dIASSERT (o1->type == dConvexClass);
+	dIASSERT (o2->type == dPlaneClass);
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+	
+	dxConvex *Convex = (dxConvex*) o1;
+	dxPlane *Plane = (dxPlane*) o2;
+	unsigned int contacts=0;
+	unsigned int maxc = flags & NUMC_MASK;
+	dVector3 v2;
+
+#define LTEQ_ZERO	0x10000000
+#define GTEQ_ZERO	0x20000000
+#define BOTH_SIGNS	(LTEQ_ZERO | GTEQ_ZERO)
+	dIASSERT((BOTH_SIGNS & NUMC_MASK) == 0); // used in conditional operator later
+
+	unsigned int totalsign = 0;
+	for(unsigned int i=0;i<Convex->pointcount;++i)
+	{
+		dMULTIPLY0_331 (v2,Convex->final_posr->R,&Convex->points[(i*3)]);
+		dVector3Add(Convex->final_posr->pos, v2, v2);
+		
+		unsigned int distance2sign = GTEQ_ZERO;
+		dReal distance2 = dVector3Dot(Plane->p, v2) - Plane->p[3]; // Ax + By + Cz - D
+		if((distance2 <= REAL(0.0)))
+		{
+			distance2sign = distance2 != REAL(0.0) ? LTEQ_ZERO : BOTH_SIGNS;
+
+			if (contacts != maxc)
+			{
+				dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip);
+				dVector3Copy(Plane->p, target->normal);
+				dVector3Copy(v2, target->pos);
+				target->depth = -distance2;
+				target->g1 = Convex;
+				target->g2 = Plane;
+				contacts++;
+			}
+		}
+
+		// Take new sign into account
+		totalsign |= distance2sign;
+		// Check if contacts are full and both signs have been already found
+		if ((contacts ^ maxc | totalsign) == BOTH_SIGNS) // harder to comprehend but requires one register less
+		{
+			break; // Nothing can be changed any more
+		}
+	}
+	if (totalsign == BOTH_SIGNS) return contacts;
+	return 0;
+#undef BOTH_SIGNS
+#undef GTEQ_ZERO
+#undef LTEQ_ZERO
+}
+
+int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dSphereClass);
+  dIASSERT (o2->type == dConvexClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxSphere *Sphere = (dxSphere*) o1;
+  dxConvex *Convex = (dxConvex*) o2;
+  dReal dist,closestdist=dInfinity;
+  dVector4 plane;
+  // dVector3 contactpoint;
+  dVector3 offsetpos,out,temp;
+  unsigned int *pPoly=Convex->polygons;
+  int closestplane;
+  bool sphereinside=true;
+  /* 
+     Do a good old sphere vs plane check first,
+     if a collision is found then check if the contact point
+     is within the polygon
+  */
+  // offset the sphere final_posr->position into the convex space
+  offsetpos[0]=Sphere->final_posr->pos[0]-Convex->final_posr->pos[0];
+  offsetpos[1]=Sphere->final_posr->pos[1]-Convex->final_posr->pos[1];
+  offsetpos[2]=Sphere->final_posr->pos[2]-Convex->final_posr->pos[2];
+  //fprintf(stdout,"Begin Check\n");  
+  for(unsigned int i=0;i<Convex->planecount;++i)
+    {
+      // apply rotation to the plane
+      dMULTIPLY0_331(plane,Convex->final_posr->R,&Convex->planes[(i*4)]);
+      plane[3]=(&Convex->planes[(i*4)])[3];
+      // Get the distance from the sphere origin to the plane
+      dist = dVector3Dot(plane, offsetpos) - plane[3]; // Ax + By + Cz - D
+      if(dist>0)
+	{
+	  // if we get here, we know the center of the sphere is
+	  // outside of the convex hull.
+	  if(dist<Sphere->radius)
+	    {
+	      // if we get here we know the sphere surface penetrates
+	      // the plane
+	      if(IsPointInPolygon(Sphere->final_posr->pos,pPoly,Convex,out))
+		{
+		  // finally if we get here we know that the
+		  // sphere is directly touching the inside of the polyhedron
+		  //fprintf(stdout,"Contact! distance=%f\n",dist);
+		  contact->normal[0] = plane[0];
+		  contact->normal[1] = plane[1];
+		  contact->normal[2] = plane[2];
+		  contact->pos[0] = Sphere->final_posr->pos[0]+
+		    (-contact->normal[0]*Sphere->radius);
+		  contact->pos[1] = Sphere->final_posr->pos[1]+
+		    (-contact->normal[1]*Sphere->radius);
+		  contact->pos[2] = Sphere->final_posr->pos[2]+
+		    (-contact->normal[2]*Sphere->radius);
+		  contact->depth = Sphere->radius-dist;
+		  contact->g1 = Sphere;
+		  contact->g2 = Convex;
+		  return 1;
+		}
+	      else
+		{
+		  // the sphere may not be directly touching
+		  // the polyhedron, but it may be touching
+		  // a point or an edge, if the distance between
+		  // the closest point on the poly (out) and the 
+		  // center of the sphere is less than the sphere 
+		  // radius we have a hit.
+		  temp[0] = (Sphere->final_posr->pos[0]-out[0]);
+		  temp[1] = (Sphere->final_posr->pos[1]-out[1]);
+		  temp[2] = (Sphere->final_posr->pos[2]-out[2]);
+		  dist=(temp[0]*temp[0])+(temp[1]*temp[1])+(temp[2]*temp[2]);
+		  // avoid the sqrt unless really necesary
+		  if(dist<(Sphere->radius*Sphere->radius))
+		    {
+		      // We got an indirect hit
+		      dist=dSqrt(dist);
+		      contact->normal[0] = temp[0]/dist;
+		      contact->normal[1] = temp[1]/dist;
+		      contact->normal[2] = temp[2]/dist;
+		      contact->pos[0] = Sphere->final_posr->pos[0]+
+			(-contact->normal[0]*Sphere->radius);
+		      contact->pos[1] = Sphere->final_posr->pos[1]+
+			(-contact->normal[1]*Sphere->radius);
+		      contact->pos[2] = Sphere->final_posr->pos[2]+
+			(-contact->normal[2]*Sphere->radius);
+		      contact->depth = Sphere->radius-dist;
+		      contact->g1 = Sphere;
+		      contact->g2 = Convex;
+		      return 1;
+		    }
+		}
+	    }
+	  sphereinside=false;
+	}
+      if(sphereinside)
+	{
+	  if(closestdist>dFabs(dist))
+	    {
+	      closestdist=dFabs(dist);
+	      closestplane=i;
+	    }
+	}
+      pPoly+=pPoly[0]+1;
+    }
+    if(sphereinside)
+      {
+	// if the center of the sphere is inside 
+	// the Convex, we need to pop it out
+	dMULTIPLY0_331(contact->normal,
+		       Convex->final_posr->R,
+		       &Convex->planes[(closestplane*4)]);
+	contact->pos[0] = Sphere->final_posr->pos[0];
+	contact->pos[1] = Sphere->final_posr->pos[1];
+	contact->pos[2] = Sphere->final_posr->pos[2];
+	contact->depth = closestdist+Sphere->radius;
+	contact->g1 = Sphere;
+	contact->g2 = Convex;
+	return 1;
+      }
+  return 0;
+}
+
+int dCollideConvexBox (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dConvexClass);
+  dIASSERT (o2->type == dBoxClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+  
+  dxConvex *Convex = (dxConvex*) o1;
+  dxBox *Box = (dxBox*) o2;
+  
+  return 0;
+}
+
+int dCollideConvexCapsule (dxGeom *o1, dxGeom *o2,
+			     int flags, dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dConvexClass);
+  dIASSERT (o2->type == dCapsuleClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxConvex *Convex = (dxConvex*) o1;
+  dxCapsule *Capsule = (dxCapsule*) o2;
+  
+  return 0;
+}
+
+/*!
+  \brief Retrieves the proper convex and plane index between 2 convex objects.
+
+  Seidel's Algorithm does not discriminate between 2 different Convex Hulls,
+  it only cares about planes, so we feed it the planes of Convex 1 followed
+  by the planes of Convex 2 as a single collection of planes, 
+  given an index into the single collection, 
+  this function determines the correct convex object and index to retrieve
+  the current plane.
+  
+  \param c1 Convex 1
+  \param c2 Convex 2
+  \param i Plane Index to retrieve
+  \param index contains the translated index uppon return
+  \return a pointer to the convex object containing plane index "i"
+*/
+inline dxConvex* GetPlaneIndex(dxConvex& c1, 
+			       dxConvex& c2,
+			       unsigned int i,unsigned int& index)
+{
+  if(i>=c1.planecount)
+    {
+      index = i-c1.planecount;
+      return &c2;
+    }
+  index=i;
+  return &c1;
+}
+
+inline void dumpplanes(dxConvex& cvx)
+{
+	// This is just a dummy debug function
+	dVector4 plane;
+	fprintf(stdout,"DUMP PLANES\n");
+	for (unsigned int i=0;i<cvx.planecount;++i)
+	{
+		dMULTIPLY0_331(plane,cvx.final_posr->R,&cvx.planes[(i*4)]);      
+		// Translate
+		plane[3]=
+			(cvx.planes[(i*4)+3])+
+			((plane[0] * cvx.final_posr->pos[0]) + 
+			(plane[1] * cvx.final_posr->pos[1]) + 
+			(plane[2] * cvx.final_posr->pos[2]));
+		fprintf(stdout,"%f %f %f %f\n",plane[0],plane[1],plane[2],plane[3]);
+	}
+}
+
+// this variable is for debuggin purpuses only, should go once everything works
+static bool hit=false;
+
+/*
+  \brief Tests whether 2 convex objects collide
+
+  Seidel's algorithm is a method to solve linear programs, 
+  it finds the optimum vertex "v" of a set of functions, 
+  in our case, the set of functions are the plane functions
+  for the 2 convex objects being tested.
+  We don't really care about the value optimum vertex though,
+  but the 2 convex objects only collide if this vertex exists,
+  otherwise, the set of functions is said to be "empty" or "void".
+
+  Seidel's Original algorithm is recursive and not bound to any number
+  of dimensions, the one I present here is Iterative rather than recursive
+  and bound to 3 dimensions, which is what we care about.
+  
+  If you're interested (and you should be!) on the algorithm, the paper
+  by Raimund Seidel himself should explain a lot better than I did, you can
+  find it here: http://www.cs.berkeley.edu/~jrs/meshpapers/SeidelLP.pdf
+
+  If posible, read the section about Linear Programming in 
+  Christer Ericson's RealTime Collision Detection book.
+  
+  \note currently there seem to be some issues with this function since
+  it doesn't detect collisions except for the most simple tests :(. 
+*/
+bool SeidelLP(dxConvex& cvx1,dxConvex& cvx2)
+{
+	dVector3 c={1,0,0}; // The Objective vector can be anything
+	dVector3 solution;    // We dont really need the solution so its local
+	dxConvex *cvx;
+	unsigned int index;
+	unsigned int planecount=cvx1.planecount+cvx2.planecount;
+	dReal sum,min,max,med;
+	dVector3 c1; // ,c2;
+	dVector4 aoveral,aoveram; // these will contain cached computations
+	unsigned int l,m,n; // l and m are the axes to the zerod dimensions, n is the axe for the last dimension
+	unsigned int i,j,k;
+	dVector4 eq1,eq2,eq3; // cached equations for 3d,2d and 1d respectivelly
+	// Get the support mapping for a HUGE bounding box in direction c
+	solution[0]= (c[0]>0) ? dInfinity : -dInfinity;
+	solution[1]= (c[1]>0) ? dInfinity : -dInfinity;
+	solution[2]= (c[2]>0) ? dInfinity : -dInfinity;
+	for( i=0;i<planecount;++i)
+	{
+		// Isolate plane equation
+		cvx=GetPlaneIndex(cvx1,cvx2,i,index);
+		// Rotate
+		dMULTIPLY0_331(eq1,cvx->final_posr->R,&cvx->planes[(index*4)]);
+
+		// Translate
+		eq1[3]=(cvx->planes[(index*4)+3])+
+			((eq1[0] * cvx->final_posr->pos[0]) + 
+			(eq1[1] * cvx->final_posr->pos[1]) + 
+			(eq1[2] * cvx->final_posr->pos[2]));
+		//       if(!hit)
+		// 	{
+		// 	  fprintf(stdout,"Plane I %d: %f %f %f %f\n",i,
+		// 		  cvx->planes[(index*4)+0],
+		// 		  cvx->planes[(index*4)+1],
+		// 		  cvx->planes[(index*4)+2],
+		// 		  cvx->planes[(index*4)+3]);
+		// 	  fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",i,
+		// 		  eq1[0],
+		// 		  eq1[1],eq1[2],eq1[3]);
+		// 	  fprintf(stdout,"POS %f,%f,%f\n",
+		// 		  cvx->final_posr->pos[0],
+		// 		  cvx->final_posr->pos[1],
+		// 		  cvx->final_posr->pos[2]);
+		// 	}
+		// find if the solution is behind the current plane
+		sum=
+			((eq1[0]*solution[0])+
+			(eq1[1]*solution[1])+
+			(eq1[2]*solution[2]))-eq1[3];
+		// if not we need to discard the current solution
+		if(sum>0)
+		{
+			// go down a dimension by eliminating a variable
+			// first find l
+			l=0;
+			for( j=0;j<3;++j)
+			{
+				if(fabs(eq1[j])>fabs(eq1[l]))
+				{
+					l=j;
+				}
+			}
+			if(eq1[l]==0)
+			{
+				if(!hit) 
+				{
+					fprintf(stdout,"Plane %d: %f %f %f %f is invalid\n",i,
+						eq1[0],eq1[1],eq1[2],eq1[3]);
+				}
+				return false; 
+			}
+			// then compute a/a[l] c1 and solution
+			aoveral[0]=eq1[0]/eq1[l];
+			aoveral[1]=eq1[1]/eq1[l];
+			aoveral[2]=eq1[2]/eq1[l];
+			aoveral[3]=eq1[3]/eq1[l];
+			c1[0]=c[0]-((c[l]/eq1[l])*eq1[0]);
+			c1[1]=c[1]-((c[l]/eq1[l])*eq1[1]);
+			c1[2]=c[2]-((c[l]/eq1[l])*eq1[2]);
+			solution[0]=solution[0]-((solution[l]/eq1[l])*eq1[0]);
+			solution[1]=solution[1]-((solution[l]/eq1[l])*eq1[1]);
+			solution[2]=solution[2]-((solution[l]/eq1[l])*eq1[2]);
+			// iterate a to get the new equations with the help of a/a[l]
+			for( j=0;j<planecount;++j)
+			{
+				if(i!=j)
+				{
+					cvx=GetPlaneIndex(cvx1,cvx2,j,index);
+					// Rotate
+					dMULTIPLY0_331(eq2,cvx->final_posr->R,&cvx->planes[(index*4)]);
+					// Translate
+					eq2[3]=(cvx->planes[(index*4)+3])+
+						((eq2[0] * cvx->final_posr->pos[0]) + 
+						(eq2[1] * cvx->final_posr->pos[1]) + 
+						(eq2[2] * cvx->final_posr->pos[2]));
+
+					//       if(!hit)
+					// 	{
+					// 	  fprintf(stdout,"Plane J %d: %f %f %f %f\n",j,
+					// 		  cvx->planes[(index*4)+0],
+					// 		  cvx->planes[(index*4)+1],
+					// 		  cvx->planes[(index*4)+2],
+					// 		  cvx->planes[(index*4)+3]);
+					// 	  fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",j,
+					// 		  eq2[0],
+					// 		  eq2[1],
+					// 		  eq2[2],
+					// 		  eq2[3]);
+					// 	  fprintf(stdout,"POS %f,%f,%f\n",
+					// 		  cvx->final_posr->pos[0],
+					// 		  cvx->final_posr->pos[1],
+					// 		  cvx->final_posr->pos[2]);
+					// 	}
+
+					// Take The equation down a dimension
+					eq2[0]-=(cvx->planes[(index*4)+l]*aoveral[0]);
+					eq2[1]-=(cvx->planes[(index*4)+l]*aoveral[1]);
+					eq2[2]-=(cvx->planes[(index*4)+l]*aoveral[2]);
+					eq2[3]-=(cvx->planes[(index*4)+l]*aoveral[3]);
+					sum=
+						((eq2[0]*solution[0])+
+						(eq2[1]*solution[1])+
+						(eq2[2]*solution[2]))-eq2[3];
+					if(sum>0)
+					{
+						m=0;
+						for( k=0;k<3;++k)
+						{
+							if(fabs(eq2[k])>fabs(eq2[m]))
+							{
+								m=k;
+							}
+						}
+						if(eq2[m]==0)
+						{
+							/* 
+							if(!hit) fprintf(stdout,
+							"Plane %d: %f %f %f %f is invalid\n",j,
+							eq2[0],eq2[1],eq2[2],eq2[3]);
+							*/
+							return false; 
+						}
+						// then compute a/a[m] c1 and solution
+						aoveram[0]=eq2[0]/eq2[m];
+						aoveram[1]=eq2[1]/eq2[m];
+						aoveram[2]=eq2[2]/eq2[m];
+						aoveram[3]=eq2[3]/eq2[m];
+						c1[0]=c[0]-((c[m]/eq2[m])*eq2[0]);
+						c1[1]=c[1]-((c[m]/eq2[m])*eq2[1]);
+						c1[2]=c[2]-((c[m]/eq2[m])*eq2[2]);
+						solution[0]=solution[0]-((solution[m]/eq2[m])*eq2[0]);
+						solution[1]=solution[1]-((solution[m]/eq2[m])*eq2[1]);
+						solution[2]=solution[2]-((solution[m]/eq2[m])*eq2[2]);
+						// figure out the value for n by elimination
+						n = (l==0) ? ((m==1)? 2:1):((m==0)?((l==1)?2:1):0);
+						// iterate a to get the new equations with the help of a/a[l]
+						min=-dInfinity;
+						max=med=dInfinity;
+						for(k=0;k<planecount;++k)
+						{
+							if((i!=k)&&(j!=k))
+							{
+								cvx=GetPlaneIndex(cvx1,cvx2,k,index);
+								// Rotate
+								dMULTIPLY0_331(eq3,cvx->final_posr->R,&cvx->planes[(index*4)]);
+								// Translate
+								eq3[3]=(cvx->planes[(index*4)+3])+
+									((eq3[0] * cvx->final_posr->pos[0]) + 
+									(eq3[1] * cvx->final_posr->pos[1]) + 
+									(eq3[2] * cvx->final_posr->pos[2]));
+								//       if(!hit)
+								// 	{
+								// 	  fprintf(stdout,"Plane K %d: %f %f %f %f\n",k,
+								// 		  cvx->planes[(index*4)+0],
+								// 		  cvx->planes[(index*4)+1],
+								// 		  cvx->planes[(index*4)+2],
+								// 		  cvx->planes[(index*4)+3]);
+								// 	  fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",k,
+								// 		  eq3[0],
+								// 		  eq3[1],
+								// 		  eq3[2],
+								// 		  eq3[3]);
+								// 	  fprintf(stdout,"POS %f,%f,%f\n",
+								// 		  cvx->final_posr->pos[0],
+								// 		  cvx->final_posr->pos[1],
+								// 		  cvx->final_posr->pos[2]);
+								// 	}
+
+								// Take the equation Down to 1D
+								eq3[0]-=(cvx->planes[(index*4)+m]*aoveram[0]);
+								eq3[1]-=(cvx->planes[(index*4)+m]*aoveram[1]);
+								eq3[2]-=(cvx->planes[(index*4)+m]*aoveram[2]);
+								eq3[3]-=(cvx->planes[(index*4)+m]*aoveram[3]);
+								if(eq3[n]>0)
+								{
+									max=dMIN(max,eq3[3]/eq3[n]);
+								}
+								else if(eq3[n]<0)
+								{
+									min=dMAX(min,eq3[3]/eq3[n]);
+								}
+								else
+								{
+									med=dMIN(med,eq3[3]);
+								}
+							}
+						}
+						if ((max<min)||(med<0)) 
+						{
+							// 			  if(!hit) fprintf(stdout,"((max<min)||(med<0)) ((%f<%f)||(%f<0))",max,min,med);
+							if(!hit)
+							{
+								dumpplanes(cvx1);
+								dumpplanes(cvx2);
+							}
+							//fprintf(stdout,"Planes %d %d\n",i,j);
+							return false;
+
+						}
+						// find the value for the solution in one dimension
+						solution[n] = (c1[n]>=0) ? max:min;
+						// lift to 2D
+						solution[m] = (eq2[3]-(eq2[n]*solution[n]))/eq2[m];
+						// lift to 3D
+						solution[l] = (eq1[3]-(eq1[m]*solution[m]+
+							eq1[n]*solution[n]))/eq1[l];
+					}
+				}
+			}
+		}
+	}
+	return true;
+}
+
+/*! \brief A Support mapping function for convex shapes
+  \param dir direction to find the Support Point for
+  \param cvx convex object to find the support point for
+  \param out the support mapping in dir.
+ */
+inline void Support(dVector3 dir,dxConvex& cvx,dVector3 out)
+{
+	unsigned int index = 0;
+	dVector3 point;
+	dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points);
+	point[0]+=cvx.final_posr->pos[0];
+	point[1]+=cvx.final_posr->pos[1];
+	point[2]+=cvx.final_posr->pos[2];
+
+	dReal max = dDOT(point,dir);
+	dReal tmp;
+	for (unsigned int i = 1; i < cvx.pointcount; ++i) 
+	{
+		dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points+(i*3));
+		point[0]+=cvx.final_posr->pos[0];
+		point[1]+=cvx.final_posr->pos[1];
+		point[2]+=cvx.final_posr->pos[2];      
+		tmp = dDOT(point, dir);
+		if (tmp > max) 
+		{ 
+			out[0]=point[0];
+			out[1]=point[1];
+			out[2]=point[2];
+			max = tmp; 
+		}
+	}
+}
+
+inline void ComputeInterval(dxConvex& cvx,dVector4 axis,dReal& min,dReal& max)
+{
+	dVector3 point;
+	dReal value;
+	//fprintf(stdout,"Compute Interval Axis %f,%f,%f\n",axis[0],axis[1],axis[2]);
+	dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points);
+	//fprintf(stdout,"initial point %f,%f,%f\n",point[0],point[1],point[2]);
+	point[0]+=cvx.final_posr->pos[0];
+	point[1]+=cvx.final_posr->pos[1];
+	point[2]+=cvx.final_posr->pos[2];
+	max = min = dDOT(axis,cvx.points);
+	for (unsigned int i = 1; i < cvx.pointcount; ++i) 
+	{
+		dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points+(i*3));
+		point[0]+=cvx.final_posr->pos[0];
+		point[1]+=cvx.final_posr->pos[1];
+		point[2]+=cvx.final_posr->pos[2];
+		value=dDOT(axis,point);
+		if(value<min)
+		{
+			min=value;
+		}
+		else if(value>max)
+		{
+			max=value;
+		}
+	}
+	//fprintf(stdout,"Compute Interval Min Max %f,%f\n",min,max);
+}
+
+/*! \brief Does an axis separation test between the 2 convex shapes
+using faces and edges */
+int TestConvexIntersection(dxConvex& cvx1,dxConvex& cvx2, int flags,
+						   dContactGeom *contact, int skip)
+{
+	dVector4 plane,savedplane;
+	dReal min1,max1,min2,max2,min_depth=-dInfinity;
+	dVector3 e1,e2,t;
+	int maxc = flags & NUMC_MASK; // this is causing a segfault
+	dIASSERT(maxc != 0);
+	dxConvex *g1,*g2;
+	unsigned int *pPoly;
+	dVector3 v;
+	// Test faces of cvx1 for separation
+	pPoly=cvx1.polygons;
+	for(unsigned int i=0;i<cvx1.planecount;++i)
+	{
+		// -- Apply Transforms --
+		// Rotate
+		dMULTIPLY0_331(plane,cvx1.final_posr->R,cvx1.planes+(i*4));
+		dNormalize3(plane);
+		// Translate
+		plane[3]=
+			(cvx1.planes[(i*4)+3])+
+			((plane[0] * cvx1.final_posr->pos[0]) + 
+			(plane[1] * cvx1.final_posr->pos[1]) + 
+			(plane[2] * cvx1.final_posr->pos[2]));
+		ComputeInterval(cvx1,plane,min1,max1);
+		ComputeInterval(cvx2,plane,min2,max2);
+		//fprintf(stdout,"width %f\n",max1-min1);
+		if(max2<min1 || max1<min2) return 0;
+#if 1
+		// this one ON works
+		else if ((max1>min2)&&(max1<max2))
+		{
+			min_depth=max1-min2;
+			savedplane[0]=plane[0];
+			savedplane[1]=plane[1];
+			savedplane[2]=plane[2];
+			savedplane[3]=plane[3];
+			g1=&cvx2; // cvx2 moves
+			g2=&cvx1;
+		}
+#endif
+		pPoly+=pPoly[0]+1;
+	}
+	// Test faces of cvx2 for separation
+	pPoly=cvx2.polygons;
+	for(unsigned int i=0;i<cvx2.planecount;++i)
+	{
+		//       fprintf(stdout,"Poly verts %d\n",pPoly[0]);
+		// -- Apply Transforms --
+		// Rotate
+		dMULTIPLY0_331(plane,
+			cvx2.final_posr->R,
+			cvx2.planes+(i*4));
+		dNormalize3(plane);
+		// Translate
+		plane[3]=
+			(cvx2.planes[(i*4)+3])+
+			((plane[0] * cvx2.final_posr->pos[0]) + 
+			(plane[1] * cvx2.final_posr->pos[1]) + 
+			(plane[2] * cvx2.final_posr->pos[2]));
+		ComputeInterval(cvx2,plane,min1,max1);
+		ComputeInterval(cvx1,plane,min2,max2);
+		//fprintf(stdout,"width %f\n",max1-min1);
+		if(max2<min1 || max1<min2) return 0;
+#if 1
+		// this one ON does not work
+		else if ((max1>min2)&&(max1<max2))
+		{
+			min_depth=max1-min2;
+			savedplane[0]=plane[0];
+			savedplane[1]=plane[1];
+			savedplane[2]=plane[2];
+			savedplane[3]=plane[3];
+			g1=&cvx1; // cvx1 moves
+			g2=&cvx2;
+		}
+#endif
+		pPoly+=pPoly[0]+1;
+	}
+	// Test cross products of pairs of edges
+	for(std::set<edge>::iterator i = cvx1.edges.begin();
+		i!= cvx1.edges.end();
+		++i)
+	{
+		// we only need to apply rotation here
+		dMULTIPLY0_331 (t,cvx1.final_posr->R,cvx1.points+(i->first*3));
+		dMULTIPLY0_331 (e1,cvx1.final_posr->R,cvx1.points+(i->second*3));
+		e1[0]-=t[0];
+		e1[1]-=t[1];
+		e1[2]-=t[2];
+		for(std::set<edge>::iterator j = cvx2.edges.begin();
+			j!= cvx2.edges.end();
+			++j)
+		{
+			// we only need to apply rotation here
+			dMULTIPLY0_331 (t,cvx2.final_posr->R,cvx2.points+(j->first*3));
+			dMULTIPLY0_331 (e2,cvx2.final_posr->R,cvx2.points+(j->second*3));
+			e2[0]-=t[0];
+			e2[1]-=t[1];
+			e2[2]-=t[2];
+			dCROSS(plane,=,e1,e2);
+			plane[3]=0;
+			ComputeInterval(cvx1,plane,min1,max1);
+			ComputeInterval(cvx2,plane,min2,max2);
+			if(max2<min1 || max1 < min2) return 0;
+		}      
+	}
+/* -- uncomment if you are debugging
+	static int  cvxhit=0;
+	if(cvxhit<2)
+		fprintf(stdout,"Plane: %f,%f,%f,%f\n",
+		(double)savedplane[0],
+		(double)savedplane[1],
+		(double)savedplane[2],
+		(double)savedplane[3]);
+*/
+	// If we get here, there was a collision
+	int contacts=0;
+	for(unsigned int i=0;i<g1->pointcount;++i)
+	{
+		dMULTIPLY0_331 (v,g1->final_posr->R,&g1->points[(i*3)]);
+		dVector3Add(g1->final_posr->pos, v, v);
+
+		dReal distance = dVector3Dot(savedplane, v) - savedplane[3]; // Ax + By + Cz - D
+		if(distance<0)
+		{
+			dContactGeom *target = SAFECONTACT(flags, contact, contacts, skip);
+			dVector3Copy(savedplane, target->normal);
+			dVector3Copy(v, target->pos);
+			target->depth = -distance;
+			target->g1 = g1;
+			target->g2 = g2;
+/* -- uncomment if you are debugging
+			if(cvxhit<2)
+				fprintf(stdout,"Contact: %f,%f,%f depth %f\n",
+				(double)target->pos[0],
+				(double)target->pos[1],
+				(double)target->pos[2],
+				(double)target->depth);
+*/
+			contacts++;
+			if (contacts==maxc) break;
+		}
+	}
+/* -- uncomment if you are debugging
+	cvxhit++;
+*/
+
+	return contacts;
+}
+
+int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dConvexClass);
+  dIASSERT (o2->type == dConvexClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+//   if(!hit) fprintf(stdout,"dCollideConvexConvex\n");
+  dxConvex *Convex1 = (dxConvex*) o1;
+  dxConvex *Convex2 = (dxConvex*) o2;
+  int contacts;
+  if(contacts=TestConvexIntersection(*Convex1,*Convex2,flags,
+				     contact,skip))
+    {
+      //fprintf(stdout,"We have a Hit!\n");
+    }
+  return contacts;
+}
+
+#if 0
+
+int dCollideRayConvex (dxGeom *o1, dxGeom *o2, int flags, 
+		       dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT( o1->type == dRayClass );
+  dIASSERT( o2->type == dConvexClass );
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxRay* ray = (dxRay*) o1;
+  dxConvex* convex = (dxConvex*) o2;
+  dVector3 origin,destination,contactpoint,out;
+  dReal depth;
+  dVector4 plane;
+  unsigned int *pPoly=convex->polygons;
+  // Calculate ray origin and destination
+  destination[0]=0;
+  destination[1]=0;
+  destination[2]= ray->length;
+  // -- Rotate --
+  dMULTIPLY0_331(destination,ray->final_posr->R,destination);
+  origin[0]=ray->final_posr->pos[0];
+  origin[1]=ray->final_posr->pos[1];
+  origin[2]=ray->final_posr->pos[2];
+  destination[0]+=origin[0];
+  destination[1]+=origin[1];
+  destination[2]+=origin[2];
+  for(int i=0;i<convex->planecount;++i)
+    {
+      // Rotate
+      dMULTIPLY0_331(plane,convex->final_posr->R,convex->planes+(i*4));
+      // Translate
+      plane[3]=
+	(convex->planes[(i*4)+3])+
+	((plane[0] * convex->final_posr->pos[0]) + 
+	 (plane[1] * convex->final_posr->pos[1]) + 
+	 (plane[2] * convex->final_posr->pos[2]));
+      if(IntersectSegmentPlane(origin, 
+			       destination, 
+			       plane, 
+			       depth, 
+			       contactpoint))
+	{
+	  if(IsPointInPolygon(contactpoint,pPoly,convex,out))
+	    {
+	      contact->pos[0]=contactpoint[0];
+	      contact->pos[1]=contactpoint[1];
+	      contact->pos[2]=contactpoint[2];
+	      contact->normal[0]=plane[0];
+	      contact->normal[1]=plane[1];
+	      contact->normal[2]=plane[2];
+	      contact->depth=depth;
+	      contact->g1 = ray;
+	      contact->g2 = convex;
+	      return 1;
+	    }
+	}
+      pPoly+=pPoly[0]+1;
+    }
+  return 0;
+}
+
+#else
+
+// Ray - Convex collider by David Walters, June 2006
+int dCollideRayConvex( dxGeom *o1, dxGeom *o2,
+					   int flags, dContactGeom *contact, int skip )
+{
+	dIASSERT( skip >= (int)sizeof(dContactGeom) );
+	dIASSERT( o1->type == dRayClass );
+	dIASSERT( o2->type == dConvexClass );
+	dIASSERT ((flags & NUMC_MASK) >= 1);
+
+	dxRay* ray = (dxRay*) o1;
+	dxConvex* convex = (dxConvex*) o2;
+
+	contact->g1 = ray;
+	contact->g2 = convex;
+
+	dReal alpha, beta, nsign;
+	int flag;
+
+	//
+	// Compute some useful info
+	//
+
+	flag = 0;	// Assume start point is behind all planes.
+
+	for ( unsigned int i = 0; i < convex->planecount; ++i )
+	{
+		// Alias this plane.
+		dReal* plane = convex->planes + ( i * 4 );
+
+		// If alpha >= 0 then start point is outside of plane.
+		alpha = dDOT( plane, ray->final_posr->pos ) - plane[3];
+
+		// If any alpha is positive, then
+		// the ray start is _outside_ of the hull
+		if ( alpha >= 0 )
+		{
+			flag = 1;
+			break;
+		}
+	}
+
+	// If the ray starts inside the convex hull, then everything is flipped.
+	nsign = ( flag ) ? REAL( 1.0 ) : REAL( -1.0 );
+
+
+	//
+	// Find closest contact point
+	//
+
+	// Assume no contacts.
+	contact->depth = dInfinity;
+
+	for ( unsigned int i = 0; i < convex->planecount; ++i )
+	{
+		// Alias this plane.
+		dReal* plane = convex->planes + ( i * 4 );
+
+		// If alpha >= 0 then point is outside of plane.
+		alpha = nsign * ( dDOT( plane, ray->final_posr->pos ) - plane[3] );
+
+		// Compute [ plane-normal DOT ray-normal ], (/flip)
+		beta = dDOT13( plane, ray->final_posr->R+2 ) * nsign;
+
+		// Ray is pointing at the plane? ( beta < 0 )
+		// Ray start to plane is within maximum ray length?
+		// Ray start to plane is closer than the current best distance?
+		if ( beta < -dEpsilon &&
+			 alpha >= 0 && alpha <= ray->length &&
+			 alpha < contact->depth )
+		{
+			// Compute contact point on convex hull surface.
+			contact->pos[0] = ray->final_posr->pos[0] + alpha * ray->final_posr->R[0*4+2];
+			contact->pos[1] = ray->final_posr->pos[1] + alpha * ray->final_posr->R[1*4+2];
+			contact->pos[2] = ray->final_posr->pos[2] + alpha * ray->final_posr->R[2*4+2];
+
+			flag = 0;
+
+			// For all _other_ planes.
+			for ( unsigned int j = 0; j < convex->planecount; ++j )
+			{
+				if ( i == j )
+					continue;	// Skip self.
+
+				// Alias this plane.
+				dReal* planej = convex->planes + ( j * 4 );
+
+				// If beta >= 0 then start is outside of plane.
+				beta = dDOT( planej, contact->pos ) - plane[3];
+
+				// If any beta is positive, then the contact point
+				// is not on the surface of the convex hull - it's just
+				// intersecting some part of its infinite extent.
+				if ( beta > dEpsilon )
+				{
+					flag = 1;
+					break;
+				}
+			}
+
+			// Contact point isn't outside hull's surface? then it's a good contact!
+			if ( flag == 0 )
+			{
+				// Store the contact normal, possibly flipped.
+				contact->normal[0] = nsign * plane[0];
+				contact->normal[1] = nsign * plane[1];
+				contact->normal[2] = nsign * plane[2];
+
+				// Store depth
+				contact->depth = alpha;
+				
+				if ((flags & CONTACTS_UNIMPORTANT) && contact->depth <= ray->length )
+				{
+					// Break on any contact if contacts are not important
+					break; 
+				}
+			}
+		}
+	}
+
+	// Contact?
+	return ( contact->depth <= ray->length );
+}
+
+#endif
+
+//<-- Convex Collision
Index: /code/branches/ode/ode-0.9/ode/src/cylinder.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/cylinder.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/cylinder.cpp	(revision 216)
@@ -0,0 +1,100 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+standard ODE geometry primitives: public API and pairwise collision functions.
+
+the rule is that only the low level primitive collision functions should set
+dContactGeom::g1 and dContactGeom::g2.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+// flat cylinder public API
+
+dxCylinder::dxCylinder (dSpaceID space, dReal _radius, dReal _length) :
+dxGeom (space,1)
+{
+	dAASSERT (_radius > 0 && _length > 0);
+	type = dCylinderClass;
+	radius = _radius;
+	lz = _length;
+}
+
+
+void dxCylinder::computeAABB()
+{
+    const dMatrix3& R = final_posr->R;
+    const dVector3& pos = final_posr->pos;
+
+	dReal xrange = dFabs (R[0] * radius) +	 dFabs (R[1] * radius) + REAL(0.5)* dFabs (R[2] * 
+		lz);
+	dReal yrange = dFabs (R[4] * radius) +   dFabs (R[5] * radius) + REAL(0.5)* dFabs (R[6] * 
+		lz);
+	dReal zrange = dFabs (R[8] * radius) +	 dFabs (R[9] * radius) + REAL(0.5)* dFabs (R[10] * 
+		lz);
+	aabb[0] = pos[0] - xrange;
+	aabb[1] = pos[0] + xrange;
+	aabb[2] = pos[1] - yrange;
+	aabb[3] = pos[1] + yrange;
+	aabb[4] = pos[2] - zrange;
+	aabb[5] = pos[2] + zrange;
+}
+
+
+dGeomID dCreateCylinder (dSpaceID space, dReal radius, dReal length)
+{
+	return new dxCylinder (space,radius,length);
+}
+
+void dGeomCylinderSetParams (dGeomID cylinder, dReal radius, dReal length)
+{
+	dUASSERT (cylinder && cylinder->type == dCylinderClass,"argument not a ccylinder");
+	dAASSERT (radius > 0 && length > 0);
+	dxCylinder *c = (dxCylinder*) cylinder;
+	c->radius = radius;
+	c->lz = length;
+	dGeomMoved (cylinder);
+}
+
+void dGeomCylinderGetParams (dGeomID cylinder, dReal *radius, dReal *length)
+{
+	dUASSERT (cylinder && cylinder->type == dCylinderClass,"argument not a ccylinder");
+	dxCylinder *c = (dxCylinder*) cylinder;
+	*radius = c->radius;
+	*length = c->lz;
+}
+
+
Index: /code/branches/ode/ode-0.9/ode/src/error.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/error.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/error.cpp	(revision 216)
@@ -0,0 +1,172 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/error.h>
+
+
+static dMessageFunction *error_function = 0;
+static dMessageFunction *debug_function = 0;
+static dMessageFunction *message_function = 0;
+
+
+extern "C" void dSetErrorHandler (dMessageFunction *fn)
+{
+  error_function = fn;
+}
+
+
+extern "C" void dSetDebugHandler (dMessageFunction *fn)
+{
+  debug_function = fn;
+}
+
+
+extern "C" void dSetMessageHandler (dMessageFunction *fn)
+{
+  message_function = fn;
+}
+
+
+extern "C" dMessageFunction *dGetErrorHandler()
+{
+  return error_function;
+}
+
+
+extern "C" dMessageFunction *dGetDebugHandler()
+{
+  return debug_function;
+}
+
+
+extern "C" dMessageFunction *dGetMessageHandler()
+{
+  return message_function;
+}
+
+
+static void printMessage (int num, const char *msg1, const char *msg2,
+			  va_list ap)
+{
+  fflush (stderr);
+  fflush (stdout);
+  if (num) fprintf (stderr,"\n%s %d: ",msg1,num);
+  else fprintf (stderr,"\n%s: ",msg1);
+  vfprintf (stderr,msg2,ap);
+  fprintf (stderr,"\n");
+  fflush (stderr);
+}
+
+//****************************************************************************
+// unix
+
+#ifndef WIN32
+
+extern "C" void dError (int num, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  if (error_function) error_function (num,msg,ap);
+  else printMessage (num,"ODE Error",msg,ap);
+  exit (1);
+}
+
+
+extern "C" void dDebug (int num, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  if (debug_function) debug_function (num,msg,ap);
+  else printMessage (num,"ODE INTERNAL ERROR",msg,ap);
+  // *((char *)0) = 0;   ... commit SEGVicide
+  abort();
+}
+
+
+extern "C" void dMessage (int num, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  if (message_function) message_function (num,msg,ap);
+  else printMessage (num,"ODE Message",msg,ap);
+}
+
+#endif
+
+//****************************************************************************
+// windows
+
+#ifdef WIN32
+
+// isn't cygwin annoying!
+#ifdef CYGWIN
+#define _snprintf snprintf
+#define _vsnprintf vsnprintf
+#endif
+
+
+#include "windows.h"
+
+
+extern "C" void dError (int num, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  if (error_function) error_function (num,msg,ap);
+  else {
+    char s[1000],title[100];
+    _snprintf (title,sizeof(title),"ODE Error %d",num);
+    _vsnprintf (s,sizeof(s),msg,ap);
+    s[sizeof(s)-1] = 0;
+    MessageBox(0,s,title,MB_OK | MB_ICONWARNING);
+  }
+  exit (1);
+}
+
+
+extern "C" void dDebug (int num, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  if (debug_function) debug_function (num,msg,ap);
+  else {
+    char s[1000],title[100];
+    _snprintf (title,sizeof(title),"ODE INTERNAL ERROR %d",num);
+    _vsnprintf (s,sizeof(s),msg,ap);
+    s[sizeof(s)-1] = 0;
+    MessageBox(0,s,title,MB_OK | MB_ICONSTOP);
+  }
+  abort();
+}
+
+
+extern "C" void dMessage (int num, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap,msg);
+  if (message_function) message_function (num,msg,ap);
+  else printMessage (num,"ODE Message",msg,ap);
+}
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/export-dif.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/export-dif.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/export-dif.cpp	(revision 216)
@@ -0,0 +1,568 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+ * Export a DIF (Dynamics Interchange Format) file.
+ */
+
+
+// @@@ TODO:
+//	* export all spaces, and geoms in spaces, not just ones attached to bodies
+//	  (separate export function?)
+//	* say the space each geom is in, so reader can construct space heirarchy
+//	* limot --> separate out into limits and motors?
+//	* make sure ODE-specific parameters divided out
+
+
+#include "ode/ode.h"
+#include "objects.h"
+#include "joint.h"
+#include "collision_kernel.h"
+
+//***************************************************************************
+// utility
+
+struct PrintingContext {
+	FILE *file;		// file to write to
+	int precision;		// digits of precision to print
+	int indent;		// number of levels of indent
+
+	void printIndent();
+	void printReal (dReal x);
+	void print (const char *name, int x);
+	void print (const char *name, dReal x);
+	void print (const char *name, const dReal *x, int n=3);
+	void print (const char *name, const char *x=0);
+	void printNonzero (const char *name, dReal x);
+	void printNonzero (const char *name, const dReal x[3]);
+};
+
+
+void PrintingContext::printIndent()
+{
+	for (int i=0; i<indent; i++) fputc ('\t',file);
+}
+
+
+void PrintingContext::print (const char *name, int x)
+{
+	printIndent();
+	fprintf (file,"%s = %d,\n",name,x);
+}
+
+
+void PrintingContext::printReal (dReal x)
+{
+	if (x==dInfinity) {
+		fprintf (file,"inf");
+	}
+	else if (x==-dInfinity) {
+		fprintf (file,"-inf");
+	}
+	else {
+		fprintf (file,"%.*g",precision,x);
+	}
+}
+
+
+void PrintingContext::print (const char *name, dReal x)
+{
+	printIndent();
+	fprintf (file,"%s = ",name);
+	printReal (x);
+	fprintf (file,",\n");
+}
+
+
+void PrintingContext::print (const char *name, const dReal *x, int n)
+{
+	printIndent();
+	fprintf (file,"%s = {",name);
+	for (int i=0; i<n; i++) {
+		printReal (x[i]);
+		if (i < n-1) fputc (',',file);
+	}
+	fprintf (file,"},\n");
+}
+
+
+void PrintingContext::print (const char *name, const char *x)
+{
+	printIndent();
+	if (x) {
+		fprintf (file,"%s = \"%s\",\n",name,x);
+	}
+	else {
+		fprintf (file,"%s\n",name);
+	}
+}
+
+
+void PrintingContext::printNonzero (const char *name, dReal x)
+{
+	if (x != 0) print (name,x);
+}
+
+
+void PrintingContext::printNonzero (const char *name, const dReal x[3])
+{
+	if (x[0] != 0 && x[1] != 0 && x[2] != 0) print (name,x);
+}
+
+//***************************************************************************
+// joints
+
+
+static void printLimot (PrintingContext &c, dxJointLimitMotor &limot, int num)
+{
+	if (num >= 0) {
+		c.printIndent();
+		fprintf (c.file,"limit%d = {\n",num);
+	}
+	else {
+		c.print ("limit = {");
+	}
+	c.indent++;
+	c.print ("low_stop",limot.lostop);
+	c.print ("high_stop",limot.histop);
+	c.printNonzero ("bounce",limot.bounce);
+	c.print ("ODE = {");
+	c.indent++;
+	c.printNonzero ("stop_erp",limot.stop_erp);
+	c.printNonzero ("stop_cfm",limot.stop_cfm);
+	c.indent--;
+	c.print ("},");
+	c.indent--;
+	c.print ("},");
+
+	if (num >= 0) {
+		c.printIndent();
+		fprintf (c.file,"motor%d = {\n",num);
+	}
+	else {
+		c.print ("motor = {");
+	}
+	c.indent++;
+	c.printNonzero ("vel",limot.vel);
+	c.printNonzero ("fmax",limot.fmax);
+	c.print ("ODE = {");
+	c.indent++;
+	c.printNonzero ("fudge_factor",limot.fudge_factor);
+	c.printNonzero ("normal_cfm",limot.normal_cfm);
+	c.indent--;
+	c.print ("},");
+	c.indent--;
+	c.print ("},");
+}
+
+
+static const char *getJointName (dxJoint *j)
+{
+	switch (j->vtable->typenum) {
+		case dJointTypeBall: return "ball";
+		case dJointTypeHinge: return "hinge";
+		case dJointTypeSlider: return "slider";
+		case dJointTypeContact: return "contact";
+		case dJointTypeUniversal: return "universal";
+		case dJointTypeHinge2: return "ODE_hinge2";
+		case dJointTypeFixed: return "fixed";
+		case dJointTypeNull: return "null";
+		case dJointTypeAMotor: return "ODE_angular_motor";
+		case dJointTypeLMotor: return "ODE_linear_motor";
+		case dJointTypePR: return "PR";
+	}
+	return "unknown";
+}
+
+
+static void printBall (PrintingContext &c, dxJoint *j)
+{
+	dxJointBall *b = (dxJointBall*) j;
+	c.print ("anchor1",b->anchor1);
+	c.print ("anchor2",b->anchor2);
+}
+
+
+static void printHinge (PrintingContext &c, dxJoint *j)
+{
+	dxJointHinge *h = (dxJointHinge*) j;
+	c.print ("anchor1",h->anchor1);
+	c.print ("anchor2",h->anchor2);
+	c.print ("axis1",h->axis1);
+	c.print ("axis2",h->axis2);
+	c.print ("qrel",h->qrel,4);
+	printLimot (c,h->limot,-1);
+}
+
+
+static void printSlider (PrintingContext &c, dxJoint *j)
+{
+	dxJointSlider *s = (dxJointSlider*) j;
+	c.print ("axis1",s->axis1);
+	c.print ("qrel",s->qrel,4);
+	c.print ("offset",s->offset);
+	printLimot (c,s->limot,-1);
+}
+
+
+static void printContact (PrintingContext &c, dxJoint *j)
+{
+	dxJointContact *ct = (dxJointContact*) j;
+	int mode = ct->contact.surface.mode;
+	c.print ("pos",ct->contact.geom.pos);
+	c.print ("normal",ct->contact.geom.normal);
+	c.print ("depth",ct->contact.geom.depth);
+	//@@@ may want to write the geoms g1 and g2 that are involved, for debugging.
+	//    to do this we must have written out all geoms in all spaces, not just
+	//    geoms that are attached to bodies.
+	c.print ("mu",ct->contact.surface.mu);
+	if (mode & dContactMu2) c.print ("mu2",ct->contact.surface.mu2);
+	if (mode & dContactBounce) c.print ("bounce",ct->contact.surface.bounce);
+	if (mode & dContactBounce) c.print ("bounce_vel",ct->contact.surface.bounce_vel);
+	if (mode & dContactSoftERP) c.print ("soft_ERP",ct->contact.surface.soft_erp);
+	if (mode & dContactSoftCFM) c.print ("soft_CFM",ct->contact.surface.soft_cfm);
+	if (mode & dContactMotion1) c.print ("motion1",ct->contact.surface.motion1);
+	if (mode & dContactMotion2) c.print ("motion2",ct->contact.surface.motion2);
+	if (mode & dContactSlip1) c.print ("slip1",ct->contact.surface.slip1);
+	if (mode & dContactSlip2) c.print ("slip2",ct->contact.surface.slip2);
+	int fa = 0;		// friction approximation code
+	if (mode & dContactApprox1_1) fa |= 1;
+	if (mode & dContactApprox1_2) fa |= 2;
+	if (fa) c.print ("friction_approximation",fa);
+	if (mode & dContactFDir1) c.print ("fdir1",ct->contact.fdir1);
+}
+
+
+static void printUniversal (PrintingContext &c, dxJoint *j)
+{
+	dxJointUniversal *u = (dxJointUniversal*) j;
+	c.print ("anchor1",u->anchor1);
+	c.print ("anchor2",u->anchor2);
+	c.print ("axis1",u->axis1);
+	c.print ("axis2",u->axis2);
+	c.print ("qrel1",u->qrel1,4);
+	c.print ("qrel2",u->qrel2,4);
+	printLimot (c,u->limot1,1);
+	printLimot (c,u->limot2,2);
+}
+
+
+static void printHinge2 (PrintingContext &c, dxJoint *j)
+{
+	dxJointHinge2 *h = (dxJointHinge2*) j;
+	c.print ("anchor1",h->anchor1);
+	c.print ("anchor2",h->anchor2);
+	c.print ("axis1",h->axis1);
+	c.print ("axis2",h->axis2);
+	c.print ("v1",h->v1);	//@@@ much better to write out 'qrel' here, if it's available
+	c.print ("v2",h->v2);
+	c.print ("susp_erp",h->susp_erp);
+	c.print ("susp_cfm",h->susp_cfm);
+	printLimot (c,h->limot1,1);
+	printLimot (c,h->limot2,2);
+}
+
+static void printPR (PrintingContext &c, dxJoint *j)
+{
+	dxJointPR *pr = (dxJointPR*) j;
+	c.print ("anchor2",pr->anchor2);
+	c.print ("axisR1",pr->axisR1);
+	c.print ("axisR2",pr->axisR2);
+	c.print ("axisP1",pr->axisP1);
+	c.print ("qrel",pr->qrel,4);
+	c.print ("offset",pr->offset);
+	printLimot (c,pr->limotP,1);
+	printLimot (c,pr->limotR,2);
+}
+
+
+static void printFixed (PrintingContext &c, dxJoint *j)
+{
+	dxJointFixed *f = (dxJointFixed*) j;
+	c.print ("qrel",f->qrel);
+	c.print ("offset",f->offset);
+}
+
+static void printLMotor (PrintingContext &c, dxJoint *j)
+{
+       dxJointLMotor *a = (dxJointLMotor*) j;
+       c.print("num", a->num);
+       c.printIndent();
+       fprintf (c.file,"rel = {%d,%d,%d},\n",a->rel[0],a->rel[1],a->rel[2]);
+       c.print ("axis1",a->axis[0]);
+       c.print ("axis2",a->axis[1]);
+       c.print ("axis3",a->axis[2]);
+       for (int i=0; i<3; i++) printLimot (c,a->limot[i],i+1);
+}
+
+
+static void printAMotor (PrintingContext &c, dxJoint *j)
+{
+	dxJointAMotor *a = (dxJointAMotor*) j;
+	c.print ("num",a->num);
+	c.print ("mode",a->mode);
+	c.printIndent();
+	fprintf (c.file,"rel = {%d,%d,%d},\n",a->rel[0],a->rel[1],a->rel[2]);
+	c.print ("axis1",a->axis[0]);
+	c.print ("axis2",a->axis[1]);
+	c.print ("axis3",a->axis[2]);
+	for (int i=0; i<3; i++) printLimot (c,a->limot[i],i+1);
+	c.print ("angle1",a->angle[0]);
+	c.print ("angle2",a->angle[1]);
+	c.print ("angle3",a->angle[2]);
+}
+
+//***************************************************************************
+// geometry
+
+static void printGeom (PrintingContext &c, dxGeom *g);
+
+static void printSphere (PrintingContext &c, dxGeom *g)
+{
+	c.print ("type","sphere");
+	c.print ("radius",dGeomSphereGetRadius (g));
+}
+
+
+static void printBox (PrintingContext &c, dxGeom *g)
+{
+	dVector3 sides;
+	dGeomBoxGetLengths (g,sides);
+	c.print ("type","box");
+	c.print ("sides",sides);
+}
+
+
+
+static void printCapsule (PrintingContext &c, dxGeom *g)
+{
+	dReal radius,length;
+	dGeomCapsuleGetParams (g,&radius,&length);
+	c.print ("type","capsule");
+	c.print ("radius",radius);
+	c.print ("length",length);
+}
+
+
+static void printPlane (PrintingContext &c, dxGeom *g)
+{
+	dVector4 e;
+	dGeomPlaneGetParams (g,e);
+	c.print ("type","plane");
+	c.print ("normal",e);
+	c.print ("d",e[3]);
+}
+
+
+
+static void printRay (PrintingContext &c, dxGeom *g)
+{
+	dReal length = dGeomRayGetLength (g);
+	c.print ("type","ray");
+	c.print ("length",length);
+}
+
+
+
+static void printGeomTransform (PrintingContext &c, dxGeom *g)
+{
+	dxGeom *g2 = dGeomTransformGetGeom (g);
+	const dReal *pos = dGeomGetPosition (g2);
+	dQuaternion q;
+	dGeomGetQuaternion (g2,q);
+	c.print ("type","transform");
+	c.print ("pos",pos);
+	c.print ("q",q,4);
+	c.print ("geometry = {");
+	c.indent++;
+	printGeom (c,g2);
+	c.indent--;
+	c.print ("}");
+}
+
+
+
+static void printTriMesh (PrintingContext &c, dxGeom *g)
+{
+	c.print ("type","trimesh");
+	//@@@ i don't think that the trimesh accessor functions are really
+	//    sufficient to read out all the triangle data, and anyway we
+	//    should have a method of not duplicating trimesh data that is
+	//    shared.
+}
+
+
+static void printGeom (PrintingContext &c, dxGeom *g)
+{
+	unsigned long category = dGeomGetCategoryBits (g);
+	if (category != (unsigned long)(~0)) {
+		c.printIndent();
+		fprintf (c.file,"category_bits = %lu\n",category);
+	}
+	unsigned long collide = dGeomGetCollideBits (g);
+	if (collide != (unsigned long)(~0)) {
+		c.printIndent();
+		fprintf (c.file,"collide_bits = %lu\n",collide);
+	}
+	if (!dGeomIsEnabled (g)) {
+		c.print ("disabled",1);
+	}
+	switch (g->type) {
+		case dSphereClass: printSphere (c,g); break;
+		case dBoxClass: printBox (c,g); break;
+		case dCapsuleClass: printCapsule (c,g); break;
+		case dPlaneClass: printPlane (c,g); break;
+		case dRayClass: printRay (c,g); break;
+		case dGeomTransformClass: printGeomTransform (c,g); break;
+		case dTriMeshClass: printTriMesh (c,g); break;
+	}
+}
+
+//***************************************************************************
+// world
+
+void dWorldExportDIF (dWorldID w, FILE *file, const char *prefix)
+{
+	PrintingContext c;
+	c.file = file;
+#if defined(dSINGLE)
+	c.precision = 7;
+#else
+	c.precision = 15;
+#endif
+	c.indent = 1;
+
+	fprintf (file,"-- Dynamics Interchange Format v0.1\n\n%sworld = dynamics.world {\n",prefix);
+	c.print ("gravity",w->gravity);
+	c.print ("ODE = {");
+	c.indent++;
+	c.print ("ERP",w->global_erp);
+	c.print ("CFM",w->global_cfm);
+	c.print ("auto_disable = {");
+	c.indent++;
+	c.print ("linear_threshold",w->adis.linear_average_threshold);
+	c.print ("angular_threshold",w->adis.angular_average_threshold);
+	c.print ("average_samples",(int)w->adis.average_samples);
+	c.print ("idle_time",w->adis.idle_time);
+	c.print ("idle_steps",w->adis.idle_steps);
+	fprintf (file,"\t\t},\n\t},\n}\n");
+	c.indent -= 3;
+
+	// bodies
+	int num = 0;
+	fprintf (file,"%sbody = {}\n",prefix);
+	for (dxBody *b=w->firstbody; b; b=(dxBody*)b->next) {
+		b->tag = num;
+		fprintf (file,"%sbody[%d] = dynamics.body {\n\tworld = %sworld,\n",prefix,num,prefix);
+		c.indent++;
+		c.print ("pos",b->posr.pos);
+		c.print ("q",b->q,4);
+		c.print ("lvel",b->lvel);
+		c.print ("avel",b->avel);
+		c.print ("mass",b->mass.mass);
+		fprintf (file,"\tI = {{");
+		for (int i=0; i<3; i++) {
+			for (int j=0; j<3; j++) {
+				c.printReal (b->mass.I[i*4+j]);
+				if (j < 2) fputc (',',file);
+			}
+			if (i < 2) fprintf (file,"},{");
+		}
+		fprintf (file,"}},\n");
+		c.printNonzero ("com",b->mass.c);
+		c.print ("ODE = {");
+		c.indent++;
+		if (b->flags & dxBodyFlagFiniteRotation) c.print ("finite_rotation",1);
+		if (b->flags & dxBodyDisabled) c.print ("disabled",1);
+		if (b->flags & dxBodyNoGravity) c.print ("no_gravity",1);
+		if (b->flags & dxBodyAutoDisable) {
+			c.print ("auto_disable = {");
+			c.indent++;
+			c.print ("linear_threshold",b->adis.linear_average_threshold);
+			c.print ("angular_threshold",b->adis.angular_average_threshold);
+			c.print ("average_samples",(int)b->adis.average_samples);
+			c.print ("idle_time",b->adis.idle_time);
+			c.print ("idle_steps",b->adis.idle_steps);
+			c.print ("time_left",b->adis_timeleft);
+			c.print ("steps_left",b->adis_stepsleft);
+			c.indent--;
+			c.print ("},");
+		}
+		c.printNonzero ("facc",b->facc);
+		c.printNonzero ("tacc",b->tacc);
+		if (b->flags & dxBodyFlagFiniteRotationAxis) {
+			c.print ("finite_rotation_axis",b->finite_rot_axis);
+		}
+		c.indent--;
+		c.print ("},");
+		if (b->geom) {
+			c.print ("geometry = {");
+			c.indent++;
+			for (dxGeom *g=b->geom; g; g=g->body_next) {
+				c.print ("{");
+				c.indent++;
+				printGeom (c,g);
+				c.indent--;
+				c.print ("},");
+			}
+			c.indent--;
+			c.print ("},");
+		}
+		c.indent--;
+		c.print ("}");
+		num++;
+	}
+
+	// joints
+	num = 0;
+	fprintf (file,"%sjoint = {}\n",prefix);
+	for (dxJoint *j=w->firstjoint; j; j=(dxJoint*)j->next) {
+		c.indent++;
+		const char *name = getJointName (j);
+		fprintf (file,
+			"%sjoint[%d] = dynamics.%s_joint {\n"
+			"\tworld = %sworld,\n"
+			"\tbody = {"
+			,prefix,num,name,prefix);
+
+		if ( j->node[0].body )
+			fprintf (file,"%sbody[%d]",prefix,j->node[0].body->tag);
+		if ( j->node[1].body )
+			fprintf (file,",%sbody[%d]",prefix,j->node[1].body->tag);
+
+		switch (j->vtable->typenum) {
+			case dJointTypeBall: printBall (c,j); break;
+			case dJointTypeHinge: printHinge (c,j); break;
+			case dJointTypeSlider: printSlider (c,j); break;
+			case dJointTypeContact: printContact (c,j); break;
+			case dJointTypeUniversal: printUniversal (c,j); break;
+			case dJointTypeHinge2: printHinge2 (c,j); break;
+			case dJointTypeFixed: printFixed (c,j); break;
+			case dJointTypeAMotor: printAMotor (c,j); break;
+			case dJointTypeLMotor: printLMotor (c,j); break;
+			case dJointTypePR: printPR (c,j); break;
+		}
+		c.indent--;
+		c.print ("}");
+		num++;
+	}
+}
Index: /code/branches/ode/ode-0.9/ode/src/fastdot.c
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/fastdot.c	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/fastdot.c	(revision 216)
@@ -0,0 +1,30 @@
+/* generated code, do not edit. */
+
+#include "ode/matrix.h"
+
+
+dReal dDot (const dReal *a, const dReal *b, int n)
+{  
+  dReal p0,q0,m0,p1,q1,m1,sum;
+  sum = 0;
+  n -= 2;
+  while (n >= 0) {
+    p0 = a[0]; q0 = b[0];
+    m0 = p0 * q0;
+    p1 = a[1]; q1 = b[1];
+    m1 = p1 * q1;
+    sum += m0;
+    sum += m1;
+    a += 2;
+    b += 2;
+    n -= 2;
+  }
+  n += 2;
+  while (n > 0) {
+    sum += (*a) * (*b);
+    a++;
+    b++;
+    n--;
+  }
+  return sum;
+}
Index: /code/branches/ode/ode-0.9/ode/src/fastldlt.c
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/fastldlt.c	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/fastldlt.c	(revision 216)
@@ -0,0 +1,381 @@
+/* generated code, do not edit. */
+
+#include "ode/matrix.h"
+
+/* solve L*X=B, with B containing 1 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*1 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 2*2.
+ * if this is in the factorizer source file, n must be a multiple of 2.
+ */
+
+static void dSolveL1_1 (const dReal *L, dReal *B, int n, int lskip1)
+{  
+  /* declare variables - Z matrix, p and q vectors, etc */
+  dReal Z11,m11,Z21,m21,p1,q1,p2,*ex;
+  const dReal *ell;
+  int i,j;
+  /* compute all 2 x 1 blocks of X */
+  for (i=0; i < n; i+=2) {
+    /* compute all 2 x 1 block of X, from rows i..i+2-1 */
+    /* set the Z matrix to 0 */
+    Z11=0;
+    Z21=0;
+    ell = L + i*lskip1;
+    ex = B;
+    /* the inner loop that computes outer products and adds them to Z */
+    for (j=i-2; j >= 0; j -= 2) {
+      /* compute outer product and add it to the Z matrix */
+      p1=ell[0];
+      q1=ex[0];
+      m11 = p1 * q1;
+      p2=ell[lskip1];
+      m21 = p2 * q1;
+      Z11 += m11;
+      Z21 += m21;
+      /* compute outer product and add it to the Z matrix */
+      p1=ell[1];
+      q1=ex[1];
+      m11 = p1 * q1;
+      p2=ell[1+lskip1];
+      m21 = p2 * q1;
+      /* advance pointers */
+      ell += 2;
+      ex += 2;
+      Z11 += m11;
+      Z21 += m21;
+      /* end of inner loop */
+    }
+    /* compute left-over iterations */
+    j += 2;
+    for (; j > 0; j--) {
+      /* compute outer product and add it to the Z matrix */
+      p1=ell[0];
+      q1=ex[0];
+      m11 = p1 * q1;
+      p2=ell[lskip1];
+      m21 = p2 * q1;
+      /* advance pointers */
+      ell += 1;
+      ex += 1;
+      Z11 += m11;
+      Z21 += m21;
+    }
+    /* finish computing the X(i) block */
+    Z11 = ex[0] - Z11;
+    ex[0] = Z11;
+    p1 = ell[lskip1];
+    Z21 = ex[1] - Z21 - p1*Z11;
+    ex[1] = Z21;
+    /* end of outer loop */
+  }
+}
+
+/* solve L*X=B, with B containing 2 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*2 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 2*2.
+ * if this is in the factorizer source file, n must be a multiple of 2.
+ */
+
+static void dSolveL1_2 (const dReal *L, dReal *B, int n, int lskip1)
+{  
+  /* declare variables - Z matrix, p and q vectors, etc */
+  dReal Z11,m11,Z12,m12,Z21,m21,Z22,m22,p1,q1,p2,q2,*ex;
+  const dReal *ell;
+  int i,j;
+  /* compute all 2 x 2 blocks of X */
+  for (i=0; i < n; i+=2) {
+    /* compute all 2 x 2 block of X, from rows i..i+2-1 */
+    /* set the Z matrix to 0 */
+    Z11=0;
+    Z12=0;
+    Z21=0;
+    Z22=0;
+    ell = L + i*lskip1;
+    ex = B;
+    /* the inner loop that computes outer products and adds them to Z */
+    for (j=i-2; j >= 0; j -= 2) {
+      /* compute outer product and add it to the Z matrix */
+      p1=ell[0];
+      q1=ex[0];
+      m11 = p1 * q1;
+      q2=ex[lskip1];
+      m12 = p1 * q2;
+      p2=ell[lskip1];
+      m21 = p2 * q1;
+      m22 = p2 * q2;
+      Z11 += m11;
+      Z12 += m12;
+      Z21 += m21;
+      Z22 += m22;
+      /* compute outer product and add it to the Z matrix */
+      p1=ell[1];
+      q1=ex[1];
+      m11 = p1 * q1;
+      q2=ex[1+lskip1];
+      m12 = p1 * q2;
+      p2=ell[1+lskip1];
+      m21 = p2 * q1;
+      m22 = p2 * q2;
+      /* advance pointers */
+      ell += 2;
+      ex += 2;
+      Z11 += m11;
+      Z12 += m12;
+      Z21 += m21;
+      Z22 += m22;
+      /* end of inner loop */
+    }
+    /* compute left-over iterations */
+    j += 2;
+    for (; j > 0; j--) {
+      /* compute outer product and add it to the Z matrix */
+      p1=ell[0];
+      q1=ex[0];
+      m11 = p1 * q1;
+      q2=ex[lskip1];
+      m12 = p1 * q2;
+      p2=ell[lskip1];
+      m21 = p2 * q1;
+      m22 = p2 * q2;
+      /* advance pointers */
+      ell += 1;
+      ex += 1;
+      Z11 += m11;
+      Z12 += m12;
+      Z21 += m21;
+      Z22 += m22;
+    }
+    /* finish computing the X(i) block */
+    Z11 = ex[0] - Z11;
+    ex[0] = Z11;
+    Z12 = ex[lskip1] - Z12;
+    ex[lskip1] = Z12;
+    p1 = ell[lskip1];
+    Z21 = ex[1] - Z21 - p1*Z11;
+    ex[1] = Z21;
+    Z22 = ex[1+lskip1] - Z22 - p1*Z12;
+    ex[1+lskip1] = Z22;
+    /* end of outer loop */
+  }
+}
+
+
+void dFactorLDLT (dReal *A, dReal *d, int n, int nskip1)
+{  
+  int i,j;
+  dReal sum,*ell,*dee,dd,p1,p2,q1,q2,Z11,m11,Z21,m21,Z22,m22;
+  if (n < 1) return;
+  
+  for (i=0; i<=n-2; i += 2) {
+    /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
+    dSolveL1_2 (A,A+i*nskip1,i,nskip1);
+    /* scale the elements in a 2 x i block at A(i,0), and also */
+    /* compute Z = the outer product matrix that we'll need. */
+    Z11 = 0;
+    Z21 = 0;
+    Z22 = 0;
+    ell = A+i*nskip1;
+    dee = d;
+    for (j=i-6; j >= 0; j -= 6) {
+      p1 = ell[0];
+      p2 = ell[nskip1];
+      dd = dee[0];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[0] = q1;
+      ell[nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      p1 = ell[1];
+      p2 = ell[1+nskip1];
+      dd = dee[1];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[1] = q1;
+      ell[1+nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      p1 = ell[2];
+      p2 = ell[2+nskip1];
+      dd = dee[2];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[2] = q1;
+      ell[2+nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      p1 = ell[3];
+      p2 = ell[3+nskip1];
+      dd = dee[3];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[3] = q1;
+      ell[3+nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      p1 = ell[4];
+      p2 = ell[4+nskip1];
+      dd = dee[4];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[4] = q1;
+      ell[4+nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      p1 = ell[5];
+      p2 = ell[5+nskip1];
+      dd = dee[5];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[5] = q1;
+      ell[5+nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      ell += 6;
+      dee += 6;
+    }
+    /* compute left-over iterations */
+    j += 6;
+    for (; j > 0; j--) {
+      p1 = ell[0];
+      p2 = ell[nskip1];
+      dd = dee[0];
+      q1 = p1*dd;
+      q2 = p2*dd;
+      ell[0] = q1;
+      ell[nskip1] = q2;
+      m11 = p1*q1;
+      m21 = p2*q1;
+      m22 = p2*q2;
+      Z11 += m11;
+      Z21 += m21;
+      Z22 += m22;
+      ell++;
+      dee++;
+    }
+    /* solve for diagonal 2 x 2 block at A(i,i) */
+    Z11 = ell[0] - Z11;
+    Z21 = ell[nskip1] - Z21;
+    Z22 = ell[1+nskip1] - Z22;
+    dee = d + i;
+    /* factorize 2 x 2 block Z,dee */
+    /* factorize row 1 */
+    dee[0] = dRecip(Z11);
+    /* factorize row 2 */
+    sum = 0;
+    q1 = Z21;
+    q2 = q1 * dee[0];
+    Z21 = q2;
+    sum += q1*q2;
+    dee[1] = dRecip(Z22 - sum);
+    /* done factorizing 2 x 2 block */
+    ell[nskip1] = Z21;
+  }
+  /* compute the (less than 2) rows at the bottom */
+  switch (n-i) {
+    case 0:
+    break;
+    
+    case 1:
+    dSolveL1_1 (A,A+i*nskip1,i,nskip1);
+    /* scale the elements in a 1 x i block at A(i,0), and also */
+    /* compute Z = the outer product matrix that we'll need. */
+    Z11 = 0;
+    ell = A+i*nskip1;
+    dee = d;
+    for (j=i-6; j >= 0; j -= 6) {
+      p1 = ell[0];
+      dd = dee[0];
+      q1 = p1*dd;
+      ell[0] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      p1 = ell[1];
+      dd = dee[1];
+      q1 = p1*dd;
+      ell[1] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      p1 = ell[2];
+      dd = dee[2];
+      q1 = p1*dd;
+      ell[2] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      p1 = ell[3];
+      dd = dee[3];
+      q1 = p1*dd;
+      ell[3] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      p1 = ell[4];
+      dd = dee[4];
+      q1 = p1*dd;
+      ell[4] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      p1 = ell[5];
+      dd = dee[5];
+      q1 = p1*dd;
+      ell[5] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      ell += 6;
+      dee += 6;
+    }
+    /* compute left-over iterations */
+    j += 6;
+    for (; j > 0; j--) {
+      p1 = ell[0];
+      dd = dee[0];
+      q1 = p1*dd;
+      ell[0] = q1;
+      m11 = p1*q1;
+      Z11 += m11;
+      ell++;
+      dee++;
+    }
+    /* solve for diagonal 1 x 1 block at A(i,i) */
+    Z11 = ell[0] - Z11;
+    dee = d + i;
+    /* factorize 1 x 1 block Z,dee */
+    /* factorize row 1 */
+    dee[0] = dRecip(Z11);
+    /* done factorizing 1 x 1 block */
+    break;
+    
+    default: *((char*)0)=0;  /* this should never happen! */
+  }
+}
Index: /code/branches/ode/ode-0.9/ode/src/fastlsolve.c
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/fastlsolve.c	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/fastlsolve.c	(revision 216)
@@ -0,0 +1,298 @@
+/* generated code, do not edit. */
+
+#include "ode/matrix.h"
+
+/* solve L*X=B, with B containing 1 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*1 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 4*4.
+ * if this is in the factorizer source file, n must be a multiple of 4.
+ */
+
+void dSolveL1 (const dReal *L, dReal *B, int n, int lskip1)
+{  
+  /* declare variables - Z matrix, p and q vectors, etc */
+  dReal Z11,Z21,Z31,Z41,p1,q1,p2,p3,p4,*ex;
+  const dReal *ell;
+  int lskip2,lskip3,i,j;
+  /* compute lskip values */
+  lskip2 = 2*lskip1;
+  lskip3 = 3*lskip1;
+  /* compute all 4 x 1 blocks of X */
+  for (i=0; i <= n-4; i+=4) {
+    /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+    /* set the Z matrix to 0 */
+    Z11=0;
+    Z21=0;
+    Z31=0;
+    Z41=0;
+    ell = L + i*lskip1;
+    ex = B;
+    /* the inner loop that computes outer products and adds them to Z */
+    for (j=i-12; j >= 0; j -= 12) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      p2=ell[lskip1];
+      p3=ell[lskip2];
+      p4=ell[lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[1];
+      q1=ex[1];
+      p2=ell[1+lskip1];
+      p3=ell[1+lskip2];
+      p4=ell[1+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[2];
+      q1=ex[2];
+      p2=ell[2+lskip1];
+      p3=ell[2+lskip2];
+      p4=ell[2+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[3];
+      q1=ex[3];
+      p2=ell[3+lskip1];
+      p3=ell[3+lskip2];
+      p4=ell[3+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[4];
+      q1=ex[4];
+      p2=ell[4+lskip1];
+      p3=ell[4+lskip2];
+      p4=ell[4+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[5];
+      q1=ex[5];
+      p2=ell[5+lskip1];
+      p3=ell[5+lskip2];
+      p4=ell[5+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[6];
+      q1=ex[6];
+      p2=ell[6+lskip1];
+      p3=ell[6+lskip2];
+      p4=ell[6+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[7];
+      q1=ex[7];
+      p2=ell[7+lskip1];
+      p3=ell[7+lskip2];
+      p4=ell[7+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[8];
+      q1=ex[8];
+      p2=ell[8+lskip1];
+      p3=ell[8+lskip2];
+      p4=ell[8+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[9];
+      q1=ex[9];
+      p2=ell[9+lskip1];
+      p3=ell[9+lskip2];
+      p4=ell[9+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[10];
+      q1=ex[10];
+      p2=ell[10+lskip1];
+      p3=ell[10+lskip2];
+      p4=ell[10+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* load p and q values */
+      p1=ell[11];
+      q1=ex[11];
+      p2=ell[11+lskip1];
+      p3=ell[11+lskip2];
+      p4=ell[11+lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* advance pointers */
+      ell += 12;
+      ex += 12;
+      /* end of inner loop */
+    }
+    /* compute left-over iterations */
+    j += 12;
+    for (; j > 0; j--) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      p2=ell[lskip1];
+      p3=ell[lskip2];
+      p4=ell[lskip3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      Z21 += p2 * q1;
+      Z31 += p3 * q1;
+      Z41 += p4 * q1;
+      /* advance pointers */
+      ell += 1;
+      ex += 1;
+    }
+    /* finish computing the X(i) block */
+    Z11 = ex[0] - Z11;
+    ex[0] = Z11;
+    p1 = ell[lskip1];
+    Z21 = ex[1] - Z21 - p1*Z11;
+    ex[1] = Z21;
+    p1 = ell[lskip2];
+    p2 = ell[1+lskip2];
+    Z31 = ex[2] - Z31 - p1*Z11 - p2*Z21;
+    ex[2] = Z31;
+    p1 = ell[lskip3];
+    p2 = ell[1+lskip3];
+    p3 = ell[2+lskip3];
+    Z41 = ex[3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
+    ex[3] = Z41;
+    /* end of outer loop */
+  }
+  /* compute rows at end that are not a multiple of block size */
+  for (; i < n; i++) {
+    /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+    /* set the Z matrix to 0 */
+    Z11=0;
+    ell = L + i*lskip1;
+    ex = B;
+    /* the inner loop that computes outer products and adds them to Z */
+    for (j=i-12; j >= 0; j -= 12) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[1];
+      q1=ex[1];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[2];
+      q1=ex[2];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[3];
+      q1=ex[3];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[4];
+      q1=ex[4];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[5];
+      q1=ex[5];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[6];
+      q1=ex[6];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[7];
+      q1=ex[7];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[8];
+      q1=ex[8];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[9];
+      q1=ex[9];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[10];
+      q1=ex[10];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* load p and q values */
+      p1=ell[11];
+      q1=ex[11];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* advance pointers */
+      ell += 12;
+      ex += 12;
+      /* end of inner loop */
+    }
+    /* compute left-over iterations */
+    j += 12;
+    for (; j > 0; j--) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      /* compute outer product and add it to the Z matrix */
+      Z11 += p1 * q1;
+      /* advance pointers */
+      ell += 1;
+      ex += 1;
+    }
+    /* finish computing the X(i) block */
+    Z11 = ex[0] - Z11;
+    ex[0] = Z11;
+  }
+}
Index: /code/branches/ode/ode-0.9/ode/src/fastltsolve.c
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/fastltsolve.c	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/fastltsolve.c	(revision 216)
@@ -0,0 +1,199 @@
+/* generated code, do not edit. */
+
+#include "ode/matrix.h"
+
+/* solve L^T * x=b, with b containing 1 right hand side.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * b is an n*1 matrix that contains the right hand side.
+ * b is overwritten with x.
+ * this processes blocks of 4.
+ */
+
+void dSolveL1T (const dReal *L, dReal *B, int n, int lskip1)
+{  
+  /* declare variables - Z matrix, p and q vectors, etc */
+  dReal Z11,m11,Z21,m21,Z31,m31,Z41,m41,p1,q1,p2,p3,p4,*ex;
+  const dReal *ell;
+  int lskip2,lskip3,i,j;
+  /* special handling for L and B because we're solving L1 *transpose* */
+  L = L + (n-1)*(lskip1+1);
+  B = B + n-1;
+  lskip1 = -lskip1;
+  /* compute lskip values */
+  lskip2 = 2*lskip1;
+  lskip3 = 3*lskip1;
+  /* compute all 4 x 1 blocks of X */
+  for (i=0; i <= n-4; i+=4) {
+    /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+    /* set the Z matrix to 0 */
+    Z11=0;
+    Z21=0;
+    Z31=0;
+    Z41=0;
+    ell = L - i;
+    ex = B;
+    /* the inner loop that computes outer products and adds them to Z */
+    for (j=i-4; j >= 0; j -= 4) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      p2=ell[-1];
+      p3=ell[-2];
+      p4=ell[-3];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      m21 = p2 * q1;
+      m31 = p3 * q1;
+      m41 = p4 * q1;
+      ell += lskip1;
+      Z11 += m11;
+      Z21 += m21;
+      Z31 += m31;
+      Z41 += m41;
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[-1];
+      p2=ell[-1];
+      p3=ell[-2];
+      p4=ell[-3];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      m21 = p2 * q1;
+      m31 = p3 * q1;
+      m41 = p4 * q1;
+      ell += lskip1;
+      Z11 += m11;
+      Z21 += m21;
+      Z31 += m31;
+      Z41 += m41;
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[-2];
+      p2=ell[-1];
+      p3=ell[-2];
+      p4=ell[-3];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      m21 = p2 * q1;
+      m31 = p3 * q1;
+      m41 = p4 * q1;
+      ell += lskip1;
+      Z11 += m11;
+      Z21 += m21;
+      Z31 += m31;
+      Z41 += m41;
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[-3];
+      p2=ell[-1];
+      p3=ell[-2];
+      p4=ell[-3];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      m21 = p2 * q1;
+      m31 = p3 * q1;
+      m41 = p4 * q1;
+      ell += lskip1;
+      ex -= 4;
+      Z11 += m11;
+      Z21 += m21;
+      Z31 += m31;
+      Z41 += m41;
+      /* end of inner loop */
+    }
+    /* compute left-over iterations */
+    j += 4;
+    for (; j > 0; j--) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      p2=ell[-1];
+      p3=ell[-2];
+      p4=ell[-3];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      m21 = p2 * q1;
+      m31 = p3 * q1;
+      m41 = p4 * q1;
+      ell += lskip1;
+      ex -= 1;
+      Z11 += m11;
+      Z21 += m21;
+      Z31 += m31;
+      Z41 += m41;
+    }
+    /* finish computing the X(i) block */
+    Z11 = ex[0] - Z11;
+    ex[0] = Z11;
+    p1 = ell[-1];
+    Z21 = ex[-1] - Z21 - p1*Z11;
+    ex[-1] = Z21;
+    p1 = ell[-2];
+    p2 = ell[-2+lskip1];
+    Z31 = ex[-2] - Z31 - p1*Z11 - p2*Z21;
+    ex[-2] = Z31;
+    p1 = ell[-3];
+    p2 = ell[-3+lskip1];
+    p3 = ell[-3+lskip2];
+    Z41 = ex[-3] - Z41 - p1*Z11 - p2*Z21 - p3*Z31;
+    ex[-3] = Z41;
+    /* end of outer loop */
+  }
+  /* compute rows at end that are not a multiple of block size */
+  for (; i < n; i++) {
+    /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+    /* set the Z matrix to 0 */
+    Z11=0;
+    ell = L - i;
+    ex = B;
+    /* the inner loop that computes outer products and adds them to Z */
+    for (j=i-4; j >= 0; j -= 4) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      ell += lskip1;
+      Z11 += m11;
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[-1];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      ell += lskip1;
+      Z11 += m11;
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[-2];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      ell += lskip1;
+      Z11 += m11;
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[-3];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      ell += lskip1;
+      ex -= 4;
+      Z11 += m11;
+      /* end of inner loop */
+    }
+    /* compute left-over iterations */
+    j += 4;
+    for (; j > 0; j--) {
+      /* load p and q values */
+      p1=ell[0];
+      q1=ex[0];
+      /* compute outer product and add it to the Z matrix */
+      m11 = p1 * q1;
+      ell += lskip1;
+      ex -= 1;
+      Z11 += m11;
+    }
+    /* finish computing the X(i) block */
+    Z11 = ex[0] - Z11;
+    ex[0] = Z11;
+  }
+}
Index: /code/branches/ode/ode-0.9/ode/src/heightfield.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/heightfield.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/heightfield.cpp	(revision 216)
@@ -0,0 +1,1812 @@
+// dHeightfield Collider
+//  Paul Cheyrou-Lagreze aka Tuan Kuranes 2006 Speed enhancements http://www.pop-3d.com
+//  Martijn Buijs 2006 http://home.planet.nl/~buijs512/
+// Based on Terrain & Cone contrib by:
+//  Benoit CHAPEROT 2003-2004 http://www.jstarlab.com
+//  Some code inspired by Magic Software
+
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+#include "heightfield.h"
+
+
+
+#if dTRIMESH_ENABLED
+#include "collision_trimesh_internal.h"
+#endif // dTRIMESH_ENABLED
+
+#define TERRAINTOL REAL(0.0)
+
+#define dMIN(A,B)  ((A)>(B) ? B : A)
+#define dMAX(A,B)  ((A)>(B) ? A : B)
+
+
+// Three-way MIN and MAX
+#define dMIN3(A,B,C)	( (A)<(B) ? dMIN((A),(C)) : dMIN((B),(C)) )
+#define dMAX3(A,B,C)	( (A)>(B) ? dMAX((A),(C)) : dMAX((B),(C)) )
+
+#define dOPESIGN(a, op1, op2,b) \
+    (a)[0] op1 op2 ((b)[0]); \
+    (a)[1] op1 op2 ((b)[1]); \
+    (a)[2] op1 op2 ((b)[2]);
+
+#define dGeomRaySetNoNormalize(myRay, MyPoint, MyVector) {  \
+    \
+    dVector3Copy (MyPoint, myRay.final_posr->pos);   \
+    myRay.final_posr->R[2] = MyVector[0];       \
+    myRay.final_posr->R[6] = MyVector[1];       \
+    myRay.final_posr->R[10] = MyVector[2];      \
+    dGeomMoved (&myRay);                        \
+            }
+
+#define dGeomPlaneSetNoNormalize(MyPlane, MyPlaneDef) { \
+    \
+    MyPlane->p[0] = MyPlaneDef[0];  \
+    MyPlane->p[1] = MyPlaneDef[1];  \
+    MyPlane->p[2] = MyPlaneDef[2];  \
+    MyPlane->p[3] = MyPlaneDef[3];  \
+    dGeomMoved (MyPlane);           \
+                    }
+//////// Local Build Option ////////////////////////////////////////////////////
+
+// Uncomment this #define to use the (0,0) corner of the geom as the origin,
+// rather than the center. This was the way the original heightfield worked,
+// but as it does not match the way all other geometries work, so for constancy it
+// was changed to work like this.
+
+// #define DHEIGHTFIELD_CORNER_ORIGIN
+
+
+// Uncomment this #define to add heightfield triangles edge colliding
+// Code is not guaranteed and I didn't find the need to add that as 
+// colliding planes triangles and edge triangles seems enough.
+// #define _HEIGHTFIELDEDGECOLLIDING
+
+
+//////// dxHeightfieldData /////////////////////////////////////////////////////////////
+
+// dxHeightfieldData constructor
+dxHeightfieldData::dxHeightfieldData()
+{
+    //
+}
+
+
+// build Heightfield data
+void dxHeightfieldData::SetData( int nWidthSamples, int nDepthSamples,
+                                dReal fWidth, dReal fDepth,
+                                dReal fScale, dReal fOffset, dReal fThickness,
+                                int bWrapMode )
+{
+    dIASSERT( fWidth > REAL( 0.0 ) );
+    dIASSERT( fDepth > REAL( 0.0 ) );
+    dIASSERT( nWidthSamples > 0 );
+    dIASSERT( nDepthSamples > 0 );
+
+    // x,z bounds
+    m_fWidth = fWidth;
+    m_fDepth = fDepth;
+
+    // cache half x,z bounds
+    m_fHalfWidth = fWidth / REAL( 2.0 );
+    m_fHalfDepth = fDepth / REAL( 2.0 );
+
+    // scale and offset
+    m_fScale = fScale;
+    m_fOffset = fOffset;
+
+    // infinite min height bounds
+    m_fThickness = fThickness;
+
+    // number of vertices per side
+    m_nWidthSamples = nWidthSamples;
+    m_nDepthSamples = nDepthSamples;
+
+    m_fSampleWidth = m_fWidth / ( m_nWidthSamples - 1 );
+    m_fSampleDepth = m_fDepth / ( m_nDepthSamples - 1 );
+
+    m_fInvSampleWidth = 1 / m_fSampleWidth;
+    m_fInvSampleDepth = 1 / m_fSampleDepth;
+
+    // finite or repeated terrain?
+    m_bWrapMode = bWrapMode;
+}
+
+
+// recomputes heights bounds
+void dxHeightfieldData::ComputeHeightBounds()
+{
+    static int i;
+    static dReal h;
+    static unsigned char *data_byte;
+    static short *data_short;
+    static float *data_float;
+    static double *data_double;
+
+    switch ( m_nGetHeightMode )
+    {
+
+        // callback
+    case 0:
+        // change nothing, keep using default or user specified bounds
+        return;
+
+        // byte
+    case 1:
+        data_byte = (unsigned char*)m_pHeightData;
+        m_fMinHeight = dInfinity;
+        m_fMaxHeight = -dInfinity;
+
+        for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
+        {
+            h = data_byte[i];
+            if (h < m_fMinHeight)	m_fMinHeight = h;
+            if (h > m_fMaxHeight)	m_fMaxHeight = h;
+        }
+
+        break;
+
+        // short
+    case 2:
+        data_short = (short*)m_pHeightData;
+        m_fMinHeight = dInfinity;
+        m_fMaxHeight = -dInfinity;
+
+        for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
+        {
+            h = data_short[i];
+            if (h < m_fMinHeight)	m_fMinHeight = h;
+            if (h > m_fMaxHeight)	m_fMaxHeight = h;
+        }
+
+        break;
+
+        // float
+    case 3:
+        data_float = (float*)m_pHeightData;
+        m_fMinHeight = dInfinity;
+        m_fMaxHeight = -dInfinity;
+
+        for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
+        {
+            h = data_float[i];
+            if (h < m_fMinHeight)	m_fMinHeight = h;
+            if (h > m_fMaxHeight)	m_fMaxHeight = h;
+        }
+
+        break;
+
+        // double
+    case 4:
+        data_double = (double*)m_pHeightData;
+        m_fMinHeight = dInfinity;
+        m_fMaxHeight = -dInfinity;
+
+        for (i=0; i<m_nWidthSamples*m_nDepthSamples; i++)
+        {
+            h = static_cast< dReal >( data_double[i] );
+            if (h < m_fMinHeight)	m_fMinHeight = h;
+            if (h > m_fMaxHeight)	m_fMaxHeight = h;
+        }
+
+        break;
+
+    }
+
+    // scale and offset
+    m_fMinHeight *= m_fScale;
+    m_fMaxHeight *= m_fScale;
+    m_fMinHeight += m_fOffset;
+    m_fMaxHeight += m_fOffset;
+
+    // add thickness
+    m_fMinHeight -= m_fThickness;
+}
+
+
+// returns whether point is over terrain Cell triangle?
+bool dxHeightfieldData::IsOnHeightfield  ( const dReal * const CellOrigin, const dReal * const pos,  const bool isABC) const
+{
+    {
+        const dReal MaxX = CellOrigin[0] + m_fSampleWidth;
+        const dReal TolX = m_fSampleWidth * TERRAINTOL;
+        if ((pos[0]<CellOrigin[0]-TolX) || (pos[0]>MaxX+TolX))	
+            return false;
+    }
+
+    {
+        const dReal MaxZ = CellOrigin[2] + m_fSampleDepth;
+        const dReal TolZ = m_fSampleDepth * TERRAINTOL;
+        if ((pos[2]<CellOrigin[2]-TolZ) || (pos[2]>MaxZ+TolZ))	
+            return false;
+    }
+
+    // add X percentage position on cell and Z percentage position on cell
+    const dReal pctTotal = (pos[0] - CellOrigin[0]) * m_fInvSampleWidth 
+        + (pos[2] - CellOrigin[2]) * m_fInvSampleDepth;
+
+    if (isABC)
+    {
+        if (pctTotal >= REAL(1.0) + TERRAINTOL)	
+            return false;
+        else	
+            return true;
+    }
+    else if (pctTotal <= REAL(1.0) - TERRAINTOL)	
+    {
+        return false;
+    }
+    return true;
+}
+// returns whether point is over terrain Cell triangle?
+bool dxHeightfieldData::IsOnHeightfield2  ( const dReal * const CellOrigin, const dReal * const pos,  const bool isABC) const
+{
+    dReal MaxX, MinX;
+    dReal MaxZ, MinZ;
+    if (isABC)
+    {
+        // point A
+        MinX = CellOrigin[0];
+        MaxX = CellOrigin[0] + m_fSampleWidth;
+
+        MinZ = CellOrigin[2];
+        MaxZ = CellOrigin[2] + m_fSampleDepth;
+    }
+    else
+    {
+        // point D
+        MinX = CellOrigin[0] - m_fSampleWidth;
+        MaxX = CellOrigin[0];
+
+        MinZ = CellOrigin[2] - m_fSampleDepth;
+        MaxZ = CellOrigin[2];
+    }
+
+    // check if inside CELL
+    {
+        const dReal TolX = m_fSampleWidth * TERRAINTOL;
+        if ((pos[0]<MinX-TolX) || (pos[0]>MaxX+TolX))	
+            return false;
+    }
+
+    {
+        const dReal TolZ = m_fSampleDepth * TERRAINTOL;
+        if ((pos[2]<MinZ-TolZ) || (pos[2]>MaxZ+TolZ))	
+            return false;
+    }
+
+    // Sum up X percentage position on cell and Z percentage position on cell
+    const dReal pctTotal = (pos[0] - MinX) * m_fInvSampleWidth 
+        + (pos[2] - MinZ) * m_fInvSampleDepth;
+
+    // check if inside respective Triangle of Cell
+    if (isABC)	
+    {
+        if (pctTotal >= REAL(1.0) + TERRAINTOL)	
+            return false;
+        else	
+            return true;
+    }
+    else if (pctTotal <= REAL(1.0) - TERRAINTOL)	
+    {
+        return false;
+    }
+    return true;
+}
+
+
+// returns height at given sample coordinates
+dReal dxHeightfieldData::GetHeight( int x, int z )
+{
+    static dReal h;
+    static unsigned char *data_byte;
+    static short *data_short;
+    static float *data_float;
+    static double *data_double;
+
+    if ( m_bWrapMode == 0 )
+    {
+        // Finite
+        if ( x < 0 ) x = 0;
+        if ( z < 0 ) z = 0;
+        if ( x > m_nWidthSamples - 1 ) x = m_nWidthSamples - 1;
+        if ( z > m_nDepthSamples - 1 ) z = m_nDepthSamples - 1;
+    }
+    else
+    {
+        // Infinite
+        x %= m_nWidthSamples - 1;
+        z %= m_nDepthSamples - 1;
+        if ( x < 0 ) x += m_nWidthSamples - 1;
+        if ( z < 0 ) z += m_nDepthSamples - 1;
+    }
+
+    switch ( m_nGetHeightMode )
+    {
+
+        // callback (dReal)
+    case 0:
+        h = (*m_pGetHeightCallback)(m_pUserData, x, z);
+        break;
+
+        // byte
+    case 1:
+        data_byte = (unsigned char*)m_pHeightData;
+        h = data_byte[x+(z * m_nWidthSamples)];
+        break;
+
+        // short
+    case 2:
+        data_short = (short*)m_pHeightData;
+        h = data_short[x+(z * m_nWidthSamples)];
+        break;
+
+        // float
+    case 3:
+        data_float = (float*)m_pHeightData;
+        h = data_float[x+(z * m_nWidthSamples)];
+        break;
+
+        // double
+    case 4:
+        data_double = (double*)m_pHeightData;
+        h = static_cast< dReal >( data_double[x+(z * m_nWidthSamples)] );
+        break;
+    }
+
+    return (h * m_fScale) + m_fOffset;
+}
+
+
+// returns height at given coordinates
+dReal dxHeightfieldData::GetHeight( dReal x, dReal z )
+{
+	dReal dnX = dFloor( x * m_fInvSampleWidth );
+	dReal dnZ = dFloor( z * m_fInvSampleDepth );
+
+    dReal dx = ( x - ( dnX * m_fSampleWidth ) ) * m_fInvSampleWidth;
+    dReal dz = ( z - ( dnZ * m_fSampleDepth ) ) * m_fInvSampleDepth;
+
+    int nX = int( dnX );
+    int nZ = int( dnZ );
+
+    //dIASSERT( ( dx + dEpsilon >= 0.0f ) && ( dx - dEpsilon <= 1.0f ) );
+    //dIASSERT( ( dz + dEpsilon >= 0.0f ) && ( dz - dEpsilon <= 1.0f ) );
+
+    dReal y, y0;
+
+    if ( dx + dz < REAL( 1.0 ) )
+    {
+        y0 = GetHeight( nX, nZ );
+
+        y = y0 + ( GetHeight( nX + 1, nZ ) - y0 ) * dx
+            + ( GetHeight( nX, nZ + 1 ) - y0 ) * dz;
+    }
+    else
+    {
+        y0 = GetHeight( nX + 1, nZ + 1 );
+
+        y = y0	+ ( GetHeight( nX + 1, nZ ) - y0 ) * ( REAL(1.0) - dz ) +
+            ( GetHeight( nX, nZ + 1 ) - y0 ) * ( REAL(1.0) - dx );
+    }
+
+    return y;
+}
+
+
+// dxHeightfieldData destructor
+dxHeightfieldData::~dxHeightfieldData()
+{
+    static unsigned char *data_byte;
+    static short *data_short;
+    static float *data_float;
+    static double *data_double;
+
+    dIASSERT( m_pHeightData );
+
+    if ( m_bCopyHeightData )
+    {
+        switch ( m_nGetHeightMode )
+        {
+
+            // callback
+        case 0:
+            // do nothing
+            break;
+
+            // byte
+        case 1:
+            data_byte = (unsigned char*)m_pHeightData;
+            delete [] data_byte;
+            break;
+
+            // short
+        case 2:
+            data_short = (short*)m_pHeightData;
+            delete [] data_short;
+            break;
+
+            // float
+        case 3:
+            data_float = (float*)m_pHeightData;
+            delete [] data_float;
+            break;
+
+            // double
+        case 4:
+            data_double = (double*)m_pHeightData;
+            delete [] data_double;
+            break;
+
+        }
+    }
+}
+
+
+//////// dxHeightfield /////////////////////////////////////////////////////////////////
+
+
+// dxHeightfield constructor
+dxHeightfield::dxHeightfield( dSpaceID space,
+                             dHeightfieldDataID data,
+                             int bPlaceable )			:
+    dxGeom( space, bPlaceable ),
+    tempPlaneBuffer(0),
+	tempPlaneInstances(0),
+    tempPlaneBufferSize(0),
+    tempTriangleBuffer(0),
+    tempTriangleBufferSize(0),
+    tempHeightBuffer(0),
+	tempHeightInstances(0),
+    tempHeightBufferSizeX(0),
+    tempHeightBufferSizeZ(0)
+{
+    type = dHeightfieldClass;
+    this->m_p_data = data;
+}
+
+
+// compute axis aligned bounding box
+void dxHeightfield::computeAABB()
+{
+    const dxHeightfieldData *d = m_p_data;
+
+    if ( d->m_bWrapMode == 0 )
+    {
+        // Finite
+        if ( gflags & GEOM_PLACEABLE )
+        {
+            dReal dx[6], dy[6], dz[6];
+
+            // Y-axis
+            dy[0] = ( final_posr->R[ 1] * d->m_fMinHeight );
+            dy[1] = ( final_posr->R[ 5] * d->m_fMinHeight );
+            dy[2] = ( final_posr->R[ 9] * d->m_fMinHeight );
+            dy[3] = ( final_posr->R[ 1] * d->m_fMaxHeight );
+            dy[4] = ( final_posr->R[ 5] * d->m_fMaxHeight );
+            dy[5] = ( final_posr->R[ 9] * d->m_fMaxHeight );
+
+#ifdef DHEIGHTFIELD_CORNER_ORIGIN
+
+            // X-axis
+            dx[0] = 0;	dx[3] = ( final_posr->R[ 0] * d->m_fWidth );
+            dx[1] = 0;	dx[4] = ( final_posr->R[ 4] * d->m_fWidth );
+            dx[2] = 0;	dx[5] = ( final_posr->R[ 8] * d->m_fWidth );
+
+            // Z-axis
+            dz[0] = 0;	dz[3] = ( final_posr->R[ 2] * d->m_fDepth );
+            dz[1] = 0;	dz[4] = ( final_posr->R[ 6] * d->m_fDepth );
+            dz[2] = 0;	dz[5] = ( final_posr->R[10] * d->m_fDepth );
+
+#else // DHEIGHTFIELD_CORNER_ORIGIN
+
+            // X-axis
+            dx[0] = ( final_posr->R[ 0] * -d->m_fHalfWidth );
+            dx[1] = ( final_posr->R[ 4] * -d->m_fHalfWidth );
+            dx[2] = ( final_posr->R[ 8] * -d->m_fHalfWidth );
+            dx[3] = ( final_posr->R[ 0] * d->m_fHalfWidth );
+            dx[4] = ( final_posr->R[ 4] * d->m_fHalfWidth );
+            dx[5] = ( final_posr->R[ 8] * d->m_fHalfWidth );
+
+            // Z-axis
+            dz[0] = ( final_posr->R[ 2] * -d->m_fHalfDepth );
+            dz[1] = ( final_posr->R[ 6] * -d->m_fHalfDepth );
+            dz[2] = ( final_posr->R[10] * -d->m_fHalfDepth );
+            dz[3] = ( final_posr->R[ 2] * d->m_fHalfDepth );
+            dz[4] = ( final_posr->R[ 6] * d->m_fHalfDepth );
+            dz[5] = ( final_posr->R[10] * d->m_fHalfDepth );
+
+#endif // DHEIGHTFIELD_CORNER_ORIGIN
+
+            // X extents
+            aabb[0] = final_posr->pos[0] +
+                dMIN3( dMIN( dx[0], dx[3] ), dMIN( dy[0], dy[3] ), dMIN( dz[0], dz[3] ) );
+            aabb[1] = final_posr->pos[0] +
+                dMAX3( dMAX( dx[0], dx[3] ), dMAX( dy[0], dy[3] ), dMAX( dz[0], dz[3] ) );
+
+            // Y extents
+            aabb[2] = final_posr->pos[1] +
+                dMIN3( dMIN( dx[1], dx[4] ), dMIN( dy[1], dy[4] ), dMIN( dz[1], dz[4] ) );
+            aabb[3] = final_posr->pos[1] +
+                dMAX3( dMAX( dx[1], dx[4] ), dMAX( dy[1], dy[4] ), dMAX( dz[1], dz[4] ) );
+
+            // Z extents
+            aabb[4] = final_posr->pos[2] +
+                dMIN3( dMIN( dx[2], dx[5] ), dMIN( dy[2], dy[5] ), dMIN( dz[2], dz[5] ) );
+            aabb[5] = final_posr->pos[2] +
+                dMAX3( dMAX( dx[2], dx[5] ), dMAX( dy[2], dy[5] ), dMAX( dz[2], dz[5] ) );
+        }
+        else
+        {
+
+#ifdef DHEIGHTFIELD_CORNER_ORIGIN
+
+            aabb[0] = 0;					aabb[1] = d->m_fWidth;
+            aabb[2] = d->m_fMinHeight;		aabb[3] = d->m_fMaxHeight;
+            aabb[4] = 0;					aabb[5] = d->m_fDepth;
+
+#else // DHEIGHTFIELD_CORNER_ORIGIN
+
+            aabb[0] = -d->m_fHalfWidth;		aabb[1] = +d->m_fHalfWidth;
+            aabb[2] = d->m_fMinHeight;		aabb[3] = d->m_fMaxHeight;
+            aabb[4] = -d->m_fHalfDepth;		aabb[5] = +d->m_fHalfDepth;
+
+#endif // DHEIGHTFIELD_CORNER_ORIGIN
+
+        }
+    }
+    else
+    {
+        // Infinite
+        if ( gflags & GEOM_PLACEABLE )
+        {
+            aabb[0] = -dInfinity;			aabb[1] = +dInfinity;
+            aabb[2] = -dInfinity;			aabb[3] = +dInfinity;
+            aabb[4] = -dInfinity;			aabb[5] = +dInfinity;
+        }
+        else
+        {
+            aabb[0] = -dInfinity;			aabb[1] = +dInfinity;
+            aabb[2] = d->m_fMinHeight;		aabb[3] = d->m_fMaxHeight;
+            aabb[4] = -dInfinity;			aabb[5] = +dInfinity;
+        }
+    }
+
+}
+
+
+// dxHeightfield destructor
+dxHeightfield::~dxHeightfield()
+{
+	resetTriangleBuffer();
+	resetPlaneBuffer();
+	resetHeightBuffer();
+}
+
+void dxHeightfield::allocateTriangleBuffer(size_t numTri)
+{
+	size_t alignedNumTri = AlignBufferSize(numTri, TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT);
+	tempTriangleBufferSize = alignedNumTri;
+	tempTriangleBuffer = new HeightFieldTriangle[alignedNumTri];
+}
+
+void dxHeightfield::resetTriangleBuffer()
+{
+	delete[] tempTriangleBuffer;
+}
+
+void dxHeightfield::allocatePlaneBuffer(size_t numTri)
+{
+	size_t alignedNumTri = AlignBufferSize(numTri, TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT);
+	tempPlaneBufferSize = alignedNumTri;
+	tempPlaneBuffer = new HeightFieldPlane *[alignedNumTri];
+	tempPlaneInstances = new HeightFieldPlane[alignedNumTri];
+
+	HeightFieldPlane *ptrPlaneMatrix = tempPlaneInstances;
+	for (size_t indexTri = 0; indexTri != alignedNumTri; indexTri++)
+	{
+		tempPlaneBuffer[indexTri] = ptrPlaneMatrix;
+		ptrPlaneMatrix += 1;
+	}
+}
+
+void dxHeightfield::resetPlaneBuffer()
+{
+	delete[] tempPlaneInstances;
+    delete[] tempPlaneBuffer;
+}
+
+void dxHeightfield::allocateHeightBuffer(size_t numX, size_t numZ)
+{
+	size_t alignedNumX = AlignBufferSize(numX, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X);
+	size_t alignedNumZ = AlignBufferSize(numZ, TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z);
+	tempHeightBufferSizeX = alignedNumX;
+	tempHeightBufferSizeZ = alignedNumZ;
+	tempHeightBuffer = new HeightFieldVertex *[alignedNumX];
+	size_t numCells = alignedNumX * alignedNumZ;
+	tempHeightInstances = new HeightFieldVertex [numCells];
+	
+	HeightFieldVertex *ptrHeightMatrix = tempHeightInstances;
+	for (size_t indexX = 0; indexX != alignedNumX; indexX++)
+	{
+		tempHeightBuffer[indexX] = ptrHeightMatrix;
+		ptrHeightMatrix += alignedNumZ;
+	}
+}
+
+void dxHeightfield::resetHeightBuffer()
+{
+	delete[] tempHeightInstances;
+    delete[] tempHeightBuffer;
+}
+//////// Heightfield data interface ////////////////////////////////////////////////////
+
+
+dHeightfieldDataID dGeomHeightfieldDataCreate()
+{
+    return new dxHeightfieldData();
+}
+
+
+void dGeomHeightfieldDataBuildCallback( dHeightfieldDataID d,
+                                       void* pUserData, dHeightfieldGetHeight* pCallback,
+                                       dReal width, dReal depth, int widthSamples, int depthSamples,
+                                       dReal scale, dReal offset, dReal thickness, int bWrap )
+{
+    dUASSERT( d, "argument not Heightfield data" );
+    dIASSERT( pCallback );
+    dIASSERT( widthSamples >= 2 );	// Ensure we're making something with at least one cell.
+    dIASSERT( depthSamples >= 2 );
+
+    // callback
+    d->m_nGetHeightMode = 0;
+    d->m_pUserData = pUserData;
+    d->m_pGetHeightCallback = pCallback;
+
+    // set info
+    d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
+
+    // default bounds
+    d->m_fMinHeight = -dInfinity;
+    d->m_fMaxHeight = dInfinity;
+}
+
+
+void dGeomHeightfieldDataBuildByte( dHeightfieldDataID d,
+                                   const unsigned char *pHeightData, int bCopyHeightData,
+                                   dReal width, dReal depth, int widthSamples, int depthSamples,
+                                   dReal scale, dReal offset, dReal thickness, int bWrap )
+{
+    dUASSERT( d, "Argument not Heightfield data" );
+    dIASSERT( pHeightData );
+    dIASSERT( widthSamples >= 2 );	// Ensure we're making something with at least one cell.
+    dIASSERT( depthSamples >= 2 );
+
+    // set info
+    d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
+    d->m_nGetHeightMode = 1;
+    d->m_bCopyHeightData = bCopyHeightData;
+
+    if ( d->m_bCopyHeightData == 0 )
+    {
+        // Data is referenced only.
+        d->m_pHeightData = pHeightData;
+    }
+    else
+    {
+        // We own the height data, allocate storage
+        d->m_pHeightData = new unsigned char[ d->m_nWidthSamples * d->m_nDepthSamples ];
+        dIASSERT( d->m_pHeightData );
+
+        // Copy data.
+        memcpy( (void*)d->m_pHeightData, pHeightData,
+            sizeof( unsigned char ) * d->m_nWidthSamples * d->m_nDepthSamples );
+    }
+
+    // Find height bounds
+    d->ComputeHeightBounds();
+}
+
+
+void dGeomHeightfieldDataBuildShort( dHeightfieldDataID d,
+                                    const short* pHeightData, int bCopyHeightData,
+                                    dReal width, dReal depth, int widthSamples, int depthSamples,
+                                    dReal scale, dReal offset, dReal thickness, int bWrap )
+{
+    dUASSERT( d, "Argument not Heightfield data" );
+    dIASSERT( pHeightData );
+    dIASSERT( widthSamples >= 2 );	// Ensure we're making something with at least one cell.
+    dIASSERT( depthSamples >= 2 );
+
+    // set info
+    d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
+    d->m_nGetHeightMode = 2;
+    d->m_bCopyHeightData = bCopyHeightData;
+
+    if ( d->m_bCopyHeightData == 0 )
+    {
+        // Data is referenced only.
+        d->m_pHeightData = pHeightData;
+    }
+    else
+    {
+        // We own the height data, allocate storage
+        d->m_pHeightData = new short[ d->m_nWidthSamples * d->m_nDepthSamples ];
+        dIASSERT( d->m_pHeightData );
+
+        // Copy data.
+        memcpy( (void*)d->m_pHeightData, pHeightData,
+            sizeof( short ) * d->m_nWidthSamples * d->m_nDepthSamples );
+    }
+
+    // Find height bounds
+    d->ComputeHeightBounds();
+}
+
+
+void dGeomHeightfieldDataBuildSingle( dHeightfieldDataID d,
+                                     const float *pHeightData, int bCopyHeightData,
+                                     dReal width, dReal depth, int widthSamples, int depthSamples,
+                                     dReal scale, dReal offset, dReal thickness, int bWrap )
+{
+    dUASSERT( d, "Argument not Heightfield data" );
+    dIASSERT( pHeightData );
+    dIASSERT( widthSamples >= 2 );	// Ensure we're making something with at least one cell.
+    dIASSERT( depthSamples >= 2 );
+
+    // set info
+    d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
+    d->m_nGetHeightMode = 3;
+    d->m_bCopyHeightData = bCopyHeightData;
+
+    if ( d->m_bCopyHeightData == 0 )
+    {
+        // Data is referenced only.
+        d->m_pHeightData = pHeightData;
+    }
+    else
+    {
+        // We own the height data, allocate storage
+        d->m_pHeightData = new float[ d->m_nWidthSamples * d->m_nDepthSamples ];
+        dIASSERT( d->m_pHeightData );
+
+        // Copy data.
+        memcpy( (void*)d->m_pHeightData, pHeightData,
+            sizeof( float ) * d->m_nWidthSamples * d->m_nDepthSamples );
+    }
+
+    // Find height bounds
+    d->ComputeHeightBounds();
+}
+
+void dGeomHeightfieldDataBuildDouble( dHeightfieldDataID d,
+                                     const double *pHeightData, int bCopyHeightData,
+                                     dReal width, dReal depth, int widthSamples, int depthSamples,
+                                     dReal scale, dReal offset, dReal thickness, int bWrap )
+{
+    dUASSERT( d, "Argument not Heightfield data" );
+    dIASSERT( pHeightData );
+    dIASSERT( widthSamples >= 2 );	// Ensure we're making something with at least one cell.
+    dIASSERT( depthSamples >= 2 );
+
+    // set info
+    d->SetData( widthSamples, depthSamples, width, depth, scale, offset, thickness, bWrap );
+    d->m_nGetHeightMode = 4;
+    d->m_bCopyHeightData = bCopyHeightData;
+
+    if ( d->m_bCopyHeightData == 0 )
+    {
+        // Data is referenced only.
+        d->m_pHeightData = pHeightData;
+    }
+    else
+    {
+        // We own the height data, allocate storage
+        d->m_pHeightData = new double[ d->m_nWidthSamples * d->m_nDepthSamples ];
+        dIASSERT( d->m_pHeightData );
+
+        // Copy data.
+        memcpy( (void*)d->m_pHeightData, pHeightData,
+            sizeof( double ) * d->m_nWidthSamples * d->m_nDepthSamples );
+    }
+
+    // Find height bounds
+    d->ComputeHeightBounds();
+}
+
+
+
+
+void dGeomHeightfieldDataSetBounds( dHeightfieldDataID d, dReal minHeight, dReal maxHeight )
+{
+    dUASSERT(d, "Argument not Heightfield data");
+    d->m_fMinHeight = ( minHeight * d->m_fScale ) + d->m_fOffset - d->m_fThickness;
+    d->m_fMaxHeight = ( maxHeight * d->m_fScale ) + d->m_fOffset;
+}
+
+
+void dGeomHeightfieldDataDestroy( dHeightfieldDataID d )
+{
+    dUASSERT(d, "argument not Heightfield data");
+    delete d;
+}
+
+
+//////// Heightfield geom interface ////////////////////////////////////////////////////
+
+
+dGeomID dCreateHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable )
+{
+    return new dxHeightfield( space, data, bPlaceable );
+}
+
+
+void dGeomHeightfieldSetHeightfieldData( dGeomID g, dHeightfieldDataID d )
+{
+    dxHeightfield* geom = (dxHeightfield*) g;
+    geom->data = d;
+}
+
+
+dHeightfieldDataID dGeomHeightfieldGetHeightfieldData( dGeomID g )
+{
+    dxHeightfield* geom = (dxHeightfield*) g;
+    return geom->m_p_data;
+}
+
+//////// dxHeightfield /////////////////////////////////////////////////////////////////
+
+
+// Typedef for generic 'get point depth' function
+typedef dReal dGetDepthFn( dGeomID g, dReal x, dReal y, dReal z );
+
+
+#define DMESS(A)	\
+    dMessage(0,"Contact Plane (%d %d %d) %.5e %.5e (%.5e %.5e %.5e)(%.5e %.5e %.5e)).",	\
+    x,z,A,	\
+    pContact->depth,	\
+    dGeomSphereGetRadius(o2),		\
+    pContact->pos[0],	\
+    pContact->pos[1],	\
+    pContact->pos[2],	\
+    pContact->normal[0],	\
+    pContact->normal[1],	\
+    pContact->normal[2]);
+
+static inline bool DescendingTriangleSort(const HeightFieldTriangle * const A, const HeightFieldTriangle * const B)
+{
+    return ((A->maxAAAB - B->maxAAAB) > dEpsilon);
+}
+static inline bool DescendingPlaneSort(const HeightFieldPlane * const A, const HeightFieldPlane * const B)
+{
+    return ((A->maxAAAB - B->maxAAAB) > dEpsilon);
+}
+
+void dxHeightfield::sortPlanes(const size_t numPlanes)
+{
+    bool has_swapped = true;
+    do
+    {
+        has_swapped = false;//reset flag
+        for (size_t i = 0; i < numPlanes - 1; i++)
+        {
+            //if they are in the wrong order
+            if (DescendingPlaneSort(tempPlaneBuffer[i], tempPlaneBuffer[i + 1]))
+            { 
+                //exchange them
+                HeightFieldPlane * tempPlane = tempPlaneBuffer[i];
+                tempPlaneBuffer[i] = tempPlaneBuffer[i + 1];
+                tempPlaneBuffer[i + 1] = tempPlane;
+
+                //we have swapped at least once, list may not be sorted yet
+                has_swapped = true;
+            }
+        }
+    }    //if no swaps were made during this pass, the list has been sorted
+    while (has_swapped);
+}
+
+static inline dReal DistancePointToLine(const dVector3 &_point,
+                                         const dVector3 &_pt0,
+                                         const dVector3 &_Edge,
+                                         const dReal _Edgelength)
+{
+    dVector3 v;
+    dVector3Subtract(_point, _pt0, v);
+    dVector3 s;
+    dVector3Copy (_Edge, s);
+    const dReal dot = dVector3Dot(v, _Edge) / _Edgelength;
+    dVector3Scale(s, dot);
+    dVector3Subtract(v, s, v);
+    return dVector3Length(v);
+}
+
+
+
+
+int dxHeightfield::dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ, 
+                                           dxGeom* o2, const int numMaxContactsPossible,
+                                           int flags, dContactGeom* contact, 
+                                           int skip )
+{
+	dContactGeom *pContact = 0;
+    int  x, z;
+    // check if not above or inside terrain first
+    // while filling a heightmap partial temporary buffer
+    const unsigned int numX = (maxX - minX) + 1;
+    const unsigned int numZ = (maxZ - minZ) + 1;
+    const dReal minO2Height = o2->aabb[2];
+    const dReal maxO2Height = o2->aabb[3];
+    unsigned int x_local, z_local;
+    dReal maxY = - dInfinity;
+    dReal minY = dInfinity;
+    // localize and const for faster access
+    const dReal cfSampleWidth = m_p_data->m_fSampleWidth;
+    const dReal cfSampleDepth = m_p_data->m_fSampleDepth;
+    {
+        if (tempHeightBufferSizeX < numX || tempHeightBufferSizeZ < numZ)
+        {
+            resetHeightBuffer();
+			allocateHeightBuffer(numX, numZ);
+        }
+
+        dReal Xpos, Ypos;
+        Xpos = minX * cfSampleWidth;
+
+
+        for ( x = minX, x_local = 0; x_local < numX; x++, x_local++)
+        {
+            const dReal c_Xpos = Xpos;
+            HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local];
+            Ypos = minZ * cfSampleDepth;
+            for ( z = minZ, z_local = 0; z_local < numZ; z++, z_local++)
+            {
+                const dReal h = m_p_data->GetHeight(x, z);
+                HeightFieldRow[z_local].vertex[0] = c_Xpos;
+                HeightFieldRow[z_local].vertex[1] = h;
+                HeightFieldRow[z_local].vertex[2] = Ypos;
+                
+
+                maxY = dMAX(maxY, h);
+                minY = dMIN(minY, h);
+
+
+                Ypos += cfSampleDepth;
+            }
+            Xpos += cfSampleWidth;
+        }
+        if (minO2Height - maxY > -dEpsilon )
+        {
+			//totally above heightfield
+            return 0;
+        }
+		if (minY - maxO2Height > -dEpsilon )
+		{
+			// totally under heightfield
+			pContact = CONTACT(contact, 0);
+
+			pContact->pos[0] = o2->final_posr->pos[0];
+			pContact->pos[1] = minY;
+			pContact->pos[2] = o2->final_posr->pos[2];
+
+			pContact->normal[0] = 0;
+			pContact->normal[1] = - 1;
+			pContact->normal[2] = 0;
+
+			pContact->depth =  minY - maxO2Height;
+
+			return 1;
+		}
+    }
+    // get All Planes that could collide against.
+    dColliderFn *geomRayNCollider;
+    dColliderFn *geomNPlaneCollider;
+    dGetDepthFn *geomNDepthGetter;
+
+    // int max_collisionContact = numMaxContactsPossible; -- not used
+    switch (o2->type)
+    {
+    case dRayClass:
+        geomRayNCollider		= NULL;
+        geomNPlaneCollider	    = dCollideRayPlane;
+        geomNDepthGetter		= NULL;
+        //max_collisionContact    = 1;
+        break;
+
+    case dSphereClass:
+        geomRayNCollider		= dCollideRaySphere;
+        geomNPlaneCollider  	= dCollideSpherePlane;
+        geomNDepthGetter		= dGeomSpherePointDepth;
+        //max_collisionContact    = 3;
+        break;
+
+    case dBoxClass:
+        geomRayNCollider		= dCollideRayBox;
+        geomNPlaneCollider	    = dCollideBoxPlane;
+        geomNDepthGetter		= dGeomBoxPointDepth;
+        //max_collisionContact    = 8;
+        break;
+
+    case dCapsuleClass:
+        geomRayNCollider		= dCollideRayCapsule;
+        geomNPlaneCollider  	= dCollideCapsulePlane;
+        geomNDepthGetter		= dGeomCapsulePointDepth;
+        // max_collisionContact    = 3;
+        break;
+
+    case dCylinderClass:
+        geomRayNCollider		= dCollideRayCylinder;
+        geomNPlaneCollider	    = dCollideCylinderPlane;
+        geomNDepthGetter		= NULL;// TODO: dGeomCCylinderPointDepth
+        //max_collisionContact    = 3;
+        break;
+
+    case dConvexClass:
+        geomRayNCollider		= dCollideRayConvex;
+        geomNPlaneCollider  	= dCollideConvexPlane;
+        geomNDepthGetter		= NULL;// TODO: dGeomConvexPointDepth;
+        //max_collisionContact    = 3;
+        break;
+
+#if dTRIMESH_ENABLED
+
+    case dTriMeshClass:
+        geomRayNCollider		= dCollideRayTrimesh;
+        geomNPlaneCollider	    = dCollideTrimeshPlane;
+        geomNDepthGetter		= NULL;// TODO: dGeomTrimeshPointDepth;
+        //max_collisionContact    = 3;
+        break;
+
+#endif // dTRIMESH_ENABLED
+
+    default:
+        dIASSERT(0);	// Shouldn't ever get here.
+        break;
+
+    }
+
+    dxPlane myplane(0,0,0,0,0);
+    dxPlane* sliding_plane = &myplane;
+    dReal triplane[4];
+    int i;
+
+    // check some trivial case.
+    // Vector Up plane
+    if (maxY - minY < dEpsilon)
+    {
+        // it's a single plane.
+        triplane[0] = 0;
+        triplane[1] = 1;
+        triplane[2] = 0;
+        triplane[3] =  minY;
+        dGeomPlaneSetNoNormalize (sliding_plane, triplane);
+        // find collision and compute contact points
+		const int numTerrainContacts = geomNPlaneCollider (o2, sliding_plane, flags, contact, skip);
+		dIASSERT(numTerrainContacts <= numMaxContactsPossible);
+        for (i = 0; i < numTerrainContacts; i++)
+        {
+			pContact = CONTACT(contact, i*skip);
+            dOPESIGN(pContact->normal, =, -, triplane);
+        }
+        return numTerrainContacts;
+    }
+    // unique plane
+    {
+        // check for very simple plane heightfield
+        dReal minXHeightDelta = dInfinity, maxXHeightDelta = - dInfinity;
+        dReal minZHeightDelta = dInfinity, maxZHeightDelta = - dInfinity;
+
+
+        dReal lastXHeight = tempHeightBuffer[0][0].vertex[1];
+        for ( x_local = 1; x_local < numX; x_local++)
+        {
+            HeightFieldVertex *HeightFieldRow = tempHeightBuffer[x_local];
+
+            const dReal deltaX = HeightFieldRow[0].vertex[1] - lastXHeight;
+
+            maxXHeightDelta = dMAX (maxXHeightDelta,  deltaX);
+            minXHeightDelta = dMIN (minXHeightDelta,  deltaX);
+
+            dReal lastZHeight = HeightFieldRow[0].vertex[1];
+            for ( z_local = 1; z_local < numZ; z_local++)
+            {
+                const dReal deltaZ = (HeightFieldRow[z_local].vertex[1] - lastZHeight);
+
+                maxZHeightDelta = dMAX (maxZHeightDelta,  deltaZ);
+                minZHeightDelta = dMIN (minZHeightDelta,  deltaZ);
+
+            }
+        }
+
+        if (maxZHeightDelta - minZHeightDelta < dEpsilon && 
+            maxXHeightDelta - minXHeightDelta < dEpsilon )
+        {
+            // it's a single plane.
+            const dVector3 &A = tempHeightBuffer[0][0].vertex;
+            const dVector3 &B = tempHeightBuffer[1][0].vertex;
+            const dVector3 &C = tempHeightBuffer[0][1].vertex;
+
+            // define 2 edges and a point that will define collision plane
+            {
+                dVector3 Edge1, Edge2; 
+                dVector3Subtract(C, A, Edge1);
+                dVector3Subtract(B, A, Edge2);
+                dVector3Cross(Edge1, Edge2, triplane);
+            }
+
+            // Define Plane
+            // Normalize plane normal
+            const dReal dinvlength = REAL(1.0) / dVector3Length(triplane);
+            triplane[0] *= dinvlength;
+            triplane[1] *= dinvlength;
+            triplane[2] *= dinvlength;
+            // get distance to origin from plane 
+            triplane[3] = dVector3Dot(triplane, A);
+
+            dGeomPlaneSetNoNormalize (sliding_plane, triplane);
+            // find collision and compute contact points
+            const int numTerrainContacts = geomNPlaneCollider (o2, sliding_plane, flags, contact, skip);
+			dIASSERT(numTerrainContacts <= numMaxContactsPossible);
+            for (i = 0; i < numTerrainContacts; i++)
+            {
+				pContact = CONTACT(contact, i*skip);
+                dOPESIGN(pContact->normal, =, -, triplane);
+            }
+            return numTerrainContacts;
+        }
+    }
+
+
+	int numTerrainContacts = 0;
+	dContactGeom *PlaneContact = m_p_data->m_contacts;
+	
+    const unsigned int numTriMax = (maxX - minX) * (maxZ - minZ) * 2;
+    if (tempTriangleBufferSize < numTriMax)
+    {
+        resetTriangleBuffer();
+		allocateTriangleBuffer(numTriMax);
+    }
+    
+    // Sorting triangle/plane  resulting from heightfield zone
+    // Perhaps that would be necessary in case of too much limited
+    // maximum contact point...
+    // or in complex mesh case (trimesh and convex)
+    // need some test or insights on this before enabling this.
+    const bool isContactNumPointsLimited = 
+        true;
+    // (numMaxContacts < 8)
+    //    || o2->type == dConvexClass
+    //    || o2->type == dTriMeshClass
+    //    || (numMaxContacts < (int)numTriMax)       
+        
+
+
+    // if small heightfield triangle related to O2 colliding
+    // or no Triangle colliding at all.
+    bool needFurtherPasses = (o2->type == dTriMeshClass);
+    //compute Ratio between Triangle size and O2 aabb size
+	// no FurtherPasses are needed in ray class
+    if (o2->type != dRayClass  && needFurtherPasses == false)
+    {
+        const dReal xratio = (o2->aabb[1] - o2->aabb[0]) * m_p_data->m_fInvSampleWidth;
+        if (xratio > REAL(1.5))
+            needFurtherPasses = true;
+        else
+        {
+            const dReal zratio = (o2->aabb[5] - o2->aabb[4]) * m_p_data->m_fInvSampleDepth;
+            if (zratio > REAL(1.5))
+                needFurtherPasses = true;
+        }
+
+    }
+
+    unsigned int numTri = 0;
+    HeightFieldVertex *A, *B, *C, *D;
+    /*    (y is up)
+         A--------B-...x
+         |       /|
+         |      / |
+         |     /  |
+         |    /   |
+         |   /    |
+         |  /     |
+         | /      |
+         |/       |
+         C--------D   
+         .
+         .
+         .
+         z
+    */  
+    // keep only triangle that does intersect geom
+    for ( x = minX, x_local = 0; x < maxX; x++, x_local++)
+    {
+        HeightFieldVertex *HeightFieldRow      = tempHeightBuffer[x_local];
+        HeightFieldVertex *HeightFieldNextRow  = tempHeightBuffer[x_local + 1];
+
+        // First A
+        C = &HeightFieldRow    [0];
+        // First B
+        D = &HeightFieldNextRow[0];
+        for ( z = minZ, z_local = 0; z < maxZ; z++, z_local++)
+        {
+            A = C;
+            B = D;
+
+            C = &HeightFieldRow    [z_local + 1];
+            D = &HeightFieldNextRow[z_local + 1];
+
+            const dReal AHeight = A->vertex[1];
+            const dReal BHeight = B->vertex[1];
+            const dReal CHeight = C->vertex[1];
+            const dReal DHeight = D->vertex[1];
+
+            const bool isACollide = 0 < AHeight - minO2Height;
+            const bool isBCollide = 0 < BHeight - minO2Height;
+            const bool isCCollide = 0 < CHeight - minO2Height;
+            const bool isDCollide = 0 < DHeight - minO2Height;
+
+            A->state = !(isACollide);
+            B->state = !(isBCollide);
+            C->state = !(isCCollide);
+            D->state = !(isCCollide);
+
+            if (isACollide || isBCollide || isCCollide)
+            {
+                HeightFieldTriangle * const CurrTriUp = &tempTriangleBuffer[numTri++];
+
+                CurrTriUp->state = false;
+
+                // changing point order here implies to change it in isOnHeightField
+                CurrTriUp->vertices[0] = A;
+                CurrTriUp->vertices[1] = B;
+                CurrTriUp->vertices[2] = C;
+
+                if (isContactNumPointsLimited)
+                    CurrTriUp->setMinMax();
+                CurrTriUp->isUp = true;
+            }
+
+            if (isBCollide || isCCollide || isDCollide)
+            {
+                HeightFieldTriangle * const CurrTriDown = &tempTriangleBuffer[numTri++];
+
+                CurrTriDown->state = false;
+                // changing point order here implies to change it in isOnHeightField
+
+                CurrTriDown->vertices[0] = D;
+                CurrTriDown->vertices[1] = B;
+                CurrTriDown->vertices[2] = C;
+
+
+                if (isContactNumPointsLimited)
+                    CurrTriDown->setMinMax();
+                CurrTriDown->isUp = false;
+            }
+
+
+            if (needFurtherPasses &&
+                (isBCollide || isCCollide)
+                &&
+                (AHeight - CHeight > 0 &&
+                 AHeight - BHeight > 0 &&
+                 DHeight - CHeight > 0 &&
+                 DHeight - BHeight > 0))
+            {
+                // That means Edge BC is concave, therefore
+                // BC Edge and B and C vertices cannot collide
+
+                B->state = true;
+                C->state = true;
+            }
+            // should find a way to check other edges (AB, BD, CD) too for concavity
+        }
+    }
+
+    // at least on triangle should intersect geom
+    dIASSERT (numTri != 0);
+    // pass1: VS triangle as Planes
+    // Group Triangle by same plane definition
+    // as Terrain often has many triangles using same plane definition
+    // then collide against that list of triangles.
+    {
+
+        dVector3 Edge1, Edge2;
+        //compute all triangles normals.
+        for (unsigned int k = 0; k < numTri; k++)
+        {
+            HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k];
+
+            // define 2 edges and a point that will define collision plane
+            dVector3Subtract(itTriangle->vertices[2]->vertex, itTriangle->vertices[0]->vertex, Edge1);
+            dVector3Subtract(itTriangle->vertices[1]->vertex, itTriangle->vertices[0]->vertex, Edge2);
+
+            // find a perpendicular vector to the triangle
+            if  (itTriangle->isUp)
+                dVector3Cross(Edge1, Edge2, triplane);
+            else
+                dVector3Cross(Edge2, Edge1, triplane);
+
+            // Define Plane
+            // Normalize plane normal
+            const dReal dinvlength = REAL(1.0) / dVector3Length(triplane);
+            triplane[0] *= dinvlength;
+            triplane[1] *= dinvlength;
+            triplane[2] *= dinvlength;
+            // get distance to origin from plane 
+            triplane[3] = dVector3Dot(triplane, itTriangle->vertices[0]->vertex);
+
+            // saves normal for collision check (planes, triangles, vertices and edges.)
+            dVector3Copy(triplane, itTriangle->planeDef);
+            // saves distance for collision check (planes, triangles, vertices and edges.)
+            itTriangle->planeDef[3] = triplane[3];
+        }
+
+        // group by Triangles by Planes sharing shame plane definition
+        if (tempPlaneBufferSize  < numTri)
+        {
+            resetPlaneBuffer();
+			allocatePlaneBuffer(numTri);
+        }
+        unsigned int numPlanes = 0;
+        for (unsigned int k = 0; k < numTri; k++)
+        {
+            HeightFieldTriangle * const tri_base = &tempTriangleBuffer[k];
+
+            if (tri_base->state == true)
+                continue;// already tested or added to plane list.
+
+            HeightFieldPlane * const currPlane = tempPlaneBuffer[numPlanes];
+            currPlane->resetTriangleListSize(numTri - k);
+            currPlane->addTriangle(tri_base);
+            // saves normal for collision check (planes, triangles, vertices and edges.)
+            dVector3Copy(tri_base->planeDef, currPlane->planeDef);
+            // saves distance for collision check (planes, triangles, vertices and edges.)
+            currPlane->planeDef[3]= tri_base->planeDef[3];
+
+            const dReal normx = tri_base->planeDef[0];
+            const dReal normy = tri_base->planeDef[1];
+            const dReal normz = tri_base->planeDef[2];
+            const dReal dist = tri_base->planeDef[3];
+
+            for (unsigned int m = k + 1; m < numTri; m++)
+            {
+
+                HeightFieldTriangle * const tri_test = &tempTriangleBuffer[m];
+                if (tri_test->state == true)
+                    continue;// already tested or added to plane list.
+
+                // normals and distance are the same.
+                if (
+                    dFabs(normy - tri_test->planeDef[1]) < dEpsilon &&  
+                    dFabs(dist  - tri_test->planeDef[3]) < dEpsilon &&
+                    dFabs(normx - tri_test->planeDef[0]) < dEpsilon && 
+                    dFabs(normz - tri_test->planeDef[2]) < dEpsilon
+                    )
+                {
+                    currPlane->addTriangle (tri_test);
+                    tri_test->state = true;
+                }
+            }
+
+            tri_base->state = true;
+            if (isContactNumPointsLimited)
+                currPlane->setMinMax();
+
+            numPlanes++;
+        }
+
+        // sort planes
+        if (isContactNumPointsLimited)
+            sortPlanes(numPlanes);
+
+#if !defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2)
+		/*
+			Note by Oleh_Derevenko:
+			It seems to be incorrect to limit contact count by some particular value
+			since some of them (and even all of them) may be culled in following condition.
+			However I do not see an easy way to fix this.
+			If not that culling the flags modification should be changed here and
+			additionally repeated after some contacts have been generated (in "if (didCollide)").
+			The maximum of contacts in flags would then be set to minimum of contacts
+			remaining and HEIGHTFIELDMAXCONTACTPERCELL.
+		*/
+		int planeTestFlags = (flags & ~NUMC_MASK) | HEIGHTFIELDMAXCONTACTPERCELL;
+		dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
+#else // if defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2)
+		int numMaxContactsPerPlane = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
+		int planeTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerPlane;
+		dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
+#endif        
+        
+		for (unsigned int k = 0; k < numPlanes; k++)
+        {
+            HeightFieldPlane * const itPlane = tempPlaneBuffer[k];
+
+            //set Geom
+            dGeomPlaneSetNoNormalize (sliding_plane,  itPlane->planeDef);
+            //dGeomPlaneSetParams (sliding_plane, triangle_Plane[0], triangle_Plane[1], triangle_Plane[2], triangle_Plane[3]);
+            // find collision and compute contact points
+            bool didCollide = false;
+			const int numPlaneContacts = geomNPlaneCollider (o2, sliding_plane, planeTestFlags, PlaneContact, sizeof(dContactGeom));
+			const size_t planeTriListSize = itPlane->trianglelistCurrentSize;
+            for (i = 0; i < numPlaneContacts; i++)
+            {
+                // Check if contact point found in plane is inside Triangle.
+                const dVector3 &pCPos = PlaneContact[i].pos;
+                for (size_t b = 0; planeTriListSize > b; b++)
+                {  
+                    if (m_p_data->IsOnHeightfield2 (itPlane->trianglelist[b]->vertices[0]->vertex, 
+                                                    pCPos, 
+                                                    itPlane->trianglelist[b]->isUp))
+                    {
+						pContact = CONTACT(contact, numTerrainContacts*skip);
+						dVector3Copy(pCPos, pContact->pos);
+						dOPESIGN(pContact->normal, =, -, itPlane->planeDef);
+						pContact->depth = PlaneContact[i].depth;
+						numTerrainContacts++;
+						if ( numTerrainContacts == numMaxContactsPossible )
+							return numTerrainContacts;
+
+						didCollide = true;
+						break;
+					}
+				}
+            }
+            if (didCollide)
+            {
+#if defined(NO_CONTACT_CULLING_BY_ISONHEIGHTFIELD2)
+				/* Note by Oleh_Derevenko:
+					This code is not used - see another note above
+				*/
+				numMaxContactsPerPlane = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
+		        planeTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerPlane;
+		        dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
+#endif        
+                for (size_t b = 0; planeTriListSize > b; b++)
+                {                      
+                    // flag Triangles Vertices as collided 
+                    // to prevent any collision test of those
+                    for (i = 0; i < 3; i++)
+                        itPlane->trianglelist[b]->vertices[i]->state = true;
+                }
+            }
+            else 
+            {
+                // flag triangle as not collided so that Vertices or Edge
+                // of that triangles will be checked.
+                for (size_t b = 0; planeTriListSize > b; b++)
+                { 
+                    itPlane->trianglelist[b]->state = false;
+                }
+            }
+        }
+    }
+    
+
+   
+    // pass2: VS triangle vertices
+    if (needFurtherPasses)
+    {
+        dxRay tempRay(0, 1); 
+        dReal depth;
+        bool vertexCollided;
+
+		// Only one contact is necessary for ray test
+		int rayTestFlags = (flags & ~NUMC_MASK) | 1;
+		dIASSERT((1 & ~NUMC_MASK) == 0);
+        //
+        // Find Contact Penetration Depth of each vertices
+        //
+        for (unsigned int k = 0; k < numTri; k++)
+        {
+            const HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k];
+            if (itTriangle->state == true)
+                continue;// plane triangle did already collide.
+
+            for (size_t i = 0; i < 3; i++)
+            {
+                HeightFieldVertex *vertex = itTriangle->vertices[i];
+                if (vertex->state == true)
+                    continue;// vertice did already collide.
+
+                vertexCollided = false;
+                const dVector3 &triVertex = vertex->vertex;
+                if ( geomNDepthGetter )
+                {
+                    depth = geomNDepthGetter( o2,
+                        triVertex[0], triVertex[1], triVertex[2] );
+                    if (depth + dEpsilon < 0)
+                        vertexCollided = true;
+                }
+                else
+                {
+                    // We don't have a GetDepth function, so do a ray cast instead.
+                    // NOTE: This isn't ideal, and a GetDepth function should be
+                    // written for all geom classes.
+                    tempRay.length = (minO2Height - triVertex[1]) * REAL(1000.0);
+
+                    //dGeomRaySet( &tempRay, pContact->pos[0], pContact->pos[1], pContact->pos[2],
+                    //    - itTriangle->Normal[0], - itTriangle->Normal[1], - itTriangle->Normal[2] );
+                    dGeomRaySetNoNormalize(tempRay, triVertex, itTriangle->planeDef);
+
+                    if ( geomRayNCollider( &tempRay, o2, rayTestFlags, PlaneContact, sizeof( dContactGeom ) ) )
+                    {
+                        depth = PlaneContact[0].depth;
+                        vertexCollided = true;
+                    }
+                }
+                if (vertexCollided)
+                {
+                    pContact = CONTACT(contact, numTerrainContacts*skip);
+                    //create contact using vertices
+                    dVector3Copy (triVertex, pContact->pos);
+                    //create contact using Plane Normal
+                    dOPESIGN(pContact->normal, =, -, itTriangle->planeDef);
+
+                    pContact->depth = depth;
+
+                    numTerrainContacts++;
+                    if ( numTerrainContacts == numMaxContactsPossible ) 
+                        return numTerrainContacts;
+
+                    vertex->state = true;
+                }
+            }
+        }
+    }
+
+#ifdef _HEIGHTFIELDEDGECOLLIDING
+    // pass3: VS triangle Edges
+    if (needFurtherPasses)
+    {
+        dVector3 Edge;
+        dxRay edgeRay(0, 1);
+
+		int numMaxContactsPerTri = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
+		int triTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerTri;
+		dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
+
+        for (unsigned int k = 0; k < numTri; k++)
+        {
+            const HeightFieldTriangle * const itTriangle = &tempTriangleBuffer[k];
+
+            if (itTriangle->state == true)
+                continue;// plane did already collide.
+
+            for (size_t m = 0; m < 3; m++)
+            {
+                const size_t next = (m + 1) % 3;
+                HeightFieldVertex *vertex0 = itTriangle->vertices[m];
+                HeightFieldVertex *vertex1 = itTriangle->vertices[next];
+
+                // not concave or under the AABB 
+                // nor triangle already collided against vertices
+                if (vertex0->state == true && vertex1->state == true)
+                    continue;// plane did already collide.
+               
+                dVector3Subtract(vertex1->vertex, vertex0->vertex, Edge);
+                edgeRay.length = dVector3Length (Edge);
+                dGeomRaySetNoNormalize(edgeRay, vertex1->vertex, Edge);
+				int prevTerrainContacts = numTerrainContacts;
+				pContact = CONTACT(contact, prevTerrainContacts*skip);
+                const int numCollision = geomRayNCollider(&edgeRay,o2,triTestFlags,pContact,skip);
+				dIASSERT(numCollision <= numMaxContactsPerTri);
+				
+				if (numCollision)
+				{
+					numTerrainContacts += numCollision;
+
+					do
+					{
+						pContact = CONTACT(contact, prevTerrainContacts*skip);
+
+						//create contact using Plane Normal
+						dOPESIGN(pContact->normal, =, -, itTriangle->planeDef);
+
+						pContact->depth = DistancePointToLine(pContact->pos, vertex1->vertex, Edge, edgeRay.length);
+					}
+					while (++prevTerrainContacts != numTerrainContacts);
+
+					if ( numTerrainContacts == numMaxContactsPossible )
+						return numTerrainContacts;
+
+					numMaxContactsPerTri = dMIN(numMaxContactsPossible - numTerrainContacts, HEIGHTFIELDMAXCONTACTPERCELL);
+					triTestFlags = (flags & ~NUMC_MASK) | numMaxContactsPerTri;
+					dIASSERT((HEIGHTFIELDMAXCONTACTPERCELL & ~NUMC_MASK) == 0);
+				}
+            }
+
+            itTriangle->vertices[0]->state = true;
+            itTriangle->vertices[1]->state = true;
+            itTriangle->vertices[2]->state = true;
+        }
+    }
+#endif // _HEIGHTFIELDEDGECOLLIDING
+    return numTerrainContacts;
+}
+
+int dCollideHeightfield( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contact, int skip )
+{
+    dIASSERT( skip >= (int)sizeof(dContactGeom) );
+    dIASSERT( o1->type == dHeightfieldClass );
+	dIASSERT((flags & NUMC_MASK) >= 1);
+
+    int i;
+
+    // if ((flags & NUMC_MASK) == 0) -- An assertion check is made on entry
+	//	{ flags = (flags & ~NUMC_MASK) | 1; dIASSERT((1 & ~NUMC_MASK) == 0); }
+
+    int numMaxTerrainContacts = (flags & NUMC_MASK);
+
+    dxHeightfield *terrain = (dxHeightfield*) o1;
+
+    dVector3 posbak;
+    dMatrix3 Rbak;
+    dReal aabbbak[6];
+    int gflagsbak;
+    dVector3 pos0,pos1;
+    dMatrix3 R1;
+
+    int numTerrainContacts = 0;
+
+    //@@ Should find a way to set reComputeAABB to false in default case
+    // aka DHEIGHTFIELD_CORNER_ORIGIN not defined and terrain not PLACEABLE
+    // so that we can free some memory and speed up things a bit
+    // while saving some precision loss 
+#ifndef DHEIGHTFIELD_CORNER_ORIGIN
+    const bool reComputeAABB = true;
+#else
+    const bool reComputeAABB = ( terrain->gflags & GEOM_PLACEABLE ) ? true : false;
+#endif //DHEIGHTFIELD_CORNER_ORIGIN
+
+    //
+    // Transform O2 into Heightfield Space
+    //
+    if (reComputeAABB)
+    {
+        // Backup original o2 position, rotation and AABB.
+        dVector3Copy( o2->final_posr->pos, posbak );
+        dMatrix3Copy( o2->final_posr->R, Rbak );
+        memcpy( aabbbak, o2->aabb, sizeof( dReal ) * 6 );
+        gflagsbak = o2->gflags;
+    }
+
+    if ( terrain->gflags & GEOM_PLACEABLE )
+    {
+        // Transform o2 into heightfield space.
+        dOP( pos0, -, o2->final_posr->pos, terrain->final_posr->pos );
+        dMULTIPLY1_331( pos1, terrain->final_posr->R, pos0 );
+        dMULTIPLY1_333( R1, terrain->final_posr->R, o2->final_posr->R );
+
+        // Update o2 with transformed position and rotation.
+        dVector3Copy( pos1, o2->final_posr->pos );
+        dMatrix3Copy( R1, o2->final_posr->R );
+    }
+
+#ifndef DHEIGHTFIELD_CORNER_ORIGIN
+    o2->final_posr->pos[ 0 ] += terrain->m_p_data->m_fHalfWidth;
+    o2->final_posr->pos[ 2 ] += terrain->m_p_data->m_fHalfDepth;
+#endif // DHEIGHTFIELD_CORNER_ORIGIN
+
+    // Rebuild AABB for O2
+    if (reComputeAABB)
+        o2->computeAABB();
+
+    //
+    // Collide
+    //
+
+    //check if inside boundaries
+    // using O2 aabb
+    //  aabb[6] is (minx, maxx, miny, maxy, minz, maxz) 
+    const bool wrapped = terrain->m_p_data->m_bWrapMode != 0;
+
+    int nMinX;
+    int nMaxX;
+    int nMinZ;
+    int nMaxZ;
+
+    if ( !wrapped )
+    {
+        if (    o2->aabb[0] > terrain->m_p_data->m_fWidth //MinX
+            &&  o2->aabb[4] > terrain->m_p_data->m_fDepth)//MinZ
+            goto dCollideHeightfieldExit;
+
+        if (    o2->aabb[1] < 0 //MaxX
+            &&  o2->aabb[5] < 0) //MaxZ
+            goto dCollideHeightfieldExit;
+
+    }
+
+    nMinX = int(dFloor(o2->aabb[0] * terrain->m_p_data->m_fInvSampleWidth));
+    nMaxX = int(dFloor(o2->aabb[1] * terrain->m_p_data->m_fInvSampleWidth)) + 1;
+    nMinZ = int(dFloor(o2->aabb[4] * terrain->m_p_data->m_fInvSampleDepth));
+    nMaxZ = int(dFloor(o2->aabb[5] * terrain->m_p_data->m_fInvSampleDepth)) + 1;
+
+    if ( !wrapped )
+    {
+        nMinX = dMAX( nMinX, 0 );
+        nMaxX = dMIN( nMaxX, terrain->m_p_data->m_nWidthSamples - 1 );
+        nMinZ = dMAX( nMinZ, 0 );
+        nMaxZ = dMIN( nMaxZ, terrain->m_p_data->m_nDepthSamples - 1 );
+
+        dIASSERT ((nMinX < nMaxX) || (nMinZ < nMaxZ))		
+    }
+
+
+
+    numTerrainContacts  += terrain->dCollideHeightfieldZone(
+        nMinX,nMaxX,nMinZ,nMaxZ,o2,numMaxTerrainContacts - numTerrainContacts,
+        flags,CONTACT(contact,numTerrainContacts*skip),skip	);
+
+        dIASSERT( numTerrainContacts <= numMaxTerrainContacts );
+
+        dContactGeom *pContact;
+        for ( i = 0; i < numTerrainContacts; ++i )
+        {
+            pContact = CONTACT(contact,i*skip);
+            pContact->g1 = o1;
+            pContact->g2 = o2;
+        }
+
+
+        //------------------------------------------------------------------------------
+
+dCollideHeightfieldExit:
+
+        if (reComputeAABB)
+        {
+            // Restore o2 position, rotation and AABB
+            dVector3Copy( posbak, o2->final_posr->pos );
+            dMatrix3Copy( Rbak, o2->final_posr->R );
+            memcpy( o2->aabb, aabbbak, sizeof(dReal)*6 );
+            o2->gflags = gflagsbak;
+
+            //
+            // Transform Contacts to World Space
+            //
+            if ( terrain->gflags & GEOM_PLACEABLE )
+            {
+                for ( i = 0; i < numTerrainContacts; ++i )
+                {
+                    pContact = CONTACT(contact,i*skip);
+                    dOPE( pos0, =, pContact->pos );
+
+#ifndef DHEIGHTFIELD_CORNER_ORIGIN
+                    pos0[ 0 ] -= terrain->m_p_data->m_fHalfWidth;
+                    pos0[ 2 ] -= terrain->m_p_data->m_fHalfDepth;
+#endif // !DHEIGHTFIELD_CORNER_ORIGIN
+
+                    dMULTIPLY0_331( pContact->pos, terrain->final_posr->R, pos0 );
+
+                    dOP( pContact->pos, +, pContact->pos, terrain->final_posr->pos );
+                    dOPE( pos0, =, pContact->normal );
+
+                    dMULTIPLY0_331( pContact->normal, terrain->final_posr->R, pos0 );
+                }
+            }
+#ifndef DHEIGHTFIELD_CORNER_ORIGIN
+            else
+            {
+                for ( i = 0; i < numTerrainContacts; ++i )
+                {
+                    pContact = CONTACT(contact,i*skip);
+                    pContact->pos[ 0 ] -= terrain->m_p_data->m_fHalfWidth;
+                    pContact->pos[ 2 ] -= terrain->m_p_data->m_fHalfDepth;
+                }
+            }
+#endif // !DHEIGHTFIELD_CORNER_ORIGIN
+        }
+        // Return contact count.
+        return numTerrainContacts;
+}
+
+
Index: /code/branches/ode/ode-0.9/ode/src/heightfield.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/heightfield.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/heightfield.h	(revision 216)
@@ -0,0 +1,225 @@
+// dHeightfield Collider
+//  Martijn Buijs 2006 http://home.planet.nl/~buijs512/
+// Based on Terrain & Cone contrib by:
+//  Benoit CHAPEROT 2003-2004 http://www.jstarlab.com
+
+#ifndef _DHEIGHTFIELD_H_
+#define _DHEIGHTFIELD_H_
+//------------------------------------------------------------------------------
+
+#include <ode/common.h>
+#include "collision_kernel.h"
+
+
+#define HEIGHTFIELDMAXCONTACTPERCELL 10
+
+//
+// dxHeightfieldData
+//
+// Heightfield Data structure
+//
+struct dxHeightfieldData
+{
+    dReal m_fWidth;				// World space heightfield dimension on X axis
+    dReal m_fDepth;				// World space heightfield dimension on Z axis
+    dReal m_fSampleWidth;		// Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1))
+    dReal m_fSampleDepth;		// Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
+    dReal m_fInvSampleWidth;		// Cache of inverse Vertex count on X axis edge (== m_vWidth / (m_nWidthSamples-1))
+    dReal m_fInvSampleDepth;		// Cache of inverse Vertex count on Z axis edge (== m_vDepth / (m_nDepthSamples-1))
+
+    dReal m_fHalfWidth;			// Cache of half of m_fWidth
+    dReal m_fHalfDepth;			// Cache of half of m_fDepth
+
+    dReal m_fMinHeight;        // Min sample height value (scaled and offset)
+    dReal m_fMaxHeight;        // Max sample height value (scaled and offset)
+    dReal m_fThickness;        // Surface thickness (added to bottom AABB)
+    dReal m_fScale;            // Sample value multiplier
+    dReal m_fOffset;           // Vertical sample offset
+
+    int	m_nWidthSamples;       // Vertex count on X axis edge (number of samples)
+    int	m_nDepthSamples;       // Vertex count on Z axis edge (number of samples)
+    int m_bCopyHeightData;     // Do we own the sample data?
+    int	m_bWrapMode;           // Heightfield wrapping mode (0=finite, 1=infinite)
+    int m_nGetHeightMode;      // GetHeight mode ( 0=callback, 1=byte, 2=short, 3=float )
+
+    const void* m_pHeightData; // Sample data array
+    void* m_pUserData;         // Callback user data
+
+    dContactGeom            m_contacts[HEIGHTFIELDMAXCONTACTPERCELL];
+
+    dHeightfieldGetHeight* m_pGetHeightCallback;		// Callback pointer.
+
+    dxHeightfieldData();
+    ~dxHeightfieldData();
+
+    void SetData( int nWidthSamples, int nDepthSamples,
+        dReal fWidth, dReal fDepth,
+        dReal fScale, dReal fOffset,
+        dReal fThickness, int bWrapMode );
+
+    void ComputeHeightBounds();
+
+    bool IsOnHeightfield  ( const dReal * const CellOrigin, const dReal * const pos,  const bool isABC) const;
+    bool IsOnHeightfield2  ( const dReal * const CellOrigin, const dReal * const pos,  const bool isABC) const;
+
+    dReal GetHeight(int x, int z);
+    dReal GetHeight(dReal x, dReal z);
+
+};
+
+class HeightFieldVertex;
+class HeightFieldEdge;
+class HeightFieldTriangle;
+
+class HeightFieldVertex
+{
+public:
+    HeightFieldVertex(){};
+
+    dVector3 vertex;
+    bool state;
+};
+
+class HeightFieldEdge
+{
+public:
+    HeightFieldEdge(){};
+
+    HeightFieldVertex   *vertices[2];
+};
+//
+// HeightFieldTriangle
+//
+// HeightFieldTriangle composing heightfield mesh
+//
+class HeightFieldTriangle
+{
+public:
+    HeightFieldTriangle(){};
+
+    inline void setMinMax()
+    {
+        maxAAAB = vertices[0]->vertex[1] > vertices[1]->vertex[1] ? vertices[0]->vertex[1] : vertices[1]->vertex[1];
+        maxAAAB = vertices[2]->vertex[1] > maxAAAB  ? vertices[2]->vertex[1] : maxAAAB;
+    };
+
+    HeightFieldVertex   *vertices[3];
+    dReal               planeDef[4];
+    dReal               maxAAAB;
+
+    bool                isUp;
+    bool                state;
+};
+//
+// HeightFieldTriangle
+//
+// HeightFieldPlane composing heightfield mesh
+//
+class HeightFieldPlane
+{
+public:
+    HeightFieldPlane():
+      trianglelist(0),
+      trianglelistReservedSize(0),
+      trianglelistCurrentSize(0)
+    {
+
+    };
+    ~HeightFieldPlane()
+    {
+        delete [] trianglelist;
+    };
+
+    inline void setMinMax()
+    {
+        const size_t asize = trianglelistCurrentSize;
+        if (asize > 0)
+        {  
+            maxAAAB = trianglelist[0]->maxAAAB;
+            for (size_t k = 1; asize > k; k++)
+            {   
+                if (trianglelist[k]->maxAAAB >  maxAAAB)
+                    maxAAAB = trianglelist[k]->maxAAAB;
+            }
+        }
+    };
+
+    void resetTriangleListSize(const size_t newSize)
+    {
+        if (trianglelistReservedSize < newSize)
+        {
+            delete [] trianglelist;
+            trianglelistReservedSize = newSize;
+            trianglelist = new HeightFieldTriangle *[newSize];
+        }
+        trianglelistCurrentSize = 0;
+    }
+
+    void addTriangle(HeightFieldTriangle *tri)
+    {
+		dIASSERT(trianglelistCurrentSize < trianglelistReservedSize);
+
+        trianglelist[trianglelistCurrentSize++] = tri;
+    }
+
+    HeightFieldTriangle **trianglelist;
+    size_t              trianglelistReservedSize;
+    size_t              trianglelistCurrentSize;
+
+    dReal   maxAAAB;
+    dReal   planeDef[4];
+};
+//
+// dxHeightfield
+//
+// Heightfield geom structure
+//
+struct dxHeightfield : public dxGeom
+{
+    dxHeightfieldData* m_p_data;
+
+    dxHeightfield( dSpaceID space, dHeightfieldDataID data, int bPlaceable );
+    ~dxHeightfield();
+
+    void computeAABB();
+
+    int dCollideHeightfieldZone( const int minX, const int maxX, const int minZ, const int maxZ,  
+        dxGeom *o2, const int numMaxContacts,
+        int flags, dContactGeom *contact, int skip );
+
+	enum
+	{
+		TEMP_PLANE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 4,
+		TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_X = 4,
+		TEMP_HEIGHT_BUFFER_ELEMENT_COUNT_ALIGNMENT_Z = 4,
+		TEMP_TRIANGLE_BUFFER_ELEMENT_COUNT_ALIGNMENT = 1, // Triangles are easy to reallocate and hard to predict
+	};
+
+	static inline size_t AlignBufferSize(size_t value, size_t alignment) { dIASSERT((alignment & (alignment - 1)) == 0); return (value + (alignment - 1)) & ~(alignment - 1); }
+
+	void  allocateTriangleBuffer(size_t numTri);
+	void  resetTriangleBuffer();
+	void  allocatePlaneBuffer(size_t numTri);
+	void  resetPlaneBuffer();
+	void  allocateHeightBuffer(size_t numX, size_t numZ);
+    void  resetHeightBuffer();
+
+    void  sortPlanes(const size_t numPlanes);
+
+    HeightFieldPlane    **tempPlaneBuffer;
+    HeightFieldPlane    *tempPlaneInstances;
+    size_t              tempPlaneBufferSize;
+
+    HeightFieldTriangle *tempTriangleBuffer;
+    size_t              tempTriangleBufferSize;
+
+    HeightFieldVertex   **tempHeightBuffer;
+	HeightFieldVertex   *tempHeightInstances;
+    size_t              tempHeightBufferSizeX;
+    size_t              tempHeightBufferSizeZ;
+
+};
+
+
+//------------------------------------------------------------------------------
+#endif //_DHEIGHTFIELD_H_
Index: /code/branches/ode/ode-0.9/ode/src/joint.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/joint.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/joint.cpp	(revision 216)
@@ -0,0 +1,4065 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+design note: the general principle for giving a joint the option of connecting
+to the static environment (i.e. the absolute frame) is to check the second
+body (joint->node[1].body), and if it is zero then behave as if its body
+transform is the identity.
+
+*/
+
+#include <ode/ode.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/matrix.h>
+#include "joint.h"
+
+//****************************************************************************
+// externs
+
+// extern "C" void dBodyAddTorque (dBodyID, dReal fx, dReal fy, dReal fz);
+// extern "C" void dBodyAddForce (dBodyID, dReal fx, dReal fy, dReal fz);
+
+//****************************************************************************
+// utility
+
+// set three "ball-and-socket" rows in the constraint equation, and the
+// corresponding right hand side.
+
+static inline void setBall (dxJoint *joint, dxJoint::Info2 *info,
+			    dVector3 anchor1, dVector3 anchor2)
+{
+  // anchor points in global coordinates with respect to body PORs.
+  dVector3 a1,a2;
+
+  int s = info->rowskip;
+
+  // set jacobian
+  info->J1l[0] = 1;
+  info->J1l[s+1] = 1;
+  info->J1l[2*s+2] = 1;
+  dMULTIPLY0_331 (a1,joint->node[0].body->posr.R,anchor1);
+  dCROSSMAT (info->J1a,a1,s,-,+);
+  if (joint->node[1].body) {
+    info->J2l[0] = -1;
+    info->J2l[s+1] = -1;
+    info->J2l[2*s+2] = -1;
+    dMULTIPLY0_331 (a2,joint->node[1].body->posr.R,anchor2);
+    dCROSSMAT (info->J2a,a2,s,+,-);
+  }
+
+  // set right hand side
+  dReal k = info->fps * info->erp;
+  if (joint->node[1].body) {
+    for (int j=0; j<3; j++) {
+      info->c[j] = k * (a2[j] + joint->node[1].body->posr.pos[j] -
+			a1[j] - joint->node[0].body->posr.pos[j]);
+    }
+  }
+  else {
+    for (int j=0; j<3; j++) {
+      info->c[j] = k * (anchor2[j] - a1[j] -
+			joint->node[0].body->posr.pos[j]);
+    }
+  }
+}
+
+
+// this is like setBall(), except that `axis' is a unit length vector
+// (in global coordinates) that should be used for the first jacobian
+// position row (the other two row vectors will be derived from this).
+// `erp1' is the erp value to use along the axis.
+
+static inline void setBall2 (dxJoint *joint, dxJoint::Info2 *info,
+			    dVector3 anchor1, dVector3 anchor2,
+			    dVector3 axis, dReal erp1)
+{
+  // anchor points in global coordinates with respect to body PORs.
+  dVector3 a1,a2;
+
+  int i,s = info->rowskip;
+
+  // get vectors normal to the axis. in setBall() axis,q1,q2 is [1 0 0],
+  // [0 1 0] and [0 0 1], which makes everything much easier.
+  dVector3 q1,q2;
+  dPlaneSpace (axis,q1,q2);
+
+  // set jacobian
+  for (i=0; i<3; i++) info->J1l[i] = axis[i];
+  for (i=0; i<3; i++) info->J1l[s+i] = q1[i];
+  for (i=0; i<3; i++) info->J1l[2*s+i] = q2[i];
+  dMULTIPLY0_331 (a1,joint->node[0].body->posr.R,anchor1);
+  dCROSS (info->J1a,=,a1,axis);
+  dCROSS (info->J1a+s,=,a1,q1);
+  dCROSS (info->J1a+2*s,=,a1,q2);
+  if (joint->node[1].body) {
+    for (i=0; i<3; i++) info->J2l[i] = -axis[i];
+    for (i=0; i<3; i++) info->J2l[s+i] = -q1[i];
+    for (i=0; i<3; i++) info->J2l[2*s+i] = -q2[i];
+    dMULTIPLY0_331 (a2,joint->node[1].body->posr.R,anchor2);
+    dCROSS (info->J2a,= -,a2,axis);
+    dCROSS (info->J2a+s,= -,a2,q1);
+    dCROSS (info->J2a+2*s,= -,a2,q2);
+  }
+
+  // set right hand side - measure error along (axis,q1,q2)
+  dReal k1 = info->fps * erp1;
+  dReal k = info->fps * info->erp;
+
+  for (i=0; i<3; i++) a1[i] += joint->node[0].body->posr.pos[i];
+  if (joint->node[1].body) {
+    for (i=0; i<3; i++) a2[i] += joint->node[1].body->posr.pos[i];
+    info->c[0] = k1 * (dDOT(axis,a2) - dDOT(axis,a1));
+    info->c[1] = k * (dDOT(q1,a2) - dDOT(q1,a1));
+    info->c[2] = k * (dDOT(q2,a2) - dDOT(q2,a1));
+  }
+  else {
+    info->c[0] = k1 * (dDOT(axis,anchor2) - dDOT(axis,a1));
+    info->c[1] = k * (dDOT(q1,anchor2) - dDOT(q1,a1));
+    info->c[2] = k * (dDOT(q2,anchor2) - dDOT(q2,a1));
+  }
+}
+
+
+// set three orientation rows in the constraint equation, and the
+// corresponding right hand side.
+
+static void setFixedOrientation(dxJoint *joint, dxJoint::Info2 *info, dQuaternion qrel, int start_row)
+{
+  int s = info->rowskip;
+  int start_index = start_row * s;
+
+  // 3 rows to make body rotations equal
+  info->J1a[start_index] = 1;
+  info->J1a[start_index + s + 1] = 1;
+  info->J1a[start_index + s*2+2] = 1;
+  if (joint->node[1].body) {
+    info->J2a[start_index] = -1;
+    info->J2a[start_index + s+1] = -1;
+    info->J2a[start_index + s*2+2] = -1;
+  }
+
+  // compute the right hand side. the first three elements will result in
+  // relative angular velocity of the two bodies - this is set to bring them
+  // back into alignment. the correcting angular velocity is
+  //   |angular_velocity| = angle/time = erp*theta / stepsize
+  //                      = (erp*fps) * theta
+  //    angular_velocity  = |angular_velocity| * u
+  //                      = (erp*fps) * theta * u
+  // where rotation along unit length axis u by theta brings body 2's frame
+  // to qrel with respect to body 1's frame. using a small angle approximation
+  // for sin(), this gives
+  //    angular_velocity  = (erp*fps) * 2 * v
+  // where the quaternion of the relative rotation between the two bodies is
+  //    q = [cos(theta/2) sin(theta/2)*u] = [s v]
+
+  // get qerr = relative rotation (rotation error) between two bodies
+  dQuaternion qerr,e;
+  if (joint->node[1].body) {
+    dQuaternion qq;
+    dQMultiply1 (qq,joint->node[0].body->q,joint->node[1].body->q);
+    dQMultiply2 (qerr,qq,qrel);
+  }
+  else {
+    dQMultiply3 (qerr,joint->node[0].body->q,qrel);
+  }
+  if (qerr[0] < 0) {
+    qerr[1] = -qerr[1];		// adjust sign of qerr to make theta small
+    qerr[2] = -qerr[2];
+    qerr[3] = -qerr[3];
+  }
+  dMULTIPLY0_331 (e,joint->node[0].body->posr.R,qerr+1); // @@@ bad SIMD padding!
+  dReal k = info->fps * info->erp;
+  info->c[start_row] = 2*k * e[0];
+  info->c[start_row+1] = 2*k * e[1];
+  info->c[start_row+2] = 2*k * e[2];
+}
+
+
+// compute anchor points relative to bodies
+
+static void setAnchors (dxJoint *j, dReal x, dReal y, dReal z,
+			dVector3 anchor1, dVector3 anchor2)
+{
+  if (j->node[0].body) {
+    dReal q[4];
+    q[0] = x - j->node[0].body->posr.pos[0];
+    q[1] = y - j->node[0].body->posr.pos[1];
+    q[2] = z - j->node[0].body->posr.pos[2];
+    q[3] = 0;
+    dMULTIPLY1_331 (anchor1,j->node[0].body->posr.R,q);
+    if (j->node[1].body) {
+      q[0] = x - j->node[1].body->posr.pos[0];
+      q[1] = y - j->node[1].body->posr.pos[1];
+      q[2] = z - j->node[1].body->posr.pos[2];
+      q[3] = 0;
+      dMULTIPLY1_331 (anchor2,j->node[1].body->posr.R,q);
+    }
+    else {
+      anchor2[0] = x;
+      anchor2[1] = y;
+      anchor2[2] = z;
+    }
+  }
+  anchor1[3] = 0;
+  anchor2[3] = 0;
+}
+
+
+// compute axes relative to bodies. either axis1 or axis2 can be 0.
+
+static void setAxes (dxJoint *j, dReal x, dReal y, dReal z,
+		     dVector3 axis1, dVector3 axis2)
+{
+  if (j->node[0].body) {
+    dReal q[4];
+    q[0] = x;
+    q[1] = y;
+    q[2] = z;
+    q[3] = 0;
+    dNormalize3 (q);
+    if (axis1) {
+      dMULTIPLY1_331 (axis1,j->node[0].body->posr.R,q);
+      axis1[3] = 0;
+    }
+    if (axis2) {
+      if (j->node[1].body) {
+	dMULTIPLY1_331 (axis2,j->node[1].body->posr.R,q);
+      }
+      else {
+	axis2[0] = x;
+	axis2[1] = y;
+	axis2[2] = z;
+      }
+      axis2[3] = 0;
+    }
+  }
+}
+
+
+static void getAnchor (dxJoint *j, dVector3 result, dVector3 anchor1)
+{
+  if (j->node[0].body) {
+    dMULTIPLY0_331 (result,j->node[0].body->posr.R,anchor1);
+    result[0] += j->node[0].body->posr.pos[0];
+    result[1] += j->node[0].body->posr.pos[1];
+    result[2] += j->node[0].body->posr.pos[2];
+  }
+}
+
+
+static void getAnchor2 (dxJoint *j, dVector3 result, dVector3 anchor2)
+{
+  if (j->node[1].body) {
+    dMULTIPLY0_331 (result,j->node[1].body->posr.R,anchor2);
+    result[0] += j->node[1].body->posr.pos[0];
+    result[1] += j->node[1].body->posr.pos[1];
+    result[2] += j->node[1].body->posr.pos[2];
+  }
+  else {
+    result[0] = anchor2[0];
+    result[1] = anchor2[1];
+    result[2] = anchor2[2];
+  }
+}
+
+
+static void getAxis (dxJoint *j, dVector3 result, dVector3 axis1)
+{
+  if (j->node[0].body) {
+    dMULTIPLY0_331 (result,j->node[0].body->posr.R,axis1);
+  }
+}
+
+
+static void getAxis2 (dxJoint *j, dVector3 result, dVector3 axis2)
+{
+  if (j->node[1].body) {
+    dMULTIPLY0_331 (result,j->node[1].body->posr.R,axis2);
+  }
+  else {
+    result[0] = axis2[0];
+    result[1] = axis2[1];
+    result[2] = axis2[2];
+  }
+}
+
+
+static dReal getHingeAngleFromRelativeQuat (dQuaternion qrel, dVector3 axis)
+{
+  // the angle between the two bodies is extracted from the quaternion that
+  // represents the relative rotation between them. recall that a quaternion
+  // q is:
+  //    [s,v] = [ cos(theta/2) , sin(theta/2) * u ]
+  // where s is a scalar and v is a 3-vector. u is a unit length axis and
+  // theta is a rotation along that axis. we can get theta/2 by:
+  //    theta/2 = atan2 ( sin(theta/2) , cos(theta/2) )
+  // but we can't get sin(theta/2) directly, only its absolute value, i.e.:
+  //    |v| = |sin(theta/2)| * |u|
+  //        = |sin(theta/2)|
+  // using this value will have a strange effect. recall that there are two
+  // quaternion representations of a given rotation, q and -q. typically as
+  // a body rotates along the axis it will go through a complete cycle using
+  // one representation and then the next cycle will use the other
+  // representation. this corresponds to u pointing in the direction of the
+  // hinge axis and then in the opposite direction. the result is that theta
+  // will appear to go "backwards" every other cycle. here is a fix: if u
+  // points "away" from the direction of the hinge (motor) axis (i.e. more
+  // than 90 degrees) then use -q instead of q. this represents the same
+  // rotation, but results in the cos(theta/2) value being sign inverted.
+
+  // extract the angle from the quaternion. cost2 = cos(theta/2),
+  // sint2 = |sin(theta/2)|
+  dReal cost2 = qrel[0];
+  dReal sint2 = dSqrt (qrel[1]*qrel[1]+qrel[2]*qrel[2]+qrel[3]*qrel[3]);
+  dReal theta = (dDOT(qrel+1,axis) >= 0) ?	// @@@ padding assumptions
+    (2 * dAtan2(sint2,cost2)) :		// if u points in direction of axis
+    (2 * dAtan2(sint2,-cost2));		// if u points in opposite direction
+
+  // the angle we get will be between 0..2*pi, but we want to return angles
+  // between -pi..pi
+  if (theta > M_PI) theta -= 2*M_PI;
+
+  // the angle we've just extracted has the wrong sign
+  theta = -theta;
+
+  return theta;
+}
+
+
+// given two bodies (body1,body2), the hinge axis that they are connected by
+// w.r.t. body1 (axis), and the initial relative orientation between them
+// (q_initial), return the relative rotation angle. the initial relative
+// orientation corresponds to an angle of zero. if body2 is 0 then measure the
+// angle between body1 and the static frame.
+//
+// this will not return the correct angle if the bodies rotate along any axis
+// other than the given hinge axis.
+
+static dReal getHingeAngle (dxBody *body1, dxBody *body2, dVector3 axis,
+			    dQuaternion q_initial)
+{
+  // get qrel = relative rotation between the two bodies
+  dQuaternion qrel;
+  if (body2) {
+    dQuaternion qq;
+    dQMultiply1 (qq,body1->q,body2->q);
+    dQMultiply2 (qrel,qq,q_initial);
+  }
+  else {
+    // pretend body2->q is the identity
+    dQMultiply3 (qrel,body1->q,q_initial);
+  }
+
+  return getHingeAngleFromRelativeQuat (qrel,axis);
+}
+
+//****************************************************************************
+// dxJointLimitMotor
+
+void dxJointLimitMotor::init (dxWorld *world)
+{
+  vel = 0;
+  fmax = 0;
+  lostop = -dInfinity;
+  histop = dInfinity;
+  fudge_factor = 1;
+  normal_cfm = world->global_cfm;
+  stop_erp = world->global_erp;
+  stop_cfm = world->global_cfm;
+  bounce = 0;
+  limit = 0;
+  limit_err = 0;
+}
+
+
+void dxJointLimitMotor::set (int num, dReal value)
+{
+  switch (num) {
+  case dParamLoStop:
+    lostop = value;
+    break;
+  case dParamHiStop:
+    histop = value;
+    break;
+  case dParamVel:
+    vel = value;
+    break;
+  case dParamFMax:
+    if (value >= 0) fmax = value;
+    break;
+  case dParamFudgeFactor:
+    if (value >= 0 && value <= 1) fudge_factor = value;
+    break;
+  case dParamBounce:
+    bounce = value;
+    break;
+  case dParamCFM:
+    normal_cfm = value;
+    break;
+  case dParamStopERP:
+    stop_erp = value;
+    break;
+  case dParamStopCFM:
+    stop_cfm = value;
+    break;
+  }
+}
+
+
+dReal dxJointLimitMotor::get (int num)
+{
+  switch (num) {
+  case dParamLoStop: return lostop;
+  case dParamHiStop: return histop;
+  case dParamVel: return vel;
+  case dParamFMax: return fmax;
+  case dParamFudgeFactor: return fudge_factor;
+  case dParamBounce: return bounce;
+  case dParamCFM: return normal_cfm;
+  case dParamStopERP: return stop_erp;
+  case dParamStopCFM: return stop_cfm;
+  default: return 0;
+  }
+}
+
+
+int dxJointLimitMotor::testRotationalLimit (dReal angle)
+{
+  if (angle <= lostop) {
+    limit = 1;
+    limit_err = angle - lostop;
+    return 1;
+  }
+  else if (angle >= histop) {
+    limit = 2;
+    limit_err = angle - histop;
+    return 1;
+  }
+  else {
+    limit = 0;
+    return 0;
+  }
+}
+
+
+int dxJointLimitMotor::addLimot (dxJoint *joint,
+				 dxJoint::Info2 *info, int row,
+				 dVector3 ax1, int rotational)
+{
+  int srow = row * info->rowskip;
+
+  // if the joint is powered, or has joint limits, add in the extra row
+  int powered = fmax > 0;
+  if (powered || limit) {
+    dReal *J1 = rotational ? info->J1a : info->J1l;
+    dReal *J2 = rotational ? info->J2a : info->J2l;
+
+    J1[srow+0] = ax1[0];
+    J1[srow+1] = ax1[1];
+    J1[srow+2] = ax1[2];
+    if (joint->node[1].body) {
+      J2[srow+0] = -ax1[0];
+      J2[srow+1] = -ax1[1];
+      J2[srow+2] = -ax1[2];
+    }
+
+    // linear limot torque decoupling step:
+    //
+    // if this is a linear limot (e.g. from a slider), we have to be careful
+    // that the linear constraint forces (+/- ax1) applied to the two bodies
+    // do not create a torque couple. in other words, the points that the
+    // constraint force is applied at must lie along the same ax1 axis.
+    // a torque couple will result in powered or limited slider-jointed free
+    // bodies from gaining angular momentum.
+    // the solution used here is to apply the constraint forces at the point
+    // halfway between the body centers. there is no penalty (other than an
+    // extra tiny bit of computation) in doing this adjustment. note that we
+    // only need to do this if the constraint connects two bodies.
+
+    dVector3 ltd;	// Linear Torque Decoupling vector (a torque)
+    if (!rotational && joint->node[1].body) {
+      dVector3 c;
+      c[0]=REAL(0.5)*(joint->node[1].body->posr.pos[0]-joint->node[0].body->posr.pos[0]);
+      c[1]=REAL(0.5)*(joint->node[1].body->posr.pos[1]-joint->node[0].body->posr.pos[1]);
+      c[2]=REAL(0.5)*(joint->node[1].body->posr.pos[2]-joint->node[0].body->posr.pos[2]);
+      dCROSS (ltd,=,c,ax1);
+      info->J1a[srow+0] = ltd[0];
+      info->J1a[srow+1] = ltd[1];
+      info->J1a[srow+2] = ltd[2];
+      info->J2a[srow+0] = ltd[0];
+      info->J2a[srow+1] = ltd[1];
+      info->J2a[srow+2] = ltd[2];
+    }
+
+    // if we're limited low and high simultaneously, the joint motor is
+    // ineffective
+    if (limit && (lostop == histop)) powered = 0;
+
+    if (powered) {
+      info->cfm[row] = normal_cfm;
+      if (! limit) {
+	info->c[row] = vel;
+	info->lo[row] = -fmax;
+	info->hi[row] = fmax;
+      }
+      else {
+	// the joint is at a limit, AND is being powered. if the joint is
+	// being powered into the limit then we apply the maximum motor force
+	// in that direction, because the motor is working against the
+	// immovable limit. if the joint is being powered away from the limit
+	// then we have problems because actually we need *two* lcp
+	// constraints to handle this case. so we fake it and apply some
+	// fraction of the maximum force. the fraction to use can be set as
+	// a fudge factor.
+
+	dReal fm = fmax;
+	if ((vel > 0) || (vel==0 && limit==2)) fm = -fm;
+
+	// if we're powering away from the limit, apply the fudge factor
+	if ((limit==1 && vel > 0) || (limit==2 && vel < 0)) fm *= fudge_factor;
+
+	if (rotational) {
+	  dBodyAddTorque (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],
+			  -fm*ax1[2]);
+	  if (joint->node[1].body)
+	    dBodyAddTorque (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]);
+	}
+	else {
+	  dBodyAddForce (joint->node[0].body,-fm*ax1[0],-fm*ax1[1],-fm*ax1[2]);
+	  if (joint->node[1].body) {
+	    dBodyAddForce (joint->node[1].body,fm*ax1[0],fm*ax1[1],fm*ax1[2]);
+
+	    // linear limot torque decoupling step: refer to above discussion
+	    dBodyAddTorque (joint->node[0].body,-fm*ltd[0],-fm*ltd[1],
+			    -fm*ltd[2]);
+	    dBodyAddTorque (joint->node[1].body,-fm*ltd[0],-fm*ltd[1],
+			    -fm*ltd[2]);
+	  }
+	}
+      }
+    }
+
+    if (limit) {
+      dReal k = info->fps * stop_erp;
+      info->c[row] = -k * limit_err;
+      info->cfm[row] = stop_cfm;
+
+      if (lostop == histop) {
+	// limited low and high simultaneously
+	info->lo[row] = -dInfinity;
+	info->hi[row] = dInfinity;
+      }
+      else {
+	if (limit == 1) {
+	  // low limit
+	  info->lo[row] = 0;
+	  info->hi[row] = dInfinity;
+	}
+	else {
+	  // high limit
+	  info->lo[row] = -dInfinity;
+	  info->hi[row] = 0;
+	}
+
+	// deal with bounce
+	if (bounce > 0) {
+	  // calculate joint velocity
+	  dReal vel;
+	  if (rotational) {
+	    vel = dDOT(joint->node[0].body->avel,ax1);
+	    if (joint->node[1].body)
+	      vel -= dDOT(joint->node[1].body->avel,ax1);
+	  }
+	  else {
+	    vel = dDOT(joint->node[0].body->lvel,ax1);
+	    if (joint->node[1].body)
+	      vel -= dDOT(joint->node[1].body->lvel,ax1);
+	  }
+
+	  // only apply bounce if the velocity is incoming, and if the
+	  // resulting c[] exceeds what we already have.
+	  if (limit == 1) {
+	    // low limit
+	    if (vel < 0) {
+	      dReal newc = -bounce * vel;
+	      if (newc > info->c[row]) info->c[row] = newc;
+	    }
+	  }
+	  else {
+	    // high limit - all those computations are reversed
+	    if (vel > 0) {
+	      dReal newc = -bounce * vel;
+	      if (newc < info->c[row]) info->c[row] = newc;
+	    }
+	  }
+	}
+      }
+    }
+    return 1;
+  }
+  else return 0;
+}
+
+//****************************************************************************
+// ball and socket
+
+static void ballInit (dxJointBall *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  j->erp = j->world->global_erp;
+  j->cfm = j->world->global_cfm;
+}
+
+
+static void ballGetInfo1 (dxJointBall *j, dxJoint::Info1 *info)
+{
+  info->m = 3;
+  info->nub = 3;
+}
+
+
+static void ballGetInfo2 (dxJointBall *joint, dxJoint::Info2 *info)
+{
+  info->erp = joint->erp;
+  info->cfm[0] = joint->cfm;
+  info->cfm[1] = joint->cfm;
+  info->cfm[2] = joint->cfm;
+  setBall (joint,info,joint->anchor1,joint->anchor2);
+}
+
+
+void dJointSetBallAnchor (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointBall* joint = (dxJointBall*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+}
+
+
+void dJointSetBallAnchor2 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointBall* joint = (dxJointBall*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  joint->anchor2[0] = x;
+  joint->anchor2[1] = y;
+  joint->anchor2[2] = z;
+  joint->anchor2[3] = 0;
+
+}
+
+void dJointGetBallAnchor (dJointID j, dVector3 result)
+{
+  dxJointBall* joint = (dxJointBall*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+void dJointGetBallAnchor2 (dJointID j, dVector3 result)
+{
+  dxJointBall* joint = (dxJointBall*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+void dxJointBall::set (int num, dReal value)
+{
+  switch (num) {
+  case dParamCFM:
+    cfm = value;
+    break;
+  case dParamERP:
+    erp = value;
+    break;
+  }
+}
+ 
+
+dReal dxJointBall::get (int num)
+{
+  switch (num) {
+  case dParamCFM:
+    return cfm;
+  case dParamERP:
+    return erp;
+  default:
+	return 0;
+  }
+}
+
+
+void dJointSetBallParam (dJointID j, int parameter, dReal value)
+{
+  dxJointBall* joint = (dxJointBall*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball joint");
+  joint->set (parameter,value);
+}
+
+
+dReal dJointGetBallParam (dJointID j, int parameter)
+{
+  dxJointBall* joint = (dxJointBall*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dball_vtable,"joint is not a ball joint");
+  return joint->get (parameter);
+}
+
+
+dxJoint::Vtable __dball_vtable = {
+  sizeof(dxJointBall),
+  (dxJoint::init_fn*) ballInit,
+  (dxJoint::getInfo1_fn*) ballGetInfo1,
+  (dxJoint::getInfo2_fn*) ballGetInfo2,
+  dJointTypeBall};
+
+//****************************************************************************
+// hinge
+
+static void hingeInit (dxJointHinge *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->axis2,4);
+  j->axis2[0] = 1;
+  dSetZero (j->qrel,4);
+  j->limot.init (j->world);
+}
+
+
+static void hingeGetInfo1 (dxJointHinge *j, dxJoint::Info1 *info)
+{
+  info->nub = 5;
+
+  // see if joint is powered
+  if (j->limot.fmax > 0)
+    info->m = 6;	// powered hinge needs an extra constraint row
+  else info->m = 5;
+
+  // see if we're at a joint limit.
+  if ((j->limot.lostop >= -M_PI || j->limot.histop <= M_PI) &&
+       j->limot.lostop <= j->limot.histop) {
+    dReal angle = getHingeAngle (j->node[0].body,j->node[1].body,j->axis1,
+				 j->qrel);
+    if (j->limot.testRotationalLimit (angle)) info->m = 6;
+  }
+}
+
+
+static void hingeGetInfo2 (dxJointHinge *joint, dxJoint::Info2 *info)
+{
+  // set the three ball-and-socket rows
+  setBall (joint,info,joint->anchor1,joint->anchor2);
+
+  // set the two hinge rows. the hinge axis should be the only unconstrained
+  // rotational axis, the angular velocity of the two bodies perpendicular to
+  // the hinge axis should be equal. thus the constraint equations are
+  //    p*w1 - p*w2 = 0
+  //    q*w1 - q*w2 = 0
+  // where p and q are unit vectors normal to the hinge axis, and w1 and w2
+  // are the angular velocity vectors of the two bodies.
+
+  dVector3 ax1;  // length 1 joint axis in global coordinates, from 1st body
+  dVector3 p,q;  // plane space vectors for ax1
+  dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
+  dPlaneSpace (ax1,p,q);
+
+  int s3=3*info->rowskip;
+  int s4=4*info->rowskip;
+
+  info->J1a[s3+0] = p[0];
+  info->J1a[s3+1] = p[1];
+  info->J1a[s3+2] = p[2];
+  info->J1a[s4+0] = q[0];
+  info->J1a[s4+1] = q[1];
+  info->J1a[s4+2] = q[2];
+
+  if (joint->node[1].body) {
+    info->J2a[s3+0] = -p[0];
+    info->J2a[s3+1] = -p[1];
+    info->J2a[s3+2] = -p[2];
+    info->J2a[s4+0] = -q[0];
+    info->J2a[s4+1] = -q[1];
+    info->J2a[s4+2] = -q[2];
+  }
+
+  // compute the right hand side of the constraint equation. set relative
+  // body velocities along p and q to bring the hinge back into alignment.
+  // if ax1,ax2 are the unit length hinge axes as computed from body1 and
+  // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
+  // if `theta' is the angle between ax1 and ax2, we need an angular velocity
+  // along u to cover angle erp*theta in one step :
+  //   |angular_velocity| = angle/time = erp*theta / stepsize
+  //                      = (erp*fps) * theta
+  //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+  //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+  // ...as ax1 and ax2 are unit length. if theta is smallish,
+  // theta ~= sin(theta), so
+  //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+  // ax1 x ax2 is in the plane space of ax1, so we project the angular
+  // velocity to p and q to find the right hand side.
+
+  dVector3 ax2,b;
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2);
+  }
+  else {
+    ax2[0] = joint->axis2[0];
+    ax2[1] = joint->axis2[1];
+    ax2[2] = joint->axis2[2];
+  }
+  dCROSS (b,=,ax1,ax2);
+  dReal k = info->fps * info->erp;
+  info->c[3] = k * dDOT(b,p);
+  info->c[4] = k * dDOT(b,q);
+
+  // if the hinge is powered, or has joint limits, add in the stuff
+  joint->limot.addLimot (joint,info,5,ax1,1);
+}
+
+
+// compute initial relative rotation body1 -> body2, or env -> body1
+
+static void hingeComputeInitialRelativeRotation (dxJointHinge *joint)
+{
+  if (joint->node[0].body) {
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+    }
+    else {
+      // set joint->qrel to the transpose of the first body q
+      joint->qrel[0] = joint->node[0].body->q[0];
+      for (int i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+    }
+  }
+}
+
+
+void dJointSetHingeAnchor (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+  hingeComputeInitialRelativeRotation (joint);
+}
+
+
+void dJointSetHingeAnchorDelta (dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+
+  if (joint->node[0].body) {
+    dReal q[4];
+    q[0] = x - joint->node[0].body->posr.pos[0];
+    q[1] = y - joint->node[0].body->posr.pos[1];
+    q[2] = z - joint->node[0].body->posr.pos[2];
+    q[3] = 0;
+    dMULTIPLY1_331 (joint->anchor1,joint->node[0].body->posr.R,q);
+
+    if (joint->node[1].body) {
+      q[0] = x - joint->node[1].body->posr.pos[0];
+      q[1] = y - joint->node[1].body->posr.pos[1];
+      q[2] = z - joint->node[1].body->posr.pos[2];
+      q[3] = 0;
+      dMULTIPLY1_331 (joint->anchor2,joint->node[1].body->posr.R,q);
+    }
+    else {
+      // Move the relative displacement between the passive body and the
+      //  anchor in the same direction as the passive body has just moved
+      joint->anchor2[0] = x + dx;
+      joint->anchor2[1] = y + dy;
+      joint->anchor2[2] = z + dz;
+    }
+  }
+  joint->anchor1[3] = 0;
+  joint->anchor2[3] = 0;
+
+  hingeComputeInitialRelativeRotation (joint);
+}
+
+
+
+void dJointSetHingeAxis (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  setAxes (joint,x,y,z,joint->axis1,joint->axis2);
+  hingeComputeInitialRelativeRotation (joint);
+}
+
+
+void dJointGetHingeAnchor (dJointID j, dVector3 result)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+void dJointGetHingeAnchor2 (dJointID j, dVector3 result)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+void dJointGetHingeAxis (dJointID j, dVector3 result)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  getAxis (joint,result,joint->axis1);
+}
+
+
+void dJointSetHingeParam (dJointID j, int parameter, dReal value)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  joint->limot.set (parameter,value);
+}
+
+
+dReal dJointGetHingeParam (dJointID j, int parameter)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  return joint->limot.get (parameter);
+}
+
+
+dReal dJointGetHingeAngle (dJointID j)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a hinge");
+  if (joint->node[0].body) {
+    dReal ang = getHingeAngle (joint->node[0].body,joint->node[1].body,joint->axis1,
+			  joint->qrel);
+	if (joint->flags & dJOINT_REVERSE)
+	   return -ang;
+	else
+	   return ang;
+  }
+  else return 0;
+}
+
+
+dReal dJointGetHingeAngleRate (dJointID j)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge");
+  if (joint->node[0].body) {
+    dVector3 axis;
+    dMULTIPLY0_331 (axis,joint->node[0].body->posr.R,joint->axis1);
+    dReal rate = dDOT(axis,joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
+    if (joint->flags & dJOINT_REVERSE) rate = - rate;
+    return rate;
+  }
+  else return 0;
+}
+
+
+void dJointAddHingeTorque (dJointID j, dReal torque)
+{
+  dxJointHinge* joint = (dxJointHinge*)j;
+  dVector3 axis;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dhinge_vtable,"joint is not a Hinge");
+
+  if (joint->flags & dJOINT_REVERSE)
+    torque = -torque;
+
+  getAxis (joint,axis,joint->axis1);
+  axis[0] *= torque;
+  axis[1] *= torque;
+  axis[2] *= torque;
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
+}
+
+
+dxJoint::Vtable __dhinge_vtable = {
+  sizeof(dxJointHinge),
+  (dxJoint::init_fn*) hingeInit,
+  (dxJoint::getInfo1_fn*) hingeGetInfo1,
+  (dxJoint::getInfo2_fn*) hingeGetInfo2,
+  dJointTypeHinge};
+
+//****************************************************************************
+// slider
+
+static void sliderInit (dxJointSlider *j)
+{
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->qrel,4);
+  dSetZero (j->offset,4);
+  j->limot.init (j->world);
+}
+
+
+dReal dJointGetSliderPosition (dJointID j)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+
+  // get axis1 in global coordinates
+  dVector3 ax1,q;
+  dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
+
+  if (joint->node[1].body) {
+    // get body2 + offset point in global coordinates
+    dMULTIPLY0_331 (q,joint->node[1].body->posr.R,joint->offset);
+    for (int i=0; i<3; i++) q[i] = joint->node[0].body->posr.pos[i] - q[i] -
+			      joint->node[1].body->posr.pos[i];
+  }
+  else {
+    for (int i=0; i<3; i++) q[i] = joint->node[0].body->posr.pos[i] -
+			      joint->offset[i];
+
+  }
+  return dDOT(ax1,q);
+}
+
+
+dReal dJointGetSliderPositionRate (dJointID j)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+
+  // get axis1 in global coordinates
+  dVector3 ax1;
+  dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
+
+  if (joint->node[1].body) {
+    return dDOT(ax1,joint->node[0].body->lvel) -
+      dDOT(ax1,joint->node[1].body->lvel);
+  }
+  else {
+    return dDOT(ax1,joint->node[0].body->lvel);
+  }
+}
+
+
+static void sliderGetInfo1 (dxJointSlider *j, dxJoint::Info1 *info)
+{
+  info->nub = 5;
+
+  // see if joint is powered
+  if (j->limot.fmax > 0)
+    info->m = 6;	// powered slider needs an extra constraint row
+  else info->m = 5;
+
+  // see if we're at a joint limit.
+  j->limot.limit = 0;
+  if ((j->limot.lostop > -dInfinity || j->limot.histop < dInfinity) &&
+      j->limot.lostop <= j->limot.histop) {
+    // measure joint position
+    dReal pos = dJointGetSliderPosition (j);
+    if (pos <= j->limot.lostop) {
+      j->limot.limit = 1;
+      j->limot.limit_err = pos - j->limot.lostop;
+      info->m = 6;
+    }
+    else if (pos >= j->limot.histop) {
+      j->limot.limit = 2;
+      j->limot.limit_err = pos - j->limot.histop;
+      info->m = 6;
+    }
+  }
+}
+
+
+static void sliderGetInfo2 (dxJointSlider *joint, dxJoint::Info2 *info)
+{
+  int i,s = info->rowskip;
+  int s3=3*s,s4=4*s;
+
+  // pull out pos and R for both bodies. also get the `connection'
+  // vector pos2-pos1.
+
+  dReal *pos1,*pos2,*R1,*R2;
+  dVector3 c;
+  pos1 = joint->node[0].body->posr.pos;
+  R1 = joint->node[0].body->posr.R;
+  if (joint->node[1].body) {
+    pos2 = joint->node[1].body->posr.pos;
+    R2 = joint->node[1].body->posr.R;
+    for (i=0; i<3; i++) c[i] = pos2[i] - pos1[i];
+  }
+  else {
+    pos2 = 0;
+    R2 = 0;
+  }
+
+  // 3 rows to make body rotations equal
+  setFixedOrientation(joint, info, joint->qrel, 0);
+
+  // remaining two rows. we want: vel2 = vel1 + w1 x c ... but this would
+  // result in three equations, so we project along the planespace vectors
+  // so that sliding along the slider axis is disregarded. for symmetry we
+  // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2.
+
+  dVector3 ax1;	// joint axis in global coordinates (unit length)
+  dVector3 p,q;	// plane space of ax1
+  dMULTIPLY0_331 (ax1,R1,joint->axis1);
+  dPlaneSpace (ax1,p,q);
+  if (joint->node[1].body) {
+    dVector3 tmp;
+    dCROSS (tmp, = REAL(0.5) * ,c,p);
+    for (i=0; i<3; i++) info->J1a[s3+i] = tmp[i];
+    for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i];
+    dCROSS (tmp, = REAL(0.5) * ,c,q);
+    for (i=0; i<3; i++) info->J1a[s4+i] = tmp[i];
+    for (i=0; i<3; i++) info->J2a[s4+i] = tmp[i];
+    for (i=0; i<3; i++) info->J2l[s3+i] = -p[i];
+    for (i=0; i<3; i++) info->J2l[s4+i] = -q[i];
+  }
+  for (i=0; i<3; i++) info->J1l[s3+i] = p[i];
+  for (i=0; i<3; i++) info->J1l[s4+i] = q[i];
+
+  // compute last two elements of right hand side. we want to align the offset
+  // point (in body 2's frame) with the center of body 1.
+  dReal k = info->fps * info->erp;
+  if (joint->node[1].body) {
+    dVector3 ofs;		// offset point in global coordinates
+    dMULTIPLY0_331 (ofs,R2,joint->offset);
+    for (i=0; i<3; i++) c[i] += ofs[i];
+    info->c[3] = k * dDOT(p,c);
+    info->c[4] = k * dDOT(q,c);
+  }
+  else {
+    dVector3 ofs;		// offset point in global coordinates
+    for (i=0; i<3; i++) ofs[i] = joint->offset[i] - pos1[i];
+    info->c[3] = k * dDOT(p,ofs);
+    info->c[4] = k * dDOT(q,ofs);
+  }
+
+  // if the slider is powered, or has joint limits, add in the extra row
+  joint->limot.addLimot (joint,info,5,ax1,0);
+}
+
+
+void dJointSetSliderAxis (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  int i;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  setAxes (joint,x,y,z,joint->axis1,0);
+
+  // compute initial relative rotation body1 -> body2, or env -> body1
+  // also compute center of body1 w.r.t body 2
+  if (joint->node[1].body) {
+    dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+    dVector3 c;
+    for (i=0; i<3; i++)
+      c[i] = joint->node[0].body->posr.pos[i] - joint->node[1].body->posr.pos[i];
+    dMULTIPLY1_331 (joint->offset,joint->node[1].body->posr.R,c);
+  }
+  else {
+    // set joint->qrel to the transpose of the first body's q
+    joint->qrel[0] = joint->node[0].body->q[0];
+    for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+    for (i=0; i<3; i++) joint->offset[i] = joint->node[0].body->posr.pos[i];
+  }
+}
+
+
+void dJointSetSliderAxisDelta (dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  int i;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  setAxes (joint,x,y,z,joint->axis1,0);
+
+  // compute initial relative rotation body1 -> body2, or env -> body1
+  // also compute center of body1 w.r.t body 2
+  if (joint->node[1].body) {
+    dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+    dVector3 c;
+    for (i=0; i<3; i++)
+      c[i] = joint->node[0].body->posr.pos[i] - joint->node[1].body->posr.pos[i];
+    dMULTIPLY1_331 (joint->offset,joint->node[1].body->posr.R,c);
+  }
+  else {
+    // set joint->qrel to the transpose of the first body's q
+    joint->qrel[0] = joint->node[0].body->q[0];
+
+    for (i=1; i<4; i++)
+      joint->qrel[i] = -joint->node[0].body->q[i];
+
+    joint->offset[0] = joint->node[0].body->posr.pos[0] + dx;
+    joint->offset[1] = joint->node[0].body->posr.pos[1] + dy;
+    joint->offset[2] = joint->node[0].body->posr.pos[2] + dz;
+  }
+}
+
+
+
+void dJointGetSliderAxis (dJointID j, dVector3 result)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  getAxis (joint,result,joint->axis1);
+}
+
+
+void dJointSetSliderParam (dJointID j, int parameter, dReal value)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  joint->limot.set (parameter,value);
+}
+
+
+dReal dJointGetSliderParam (dJointID j, int parameter)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+  return joint->limot.get (parameter);
+}
+
+
+void dJointAddSliderForce (dJointID j, dReal force)
+{
+  dxJointSlider* joint = (dxJointSlider*)j;
+  dVector3 axis;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dslider_vtable,"joint is not a slider");
+
+  if (joint->flags & dJOINT_REVERSE)
+    force -= force;
+
+  getAxis (joint,axis,joint->axis1);
+  axis[0] *= force;
+  axis[1] *= force;
+  axis[2] *= force;
+
+  if (joint->node[0].body != 0)
+    dBodyAddForce (joint->node[0].body,axis[0],axis[1],axis[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddForce(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
+
+  if (joint->node[0].body != 0 && joint->node[1].body != 0) {
+    // linear torque decoupling:
+    // we have to compensate the torque, that this slider force may generate
+    // if body centers are not aligned along the slider axis
+
+    dVector3 ltd; // Linear Torque Decoupling vector (a torque)
+
+    dVector3 c;
+    c[0]=REAL(0.5)*(joint->node[1].body->posr.pos[0]-joint->node[0].body->posr.pos[0]);
+    c[1]=REAL(0.5)*(joint->node[1].body->posr.pos[1]-joint->node[0].body->posr.pos[1]);
+    c[2]=REAL(0.5)*(joint->node[1].body->posr.pos[2]-joint->node[0].body->posr.pos[2]);
+    dCROSS (ltd,=,c,axis);
+
+    dBodyAddTorque (joint->node[0].body,ltd[0],ltd[1], ltd[2]);
+    dBodyAddTorque (joint->node[1].body,ltd[0],ltd[1], ltd[2]);
+  }
+}
+
+
+dxJoint::Vtable __dslider_vtable = {
+  sizeof(dxJointSlider),
+  (dxJoint::init_fn*) sliderInit,
+  (dxJoint::getInfo1_fn*) sliderGetInfo1,
+  (dxJoint::getInfo2_fn*) sliderGetInfo2,
+  dJointTypeSlider};
+
+//****************************************************************************
+// contact
+
+static void contactInit (dxJointContact *j)
+{
+  // default frictionless contact. hmmm, this info gets overwritten straight
+  // away anyway, so why bother?
+#if 0 /* so don't bother ;) */
+  j->contact.surface.mode = 0;
+  j->contact.surface.mu = 0;
+  dSetZero (j->contact.geom.pos,4);
+  dSetZero (j->contact.geom.normal,4);
+  j->contact.geom.depth = 0;
+#endif
+}
+
+
+static void contactGetInfo1 (dxJointContact *j, dxJoint::Info1 *info)
+{
+  // make sure mu's >= 0, then calculate number of constraint rows and number
+  // of unbounded rows.
+  int m = 1, nub=0;
+  if (j->contact.surface.mu < 0) j->contact.surface.mu = 0;
+  if (j->contact.surface.mode & dContactMu2) {
+    if (j->contact.surface.mu > 0) m++;
+    if (j->contact.surface.mu2 < 0) j->contact.surface.mu2 = 0;
+    if (j->contact.surface.mu2 > 0) m++;
+    if (j->contact.surface.mu  == dInfinity) nub ++;
+    if (j->contact.surface.mu2 == dInfinity) nub ++;
+  }
+  else {
+    if (j->contact.surface.mu > 0) m += 2;
+    if (j->contact.surface.mu == dInfinity) nub += 2;
+  }
+
+  j->the_m = m;
+  info->m = m;
+  info->nub = nub;
+}
+
+
+static void contactGetInfo2 (dxJointContact *j, dxJoint::Info2 *info)
+{
+  int s = info->rowskip;
+  int s2 = 2*s;
+
+  // get normal, with sign adjusted for body1/body2 polarity
+  dVector3 normal;
+  if (j->flags & dJOINT_REVERSE) {
+    normal[0] = - j->contact.geom.normal[0];
+    normal[1] = - j->contact.geom.normal[1];
+    normal[2] = - j->contact.geom.normal[2];
+  }
+  else {
+    normal[0] = j->contact.geom.normal[0];
+    normal[1] = j->contact.geom.normal[1];
+    normal[2] = j->contact.geom.normal[2];
+  }
+  normal[3] = 0;	// @@@ hmmm
+
+  // c1,c2 = contact points with respect to body PORs
+  dVector3 c1,c2;
+  c1[0] = j->contact.geom.pos[0] - j->node[0].body->posr.pos[0];
+  c1[1] = j->contact.geom.pos[1] - j->node[0].body->posr.pos[1];
+  c1[2] = j->contact.geom.pos[2] - j->node[0].body->posr.pos[2];
+
+  // set jacobian for normal
+  info->J1l[0] = normal[0];
+  info->J1l[1] = normal[1];
+  info->J1l[2] = normal[2];
+  dCROSS (info->J1a,=,c1,normal);
+  if (j->node[1].body) {
+    c2[0] = j->contact.geom.pos[0] - j->node[1].body->posr.pos[0];
+    c2[1] = j->contact.geom.pos[1] - j->node[1].body->posr.pos[1];
+    c2[2] = j->contact.geom.pos[2] - j->node[1].body->posr.pos[2];
+    info->J2l[0] = -normal[0];
+    info->J2l[1] = -normal[1];
+    info->J2l[2] = -normal[2];
+    dCROSS (info->J2a,= -,c2,normal);
+  }
+
+  // set right hand side and cfm value for normal
+  dReal erp = info->erp;
+  if (j->contact.surface.mode & dContactSoftERP)
+    erp = j->contact.surface.soft_erp;
+  dReal k = info->fps * erp;
+  dReal depth = j->contact.geom.depth - j->world->contactp.min_depth;
+  if (depth < 0) depth = 0;
+
+  const dReal maxvel = j->world->contactp.max_vel;
+  info->c[0] = k*depth;
+  if (info->c[0] > maxvel)
+    info->c[0] = maxvel;
+
+  if (j->contact.surface.mode & dContactSoftCFM)
+    info->cfm[0] = j->contact.surface.soft_cfm;
+
+  // deal with bounce
+  if (j->contact.surface.mode & dContactBounce) {
+    // calculate outgoing velocity (-ve for incoming contact)
+    dReal outgoing = dDOT(info->J1l,j->node[0].body->lvel) +
+      dDOT(info->J1a,j->node[0].body->avel);
+    if (j->node[1].body) {
+      outgoing += dDOT(info->J2l,j->node[1].body->lvel) +
+	dDOT(info->J2a,j->node[1].body->avel);
+    }
+    // only apply bounce if the outgoing velocity is greater than the
+    // threshold, and if the resulting c[0] exceeds what we already have.
+    if (j->contact.surface.bounce_vel >= 0 &&
+	(-outgoing) > j->contact.surface.bounce_vel) {
+      dReal newc = - j->contact.surface.bounce * outgoing;
+      if (newc > info->c[0]) info->c[0] = newc;
+    }
+  }
+
+  // set LCP limits for normal
+  info->lo[0] = 0;
+  info->hi[0] = dInfinity;
+
+  // now do jacobian for tangential forces
+  dVector3 t1,t2;	// two vectors tangential to normal
+
+  // first friction direction
+  if (j->the_m >= 2) {
+    if (j->contact.surface.mode & dContactFDir1) {	// use fdir1 ?
+      t1[0] = j->contact.fdir1[0];
+      t1[1] = j->contact.fdir1[1];
+      t1[2] = j->contact.fdir1[2];
+      dCROSS (t2,=,normal,t1);
+    }
+    else {
+      dPlaneSpace (normal,t1,t2);
+    }
+    info->J1l[s+0] = t1[0];
+    info->J1l[s+1] = t1[1];
+    info->J1l[s+2] = t1[2];
+    dCROSS (info->J1a+s,=,c1,t1);
+    if (j->node[1].body) {
+      info->J2l[s+0] = -t1[0];
+      info->J2l[s+1] = -t1[1];
+      info->J2l[s+2] = -t1[2];
+      dCROSS (info->J2a+s,= -,c2,t1);
+    }
+    // set right hand side
+    if (j->contact.surface.mode & dContactMotion1) {
+      info->c[1] = j->contact.surface.motion1;
+    }
+    // set LCP bounds and friction index. this depends on the approximation
+    // mode
+    info->lo[1] = -j->contact.surface.mu;
+    info->hi[1] = j->contact.surface.mu;
+    if (j->contact.surface.mode & dContactApprox1_1) info->findex[1] = 0;
+
+    // set slip (constraint force mixing)
+    if (j->contact.surface.mode & dContactSlip1)
+      info->cfm[1] = j->contact.surface.slip1;
+  }
+
+  // second friction direction
+  if (j->the_m >= 3) {
+    info->J1l[s2+0] = t2[0];
+    info->J1l[s2+1] = t2[1];
+    info->J1l[s2+2] = t2[2];
+    dCROSS (info->J1a+s2,=,c1,t2);
+    if (j->node[1].body) {
+      info->J2l[s2+0] = -t2[0];
+      info->J2l[s2+1] = -t2[1];
+      info->J2l[s2+2] = -t2[2];
+      dCROSS (info->J2a+s2,= -,c2,t2);
+    }
+    // set right hand side
+    if (j->contact.surface.mode & dContactMotion2) {
+      info->c[2] = j->contact.surface.motion2;
+    }
+    // set LCP bounds and friction index. this depends on the approximation
+    // mode
+    if (j->contact.surface.mode & dContactMu2) {
+      info->lo[2] = -j->contact.surface.mu2;
+      info->hi[2] = j->contact.surface.mu2;
+    }
+    else {
+      info->lo[2] = -j->contact.surface.mu;
+      info->hi[2] = j->contact.surface.mu;
+    }
+    if (j->contact.surface.mode & dContactApprox1_2) info->findex[2] = 0;
+
+    // set slip (constraint force mixing)
+    if (j->contact.surface.mode & dContactSlip2)
+      info->cfm[2] = j->contact.surface.slip2;
+  }
+}
+
+
+dxJoint::Vtable __dcontact_vtable = {
+  sizeof(dxJointContact),
+  (dxJoint::init_fn*) contactInit,
+  (dxJoint::getInfo1_fn*) contactGetInfo1,
+  (dxJoint::getInfo2_fn*) contactGetInfo2,
+  dJointTypeContact};
+
+//****************************************************************************
+// hinge 2. note that this joint must be attached to two bodies for it to work
+
+static dReal measureHinge2Angle (dxJointHinge2 *joint)
+{
+  dVector3 a1,a2;
+  dMULTIPLY0_331 (a1,joint->node[1].body->posr.R,joint->axis2);
+  dMULTIPLY1_331 (a2,joint->node[0].body->posr.R,a1);
+  dReal x = dDOT(joint->v1,a2);
+  dReal y = dDOT(joint->v2,a2);
+  return -dAtan2 (y,x);
+}
+
+
+static void hinge2Init (dxJointHinge2 *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->axis2,4);
+  j->axis2[1] = 1;
+  j->c0 = 0;
+  j->s0 = 0;
+
+  dSetZero (j->v1,4);
+  j->v1[0] = 1;
+  dSetZero (j->v2,4);
+  j->v2[1] = 1;
+
+  j->limot1.init (j->world);
+  j->limot2.init (j->world);
+
+  j->susp_erp = j->world->global_erp;
+  j->susp_cfm = j->world->global_cfm;
+
+  j->flags |= dJOINT_TWOBODIES;
+}
+
+
+static void hinge2GetInfo1 (dxJointHinge2 *j, dxJoint::Info1 *info)
+{
+  info->m = 4;
+  info->nub = 4;
+
+  // see if we're powered or at a joint limit for axis 1
+  int atlimit=0;
+  if ((j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) &&
+      j->limot1.lostop <= j->limot1.histop) {
+    dReal angle = measureHinge2Angle (j);
+    if (j->limot1.testRotationalLimit (angle)) atlimit = 1;
+  }
+  if (atlimit || j->limot1.fmax > 0) info->m++;
+
+  // see if we're powering axis 2 (we currently never limit this axis)
+  j->limot2.limit = 0;
+  if (j->limot2.fmax > 0) info->m++;
+}
+
+
+// macro that computes ax1,ax2 = axis 1 and 2 in global coordinates (they are
+// relative to body 1 and 2 initially) and then computes the constrained
+// rotational axis as the cross product of ax1 and ax2.
+// the sin and cos of the angle between axis 1 and 2 is computed, this comes
+// from dot and cross product rules.
+
+#define HINGE2_GET_AXIS_INFO(axis,sin_angle,cos_angle) \
+  dVector3 ax1,ax2; \
+  dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1); \
+  dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2); \
+  dCROSS (axis,=,ax1,ax2); \
+  sin_angle = dSqrt (axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]); \
+  cos_angle = dDOT (ax1,ax2);
+
+
+static void hinge2GetInfo2 (dxJointHinge2 *joint, dxJoint::Info2 *info)
+{
+  // get information we need to set the hinge row
+  dReal s,c;
+  dVector3 q;
+  HINGE2_GET_AXIS_INFO (q,s,c);
+  dNormalize3 (q);		// @@@ quicker: divide q by s ?
+
+  // set the three ball-and-socket rows (aligned to the suspension axis ax1)
+  setBall2 (joint,info,joint->anchor1,joint->anchor2,ax1,joint->susp_erp);
+
+  // set the hinge row
+  int s3=3*info->rowskip;
+  info->J1a[s3+0] = q[0];
+  info->J1a[s3+1] = q[1];
+  info->J1a[s3+2] = q[2];
+  if (joint->node[1].body) {
+    info->J2a[s3+0] = -q[0];
+    info->J2a[s3+1] = -q[1];
+    info->J2a[s3+2] = -q[2];
+  }
+
+  // compute the right hand side for the constrained rotational DOF.
+  // axis 1 and axis 2 are separated by an angle `theta'. the desired
+  // separation angle is theta0. sin(theta0) and cos(theta0) are recorded
+  // in the joint structure. the correcting angular velocity is:
+  //   |angular_velocity| = angle/time = erp*(theta0-theta) / stepsize
+  //                      = (erp*fps) * (theta0-theta)
+  // (theta0-theta) can be computed using the following small-angle-difference
+  // approximation:
+  //   theta0-theta ~= tan(theta0-theta)
+  //                 = sin(theta0-theta)/cos(theta0-theta)
+  //                 = (c*s0 - s*c0) / (c*c0 + s*s0)
+  //                 = c*s0 - s*c0         assuming c*c0 + s*s0 ~= 1
+  // where c = cos(theta), s = sin(theta)
+  //       c0 = cos(theta0), s0 = sin(theta0)
+
+  dReal k = info->fps * info->erp;
+  info->c[3] = k * (joint->c0 * s - joint->s0 * c);
+
+  // if the axis1 hinge is powered, or has joint limits, add in more stuff
+  int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1);
+
+  // if the axis2 hinge is powered, add in more stuff
+  joint->limot2.addLimot (joint,info,row,ax2,1);
+
+  // set parameter for the suspension
+  info->cfm[0] = joint->susp_cfm;
+}
+
+
+// compute vectors v1 and v2 (embedded in body1), used to measure angle
+// between body 1 and body 2
+
+static void makeHinge2V1andV2 (dxJointHinge2 *joint)
+{
+  if (joint->node[0].body) {
+    // get axis 1 and 2 in global coords
+    dVector3 ax1,ax2,v;
+    dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
+    dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2);
+
+    // don't do anything if the axis1 or axis2 vectors are zero or the same
+    if ((ax1[0]==0 && ax1[1]==0 && ax1[2]==0) ||
+	(ax2[0]==0 && ax2[1]==0 && ax2[2]==0) ||
+	(ax1[0]==ax2[0] && ax1[1]==ax2[1] && ax1[2]==ax2[2])) return;
+
+    // modify axis 2 so it's perpendicular to axis 1
+    dReal k = dDOT(ax1,ax2);
+    for (int i=0; i<3; i++) ax2[i] -= k*ax1[i];
+    dNormalize3 (ax2);
+
+    // make v1 = modified axis2, v2 = axis1 x (modified axis2)
+    dCROSS (v,=,ax1,ax2);
+    dMULTIPLY1_331 (joint->v1,joint->node[0].body->posr.R,ax2);
+    dMULTIPLY1_331 (joint->v2,joint->node[0].body->posr.R,v);
+  }
+}
+
+
+void dJointSetHinge2Anchor (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+  makeHinge2V1andV2 (joint);
+}
+
+
+void dJointSetHinge2Axis1 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) {
+    dReal q[4];
+    q[0] = x;
+    q[1] = y;
+    q[2] = z;
+    q[3] = 0;
+    dNormalize3 (q);
+    dMULTIPLY1_331 (joint->axis1,joint->node[0].body->posr.R,q);
+    joint->axis1[3] = 0;
+
+    // compute the sin and cos of the angle between axis 1 and axis 2
+    dVector3 ax;
+    HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0);
+  }
+  makeHinge2V1andV2 (joint);
+}
+
+
+void dJointSetHinge2Axis2 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[1].body) {
+    dReal q[4];
+    q[0] = x;
+    q[1] = y;
+    q[2] = z;
+    q[3] = 0;
+    dNormalize3 (q);
+    dMULTIPLY1_331 (joint->axis2,joint->node[1].body->posr.R,q);
+    joint->axis1[3] = 0;
+
+    // compute the sin and cos of the angle between axis 1 and axis 2
+    dVector3 ax;
+    HINGE2_GET_AXIS_INFO(ax,joint->s0,joint->c0);
+  }
+  makeHinge2V1andV2 (joint);
+}
+
+
+void dJointSetHinge2Param (dJointID j, int parameter, dReal value)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if ((parameter & 0xff00) == 0x100) {
+    joint->limot2.set (parameter & 0xff,value);
+  }
+  else {
+    if (parameter == dParamSuspensionERP) joint->susp_erp = value;
+    else if (parameter == dParamSuspensionCFM) joint->susp_cfm = value;
+    else joint->limot1.set (parameter,value);
+  }
+}
+
+
+void dJointGetHinge2Anchor (dJointID j, dVector3 result)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+void dJointGetHinge2Anchor2 (dJointID j, dVector3 result)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+void dJointGetHinge2Axis1 (dJointID j, dVector3 result)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) {
+    dMULTIPLY0_331 (result,joint->node[0].body->posr.R,joint->axis1);
+  }
+}
+
+
+void dJointGetHinge2Axis2 (dJointID j, dVector3 result)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (result,joint->node[1].body->posr.R,joint->axis2);
+  }
+}
+
+
+dReal dJointGetHinge2Param (dJointID j, int parameter)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if ((parameter & 0xff00) == 0x100) {
+    return joint->limot2.get (parameter & 0xff);
+  }
+  else {
+    if (parameter == dParamSuspensionERP) return joint->susp_erp;
+    else if (parameter == dParamSuspensionCFM) return joint->susp_cfm;
+    else return joint->limot1.get (parameter);
+  }
+}
+
+
+dReal dJointGetHinge2Angle1 (dJointID j)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) return measureHinge2Angle (joint);
+  else return 0;
+}
+
+
+dReal dJointGetHinge2Angle1Rate (dJointID j)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body) {
+    dVector3 axis;
+    dMULTIPLY0_331 (axis,joint->node[0].body->posr.R,joint->axis1);
+    dReal rate = dDOT(axis,joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
+    return rate;
+  }
+  else return 0;
+}
+
+
+dReal dJointGetHinge2Angle2Rate (dJointID j)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+  if (joint->node[0].body && joint->node[1].body) {
+    dVector3 axis;
+    dMULTIPLY0_331 (axis,joint->node[1].body->posr.R,joint->axis2);
+    dReal rate = dDOT(axis,joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis,joint->node[1].body->avel);
+    return rate;
+  }
+  else return 0;
+}
+
+
+void dJointAddHinge2Torques (dJointID j, dReal torque1, dReal torque2)
+{
+  dxJointHinge2* joint = (dxJointHinge2*)j;
+  dVector3 axis1, axis2;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dhinge2_vtable,"joint is not a hinge2");
+
+  if (joint->node[0].body && joint->node[1].body) {
+    dMULTIPLY0_331 (axis1,joint->node[0].body->posr.R,joint->axis1);
+    dMULTIPLY0_331 (axis2,joint->node[1].body->posr.R,joint->axis2);
+    axis1[0] = axis1[0] * torque1 + axis2[0] * torque2;
+    axis1[1] = axis1[1] * torque1 + axis2[1] * torque2;
+    axis1[2] = axis1[2] * torque1 + axis2[2] * torque2;
+    dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]);
+    dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]);
+  }
+}
+
+
+dxJoint::Vtable __dhinge2_vtable = {
+  sizeof(dxJointHinge2),
+  (dxJoint::init_fn*) hinge2Init,
+  (dxJoint::getInfo1_fn*) hinge2GetInfo1,
+  (dxJoint::getInfo2_fn*) hinge2GetInfo2,
+  dJointTypeHinge2};
+
+//****************************************************************************
+// universal
+
+// I just realized that the universal joint is equivalent to a hinge 2 joint with
+// perfectly stiff suspension.  By comparing the hinge 2 implementation to
+// the universal implementation, you may be able to improve this
+// implementation (or, less likely, the hinge2 implementation).
+
+static void universalInit (dxJointUniversal *j)
+{
+  dSetZero (j->anchor1,4);
+  dSetZero (j->anchor2,4);
+  dSetZero (j->axis1,4);
+  j->axis1[0] = 1;
+  dSetZero (j->axis2,4);
+  j->axis2[1] = 1;
+  dSetZero(j->qrel1,4);
+  dSetZero(j->qrel2,4);
+  j->limot1.init (j->world);
+  j->limot2.init (j->world);
+}
+
+
+static void getUniversalAxes(dxJointUniversal *joint, dVector3 ax1, dVector3 ax2)
+{
+  // This says "ax1 = joint->node[0].body->posr.R * joint->axis1"
+  dMULTIPLY0_331 (ax1,joint->node[0].body->posr.R,joint->axis1);
+
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (ax2,joint->node[1].body->posr.R,joint->axis2);
+  }
+  else {
+    ax2[0] = joint->axis2[0];
+    ax2[1] = joint->axis2[1];
+    ax2[2] = joint->axis2[2];
+  }
+}
+
+static void getUniversalAngles(dxJointUniversal *joint, dReal *angle1, dReal *angle2)
+{
+  if (joint->node[0].body)
+  {
+    // length 1 joint axis in global coordinates, from each body
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross, qq, qrel;
+
+    getUniversalAxes (joint,ax1,ax2);
+
+    // It should be possible to get both angles without explicitly
+    // constructing the rotation matrix of the cross.  Basically,
+    // orientation of the cross about axis1 comes from body 2,
+    // about axis 2 comes from body 1, and the perpendicular
+    // axis can come from the two bodies somehow.  (We don't really
+    // want to assume it's 90 degrees, because in general the
+    // constraints won't be perfectly satisfied, or even very well
+    // satisfied.)
+    //
+    // However, we'd need a version of getHingeAngleFromRElativeQuat()
+    // that CAN handle when its relative quat is rotated along a direction
+    // other than the given axis.  What I have here works,
+    // although it's probably much slower than need be.
+
+    dRFrom2Axes (R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
+
+    dRtoQ (R, qcross);
+
+
+    // This code is essentialy the same as getHingeAngle(), see the comments
+    // there for details.
+
+    // get qrel = relative rotation between node[0] and the cross
+    dQMultiply1 (qq, joint->node[0].body->q, qcross);
+    dQMultiply2 (qrel, qq, joint->qrel1);
+
+    *angle1 = getHingeAngleFromRelativeQuat(qrel, joint->axis1);
+
+    // This is equivalent to
+    // dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
+    // You see that the R is constructed from the same 2 axis as for angle1
+    // but the first and second axis are swapped.
+    // So we can take the first R and rapply a rotation to it.
+    // The rotation is around the axis between the 2 axes (ax1 and ax2).
+    // We do a rotation of 180deg.
+
+    dQuaternion qcross2;
+    // Find the vector between ax1 and ax2 (i.e. in the middle)
+    // We need to turn around this vector by 180deg
+
+    // The 2 axes should be normalize so to find the vector between the 2.
+    // Add and devide by 2 then normalize or simply normalize
+    //    ax2
+    //    ^
+    //    |
+    //    |
+    ///   *------------> ax1
+    //    We want the vector a 45deg
+    //
+    // N.B. We don't need to normalize the ax1 and ax2 since there are
+    //      normalized when we set them.
+
+    // We set the quaternion q = [cos(theta), dir*sin(theta)] = [w, x, y, Z]
+    qrel[0] = 0;                // equivalent to cos(Pi/2)
+    qrel[1] = ax1[0] + ax2[0];  // equivalent to x*sin(Pi/2); since sin(Pi/2) = 1
+    qrel[2] = ax1[1] + ax2[1];
+    qrel[3] = ax1[2] + ax2[2];
+
+    dReal l = dRecip(sqrt(qrel[1]*qrel[1] + qrel[2]*qrel[2] + qrel[3]*qrel[3]));
+    qrel[1] *= l;
+    qrel[2] *= l;
+    qrel[3] *= l;
+
+    dQMultiply0 (qcross2, qrel, qcross);
+
+    if (joint->node[1].body) {
+      dQMultiply1 (qq, joint->node[1].body->q, qcross2);
+      dQMultiply2 (qrel, qq, joint->qrel2);
+    }
+    else {
+      // pretend joint->node[1].body->q is the identity
+      dQMultiply2 (qrel, qcross2, joint->qrel2);
+    }
+
+    *angle2 = - getHingeAngleFromRelativeQuat(qrel, joint->axis2);
+
+  }
+  else
+  {
+    *angle1 = 0;
+    *angle2 = 0;
+  }
+}
+
+static dReal getUniversalAngle1(dxJointUniversal *joint)
+{
+  if (joint->node[0].body) {
+    // length 1 joint axis in global coordinates, from each body
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross, qq, qrel;
+
+    getUniversalAxes (joint,ax1,ax2);
+
+    // It should be possible to get both angles without explicitly
+    // constructing the rotation matrix of the cross.  Basically,
+    // orientation of the cross about axis1 comes from body 2,
+    // about axis 2 comes from body 1, and the perpendicular
+    // axis can come from the two bodies somehow.  (We don't really
+    // want to assume it's 90 degrees, because in general the
+    // constraints won't be perfectly satisfied, or even very well
+    // satisfied.)
+    //
+    // However, we'd need a version of getHingeAngleFromRElativeQuat()
+    // that CAN handle when its relative quat is rotated along a direction
+    // other than the given axis.  What I have here works,
+    // although it's probably much slower than need be.
+
+    dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
+    dRtoQ (R,qcross);
+
+    // This code is essential the same as getHingeAngle(), see the comments
+    // there for details.
+
+    // get qrel = relative rotation between node[0] and the cross
+    dQMultiply1 (qq,joint->node[0].body->q,qcross);
+    dQMultiply2 (qrel,qq,joint->qrel1);
+
+    return getHingeAngleFromRelativeQuat(qrel, joint->axis1);
+  }
+  return 0;
+}
+
+
+static dReal getUniversalAngle2(dxJointUniversal *joint)
+{
+  if (joint->node[0].body) {
+    // length 1 joint axis in global coordinates, from each body
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross, qq, qrel;
+
+    getUniversalAxes (joint,ax1,ax2);
+
+    // It should be possible to get both angles without explicitly
+    // constructing the rotation matrix of the cross.  Basically,
+    // orientation of the cross about axis1 comes from body 2,
+    // about axis 2 comes from body 1, and the perpendicular
+    // axis can come from the two bodies somehow.  (We don't really
+    // want to assume it's 90 degrees, because in general the
+    // constraints won't be perfectly satisfied, or even very well
+    // satisfied.)
+    //
+    // However, we'd need a version of getHingeAngleFromRElativeQuat()
+    // that CAN handle when its relative quat is rotated along a direction
+    // other than the given axis.  What I have here works,
+    // although it's probably much slower than need be.
+
+    dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
+    dRtoQ(R, qcross);
+
+    if (joint->node[1].body) {
+      dQMultiply1 (qq, joint->node[1].body->q, qcross);
+      dQMultiply2 (qrel,qq,joint->qrel2);
+    }
+    else {
+      // pretend joint->node[1].body->q is the identity
+      dQMultiply2 (qrel,qcross, joint->qrel2);
+    }
+
+    return - getHingeAngleFromRelativeQuat(qrel, joint->axis2);
+  }
+  return 0;
+}
+
+
+static void universalGetInfo1 (dxJointUniversal *j, dxJoint::Info1 *info)
+{
+  info->nub = 4;
+  info->m = 4;
+
+  // see if we're powered or at a joint limit.
+  bool constraint1 = j->limot1.fmax > 0;
+  bool constraint2 = j->limot2.fmax > 0;
+
+  bool limiting1 = (j->limot1.lostop >= -M_PI || j->limot1.histop <= M_PI) &&
+       j->limot1.lostop <= j->limot1.histop;
+  bool limiting2 = (j->limot2.lostop >= -M_PI || j->limot2.histop <= M_PI) &&
+       j->limot2.lostop <= j->limot2.histop;
+
+  // We need to call testRotationLimit() even if we're motored, since it
+  // records the result.
+  if (limiting1 || limiting2) {
+    dReal angle1, angle2;
+    getUniversalAngles (j, &angle1, &angle2);
+    if (limiting1 && j->limot1.testRotationalLimit (angle1)) constraint1 = true;
+    if (limiting2 && j->limot2.testRotationalLimit (angle2)) constraint2 = true;
+  }
+  if (constraint1)
+    info->m++;
+  if (constraint2)
+    info->m++;
+}
+
+
+static void universalGetInfo2 (dxJointUniversal *joint, dxJoint::Info2 *info)
+{
+  // set the three ball-and-socket rows
+  setBall (joint,info,joint->anchor1,joint->anchor2);
+
+  // set the universal joint row. the angular velocity about an axis
+  // perpendicular to both joint axes should be equal. thus the constraint
+  // equation is
+  //    p*w1 - p*w2 = 0
+  // where p is a vector normal to both joint axes, and w1 and w2
+  // are the angular velocity vectors of the two bodies.
+
+  // length 1 joint axis in global coordinates, from each body
+  dVector3 ax1, ax2;
+  dVector3 ax2_temp;
+  // length 1 vector perpendicular to ax1 and ax2. Neither body can rotate
+  // about this.
+  dVector3 p;
+  dReal k;
+
+  getUniversalAxes(joint, ax1, ax2);
+  k = dDOT(ax1, ax2);
+  ax2_temp[0] = ax2[0] - k*ax1[0];
+  ax2_temp[1] = ax2[1] - k*ax1[1];
+  ax2_temp[2] = ax2[2] - k*ax1[2];
+  dCROSS(p, =, ax1, ax2_temp);
+  dNormalize3(p);
+
+  int s3=3*info->rowskip;
+
+  info->J1a[s3+0] = p[0];
+  info->J1a[s3+1] = p[1];
+  info->J1a[s3+2] = p[2];
+
+  if (joint->node[1].body) {
+    info->J2a[s3+0] = -p[0];
+    info->J2a[s3+1] = -p[1];
+    info->J2a[s3+2] = -p[2];
+  }
+
+  // compute the right hand side of the constraint equation. set relative
+  // body velocities along p to bring the axes back to perpendicular.
+  // If ax1, ax2 are unit length joint axes as computed from body1 and
+  // body2, we need to rotate both bodies along the axis p.  If theta
+  // is the angle between ax1 and ax2, we need an angular velocity
+  // along p to cover the angle erp * (theta - Pi/2) in one step:
+  //
+  //   |angular_velocity| = angle/time = erp*(theta - Pi/2) / stepsize
+  //                      = (erp*fps) * (theta - Pi/2)
+  //
+  // if theta is close to Pi/2,
+  // theta - Pi/2 ~= cos(theta), so
+  //    |angular_velocity|  ~= (erp*fps) * (ax1 dot ax2)
+
+  info->c[3] = info->fps * info->erp * - dDOT(ax1, ax2);
+
+  // if the first angle is powered, or has joint limits, add in the stuff
+  int row = 4 + joint->limot1.addLimot (joint,info,4,ax1,1);
+
+  // if the second angle is powered, or has joint limits, add in more stuff
+  joint->limot2.addLimot (joint,info,row,ax2,1);
+}
+
+
+static void universalComputeInitialRelativeRotations (dxJointUniversal *joint)
+{
+  if (joint->node[0].body) {
+    dVector3 ax1, ax2;
+    dMatrix3 R;
+    dQuaternion qcross;
+
+    getUniversalAxes(joint, ax1, ax2);
+
+    // Axis 1.
+    dRFrom2Axes(R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2]);
+    dRtoQ(R, qcross);
+    dQMultiply1 (joint->qrel1, joint->node[0].body->q, qcross);
+
+    // Axis 2.
+    dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
+    dRtoQ(R, qcross);
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel2, joint->node[1].body->q, qcross);
+    }
+    else {
+      // set joint->qrel to qcross
+      for (int i=0; i<4; i++) joint->qrel2[i] = qcross[i];
+    }
+  }
+}
+
+
+void dJointSetUniversalAnchor (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  setAnchors (joint,x,y,z,joint->anchor1,joint->anchor2);
+  universalComputeInitialRelativeRotations(joint);
+}
+
+
+void dJointSetUniversalAxis1 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    setAxes (joint,x,y,z,NULL,joint->axis2);
+  else
+    setAxes (joint,x,y,z,joint->axis1,NULL);
+  universalComputeInitialRelativeRotations(joint);
+}
+
+
+void dJointSetUniversalAxis2 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    setAxes (joint,x,y,z,joint->axis1,NULL);
+  else
+    setAxes (joint,x,y,z,NULL,joint->axis2);
+  universalComputeInitialRelativeRotations(joint);
+}
+
+
+void dJointGetUniversalAnchor (dJointID j, dVector3 result)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+    getAnchor (joint,result,joint->anchor1);
+}
+
+
+void dJointGetUniversalAnchor2 (dJointID j, dVector3 result)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAnchor (joint,result,joint->anchor1);
+  else
+    getAnchor2 (joint,result,joint->anchor2);
+}
+
+
+void dJointGetUniversalAxis1 (dJointID j, dVector3 result)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAxis2 (joint,result,joint->axis2);
+  else
+    getAxis (joint,result,joint->axis1);
+}
+
+
+void dJointGetUniversalAxis2 (dJointID j, dVector3 result)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    getAxis (joint,result,joint->axis1);
+  else
+    getAxis2 (joint,result,joint->axis2);
+}
+
+
+void dJointSetUniversalParam (dJointID j, int parameter, dReal value)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if ((parameter & 0xff00) == 0x100) {
+    joint->limot2.set (parameter & 0xff,value);
+  }
+  else {
+    joint->limot1.set (parameter,value);
+  }
+}
+
+
+dReal dJointGetUniversalParam (dJointID j, int parameter)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if ((parameter & 0xff00) == 0x100) {
+    return joint->limot2.get (parameter & 0xff);
+  }
+  else {
+    return joint->limot1.get (parameter);
+  }
+}
+
+void dJointGetUniversalAngles (dJointID j, dReal *angle1, dReal *angle2)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    return getUniversalAngles (joint, angle2, angle1);
+  else
+    return getUniversalAngles (joint, angle1, angle2);
+}
+
+
+dReal dJointGetUniversalAngle1 (dJointID j)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    return getUniversalAngle2 (joint);
+  else
+    return getUniversalAngle1 (joint);
+}
+
+
+dReal dJointGetUniversalAngle2 (dJointID j)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+  if (joint->flags & dJOINT_REVERSE)
+    return getUniversalAngle1 (joint);
+  else
+    return getUniversalAngle2 (joint);
+}
+
+
+dReal dJointGetUniversalAngle1Rate (dJointID j)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+
+  if (joint->node[0].body) {
+    dVector3 axis;
+
+    if (joint->flags & dJOINT_REVERSE)
+      getAxis2 (joint,axis,joint->axis2);
+    else
+      getAxis (joint,axis,joint->axis1);
+
+    dReal rate = dDOT(axis, joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel);
+    return rate;
+  }
+  return 0;
+}
+
+
+dReal dJointGetUniversalAngle2Rate (dJointID j)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+
+  if (joint->node[0].body) {
+    dVector3 axis;
+
+    if (joint->flags & dJOINT_REVERSE)
+      getAxis (joint,axis,joint->axis1);
+    else
+      getAxis2 (joint,axis,joint->axis2);
+
+    dReal rate = dDOT(axis, joint->node[0].body->avel);
+    if (joint->node[1].body) rate -= dDOT(axis, joint->node[1].body->avel);
+    return rate;
+  }
+  return 0;
+}
+
+
+void dJointAddUniversalTorques (dJointID j, dReal torque1, dReal torque2)
+{
+  dxJointUniversal* joint = (dxJointUniversal*)j;
+  dVector3 axis1, axis2;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__duniversal_vtable,"joint is not a universal");
+
+  if (joint->flags & dJOINT_REVERSE) {
+    dReal temp = torque1;
+    torque1 = - torque2;
+    torque2 = - temp;
+  }
+
+  getAxis (joint,axis1,joint->axis1);
+  getAxis2 (joint,axis2,joint->axis2);
+  axis1[0] = axis1[0] * torque1 + axis2[0] * torque2;
+  axis1[1] = axis1[1] * torque1 + axis2[1] * torque2;
+  axis1[2] = axis1[2] * torque1 + axis2[2] * torque2;
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body,axis1[0],axis1[1],axis1[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axis1[0], -axis1[1], -axis1[2]);
+}
+
+
+
+
+
+dxJoint::Vtable __duniversal_vtable = {
+  sizeof(dxJointUniversal),
+  (dxJoint::init_fn*) universalInit,
+  (dxJoint::getInfo1_fn*) universalGetInfo1,
+  (dxJoint::getInfo2_fn*) universalGetInfo2,
+  dJointTypeUniversal};
+
+
+
+//****************************************************************************
+// Prismatic and Rotoide
+
+static void PRInit (dxJointPR *j)
+{
+  // Default Position
+  // Z^
+  //  | Body 1       P      R          Body2
+  //  |+---------+   _      _         +-----------+
+  //  ||         |----|----(_)--------+           |
+  //  |+---------+   -                +-----------+
+  //  |
+  // X.-----------------------------------------> Y
+  // N.B. X is comming out of the page
+  dSetZero (j->anchor2,4);
+
+  dSetZero (j->axisR1,4);
+  j->axisR1[0] = 1;
+  dSetZero (j->axisR2,4);
+  j->axisR2[0] = 1;
+
+  dSetZero (j->axisP1,4);
+  j->axisP1[1] = 1;
+  dSetZero (j->qrel,4);
+  dSetZero (j->offset,4);
+
+  j->limotR.init (j->world);
+  j->limotP.init (j->world);
+}
+
+
+dReal dJointGetPRPosition (dJointID j)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+
+  dVector3 q;
+  // get the offset in global coordinates
+  dMULTIPLY0_331 (q,joint->node[0].body->posr.R,joint->offset);
+
+  if (joint->node[1].body) {
+    dVector3 anchor2;
+
+    // get the anchor2 in global coordinates
+    dMULTIPLY0_331 (anchor2,joint->node[1].body->posr.R,joint->anchor2);
+
+    q[0] = ( (joint->node[0].body->posr.pos[0] + q[0]) -
+             (joint->node[1].body->posr.pos[0] + anchor2[0]) );
+    q[1] = ( (joint->node[0].body->posr.pos[1] + q[1]) -
+             (joint->node[1].body->posr.pos[1] + anchor2[1]) );
+    q[2] = ( (joint->node[0].body->posr.pos[2] + q[2]) -
+             (joint->node[1].body->posr.pos[2] + anchor2[2]) );
+
+  }
+  else {
+    //N.B. When there is no body 2 the joint->anchor2 is already in
+    //     global coordinates
+
+    q[0] = ( (joint->node[0].body->posr.pos[0] + q[0]) -
+             (joint->anchor2[0]) );
+    q[1] = ( (joint->node[0].body->posr.pos[1] + q[1]) -
+             (joint->anchor2[1]) );
+    q[2] = ( (joint->node[0].body->posr.pos[2] + q[2]) -
+             (joint->anchor2[2]) );
+
+  }
+
+  dVector3 axP;
+  // get prismatic axis in global coordinates
+  dMULTIPLY0_331 (axP,joint->node[0].body->posr.R,joint->axisP1);
+
+  return dDOT(axP, q);
+}
+
+
+dReal dJointGetPRPositionRate (dJointID j)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+
+  if (joint->node[0].body) {
+		// We want to find the rate of change of the prismatic part of the joint
+		// We can find it by looking at the speed difference between body1 and the
+		// anchor point.
+
+		// r will be used to find the distance between body1 and the anchor point
+		dVector3 r;
+		if (joint->node[1].body) {
+			// Find joint->anchor2 in global coordinates
+			dVector3 anchor2;
+			dMULTIPLY0_331 (anchor2,joint->node[1].body->posr.R,joint->anchor2);
+
+			r[0] = joint->node[0].body->posr.pos[0] - anchor2[0];
+			r[1] = joint->node[0].body->posr.pos[1] - anchor2[1];
+			r[2] = joint->node[0].body->posr.pos[2] - anchor2[2];
+		}
+		else {
+			//N.B. When there is no body 2 the joint->anchor2 is already in
+			//     global coordinates
+			r[0] = joint->node[0].body->posr.pos[0] - joint->anchor2[0];
+			r[1] = joint->node[0].body->posr.pos[1] - joint->anchor2[1];
+			r[2] = joint->node[0].body->posr.pos[2] - joint->anchor2[2];
+		}
+
+		// The body1 can have velocity coming from the rotation of
+		// the rotoide axis. We need to remove this.
+
+		// Take only the angular rotation coming from the rotation
+		// of the rotoide articulation
+		// N.B. Body1 and Body2 should have the same rotation along axis
+		//      other than the rotoide axis.
+		dVector3 angular;
+		dMULTIPLY0_331 (angular,joint->node[0].body->posr.R,joint->axisR1);
+		dReal omega = dDOT(angular, joint->node[0].body->avel);
+		angular[0] *= omega;
+		angular[1] *= omega;
+		angular[2] *= omega;
+
+		// Find the contribution of the angular rotation to the linear speed
+		// N.B. We do vel = r X w instead of vel = w x r to have vel negative
+		//      since we want to remove it from the linear velocity of the body
+		dVector3 lvel1;
+		dCROSS(lvel1, =, r, angular);
+
+		lvel1[0] += joint->node[0].body->lvel[0];
+		lvel1[1] += joint->node[0].body->lvel[1];
+		lvel1[2] += joint->node[0].body->lvel[2];
+
+		// Since we want rate of change along the prismatic axis
+		// get axisP1 in global coordinates and get the component
+		// along this axis only
+		dVector3 axP1;
+		dMULTIPLY0_331 (axP1,joint->node[0].body->posr.R,joint->axisP1);
+		return dDOT(axP1, lvel1);
+	}
+
+	return 0.0;
+}
+
+
+
+static void PRGetInfo1 (dxJointPR *j, dxJoint::Info1 *info)
+{
+  info->m = 4;
+  info->nub = 4;
+
+  bool added = false;
+
+  added = false;
+  // see if the prismatic articulation is powered
+  if (j->limotP.fmax > 0)
+  {
+    added = true;
+    (info->m)++;  // powered needs an extra constraint row
+  }
+
+  // see if we're at a joint limit.
+  j->limotP.limit = 0;
+  if ((j->limotP.lostop > -dInfinity || j->limotP.histop < dInfinity) &&
+      j->limotP.lostop <= j->limotP.histop) {
+    // measure joint position
+    dReal pos = dJointGetPRPosition (j);
+    if (pos <= j->limotP.lostop) {
+      j->limotP.limit = 1;
+      j->limotP.limit_err = pos - j->limotP.lostop;
+      if (!added)
+        (info->m)++;
+    }
+
+    if (pos >= j->limotP.histop) {
+      j->limotP.limit = 2;
+      j->limotP.limit_err = pos - j->limotP.histop;
+      if (!added)
+        (info->m)++;
+    }
+  }
+
+}
+
+
+
+static void PRGetInfo2 (dxJointPR *joint, dxJoint::Info2 *info)
+{
+  int s = info->rowskip;
+  int s2= 2*s;
+  int s3= 3*s;
+  int s4= 4*s;
+
+  dReal k = info->fps * info->erp;
+
+
+  dVector3 q;  // plane space of axP and after that axR
+
+  // pull out pos and R for both bodies. also get the `connection'
+  // vector pos2-pos1.
+
+  dReal *pos1,*pos2,*R1,*R2;
+  pos1 = joint->node[0].body->posr.pos;
+  R1 = joint->node[0].body->posr.R;
+  if (joint->node[1].body) {
+    pos2 = joint->node[1].body->posr.pos;
+    R2 = joint->node[1].body->posr.R;
+  }
+  else {
+   //     pos2 = 0; // N.B. We can do that to be safe but it is no necessary
+   //     R2 = 0;   // N.B. We can do that to be safe but it is no necessary
+  }
+
+
+  dVector3 axP; // Axis of the prismatic joint in global frame
+  dMULTIPLY0_331 (axP, R1, joint->axisP1);
+
+  // distance between the body1 and the anchor2 in global frame
+  // Calculated in the same way as the offset
+  dVector3 dist;
+
+  if (joint->node[1].body)
+  {
+    dMULTIPLY0_331 (dist, R2, joint->anchor2);
+    dist[0] += pos2[0] - pos1[0];
+    dist[1] += pos2[1] - pos1[1];
+    dist[2] += pos2[2] - pos1[2];
+  }
+  else {
+    dist[0] = joint->anchor2[0] - pos1[0];
+    dist[1] = joint->anchor2[1] - pos1[1];
+    dist[2] = joint->anchor2[2] - pos1[2];
+  }
+
+
+  // ======================================================================
+  // Work on the Rotoide part (i.e. row 0, 1 and maybe 4 if rotoide powered
+
+  // Set the two rotoide rows. The rotoide axis should be the only unconstrained
+  // rotational axis, the angular velocity of the two bodies perpendicular to
+  // the rotoide axis should be equal. Thus the constraint equations are
+  //    p*w1 - p*w2 = 0
+  //    q*w1 - q*w2 = 0
+  // where p and q are unit vectors normal to the rotoide axis, and w1 and w2
+  // are the angular velocity vectors of the two bodies.
+  dVector3 ax1;
+  dMULTIPLY0_331 (ax1, joint->node[0].body->posr.R, joint->axisR1);
+  dCROSS(q , =, ax1, axP);
+
+  info->J1a[0] = axP[0];
+  info->J1a[1] = axP[1];
+  info->J1a[2] = axP[2];
+  info->J1a[s+0] = q[0];
+  info->J1a[s+1] = q[1];
+  info->J1a[s+2] = q[2];
+
+  if (joint->node[1].body) {
+    info->J2a[0] = -axP[0];
+    info->J2a[1] = -axP[1];
+    info->J2a[2] = -axP[2];
+    info->J2a[s+0] = -q[0];
+    info->J2a[s+1] = -q[1];
+    info->J2a[s+2] = -q[2];
+  }
+
+
+  // Compute the right hand side of the constraint equation set. Relative
+  // body velocities along p and q to bring the rotoide back into alignment.
+  // ax1,ax2 are the unit length rotoide axes of body1 and body2 in world frame.
+  // We need to rotate both bodies along the axis u = (ax1 x ax2).
+  // if `theta' is the angle between ax1 and ax2, we need an angular velocity
+  // along u to cover angle erp*theta in one step :
+  //   |angular_velocity| = angle/time = erp*theta / stepsize
+  //                      = (erp*fps) * theta
+  //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+  //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+  // ...as ax1 and ax2 are unit length. if theta is smallish,
+  // theta ~= sin(theta), so
+  //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+  // ax1 x ax2 is in the plane space of ax1, so we project the angular
+  // velocity to p and q to find the right hand side.
+
+  dVector3 ax2;
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (ax2, R2, joint->axisR2);
+  }
+  else {
+    ax2[0] = joint->axisR2[0];
+    ax2[1] = joint->axisR2[1];
+    ax2[2] = joint->axisR2[2];
+  }
+
+  dVector3 b;
+  dCROSS (b,=,ax1, ax2);
+  info->c[0] = k * dDOT(b, axP);
+  info->c[1] = k * dDOT(b, q);
+
+
+
+  // ==========================
+  // Work on the Prismatic part (i.e row 2,3 and 4 if only the prismatic is powered
+  // or 5 if rotoide and prismatic powered
+
+  // two rows. we want: vel2 = vel1 + w1 x c ... but this would
+  // result in three equations, so we project along the planespace vectors
+  // so that sliding along the prismatic axis is disregarded. for symmetry we
+  // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2.
+
+  // p1 + R1 dist' = p2 + R2 anchor2' ## OLD ## p1 + R1 anchor1' = p2 + R2 dist'
+  // v1 + w1 x R1 dist' + v_p = v2 + w2 x R2 anchor2'## OLD  v1 + w1 x R1 anchor1' = v2 + w2 x R2 dist' + v_p
+  // v_p is speed of prismatic joint (i.e. elongation rate)
+  // Since the constraints are perpendicular to v_p we have:
+  // p dot v_p = 0 and q dot v_p = 0
+  // ax1 dot ( v1 + w1 x dist = v2 + w2 x anchor2 )
+  // q dot ( v1 + w1 x dist = v2 + w2 x anchor2 )
+  // ==
+  // ax1 . v1 + ax1 . w1 x dist = ax1 . v2 + ax1 . w2 x anchor2 ## OLD ## ax1 . v1 + ax1 . w1 x anchor1 = ax1 . v2 + ax1 . w2 x dist
+  // since a . (b x c) = - b . (a x c) = - (a x c) . b
+  // and a x b = - b x a
+  // ax1 . v1 - ax1 x dist . w1 - ax1 . v2 - (- ax1 x anchor2 . w2) = 0
+  // ax1 . v1 + dist x ax1 . w1 - ax1 . v2 - anchor2 x ax1 . w2 = 0
+  // Coeff for 1er line of: J1l => ax1, J2l => -ax1
+  // Coeff for 2er line of: J1l => q, J2l => -q
+  // Coeff for 1er line of: J1a => dist x ax1, J2a => - anchor2 x ax1
+  // Coeff for 2er line of: J1a => dist x q,   J2a => - anchor2 x q
+
+
+	dCROSS ((info->J1a)+s2, = , dist, ax1);
+
+	dCROSS ((info->J1a)+s3, = , dist, q);
+
+
+  info->J1l[s2+0] = ax1[0];
+	info->J1l[s2+1] = ax1[1];
+	info->J1l[s2+2] = ax1[2];
+
+  info->J1l[s3+0] = q[0];
+	info->J1l[s3+1] = q[1];
+	info->J1l[s3+2] = q[2];
+
+  if (joint->node[1].body) {
+    dVector3 anchor2;
+
+    // Calculate anchor2 in world coordinate
+    dMULTIPLY0_331 (anchor2, R2, joint->anchor2);
+
+		// ax2 x anchor2 instead of anchor2 x ax2 since we want the negative value
+		dCROSS ((info->J2a)+s2, = , ax2, anchor2); // since ax1 == ax2
+
+		// The cross product is in reverse order since we want the negative value
+		dCROSS ((info->J2a)+s3, = , q, anchor2);
+
+		info->J2l[s2+0] = -ax1[0];
+		info->J2l[s2+1] = -ax1[1];
+		info->J2l[s2+2] = -ax1[2];
+
+    info->J2l[s3+0] = -q[0];
+		info->J2l[s3+1] = -q[1];
+		info->J2l[s3+2] = -q[2];
+  }
+
+
+  // We want to make correction for motion not in the line of the axisP
+  // We calculate the displacement w.r.t. the anchor pt.
+  //
+  // compute the elements 2 and 3 of right hand side.
+  // we want to align the offset point (in body 2's frame) with the center of body 1.
+  // The position should be the same when we are not along the prismatic axis
+  dVector3 err;
+  dMULTIPLY0_331 (err, R1, joint->offset);
+  err[0] += dist[0];
+  err[1] += dist[1];
+  err[2] += dist[2];
+  info->c[2] = k * dDOT(ax1, err);
+  info->c[3] = k * dDOT(q, err);
+
+  // Here we can't use addLimot because of some assumption in the function
+  int powered = joint->limotP.fmax > 0;
+  if (powered || joint->limotP.limit) {
+    info->J1l[s4+0] = axP[0];
+    info->J1l[s4+1] = axP[1];
+    info->J1l[s4+2] = axP[2];
+    if (joint->node[1].body) {
+      info->J2l[s4+0] = -axP[0];
+      info->J2l[s4+1] = -axP[1];
+      info->J2l[s4+2] = -axP[2];
+    }
+    // linear limot torque decoupling step:
+    //
+    // if this is a linear limot (e.g. from a slider), we have to be careful
+    // that the linear constraint forces (+/- ax1) applied to the two bodies
+    // do not create a torque couple. in other words, the points that the
+    // constraint force is applied at must lie along the same ax1 axis.
+    // a torque couple will result in powered or limited slider-jointed free
+    // bodies from gaining angular momentum.
+    // the solution used here is to apply the constraint forces at the point
+    // halfway between the body centers. there is no penalty (other than an
+    // extra tiny bit of computation) in doing this adjustment. note that we
+    // only need to do this if the constraint connects two bodies.
+
+		dVector3 ltd;  // Linear Torque Decoupling vector (a torque)
+    if (joint->node[1].body) {
+			dVector3 c;
+      c[0]=REAL(0.5)*(joint->node[1].body->posr.pos[0]-joint->node[0].body->posr.pos[0]);
+      c[1]=REAL(0.5)*(joint->node[1].body->posr.pos[1]-joint->node[0].body->posr.pos[1]);
+      c[2]=REAL(0.5)*(joint->node[1].body->posr.pos[2]-joint->node[0].body->posr.pos[2]);
+			dReal val = dDOT(q, c);
+			c[0] -= val * c[0];
+			c[1] -= val * c[1];
+			c[2] -= val * c[2];
+
+      dCROSS (ltd,=,c,axP);
+      info->J1a[s4+0] = ltd[0];
+      info->J1a[s4+1] = ltd[1];
+      info->J1a[s4+2] = ltd[2];
+      info->J2a[s4+0] = ltd[0];
+      info->J2a[s4+1] = ltd[1];
+      info->J2a[s4+2] = ltd[2];
+    }
+
+    // if we're limited low and high simultaneously, the joint motor is
+    // ineffective
+    if (joint->limotP.limit && (joint->limotP.lostop == joint->limotP.histop))
+      powered = 0;
+
+    int row = 4;
+    if (powered) {
+      info->cfm[row] = joint->limotP.normal_cfm;
+      if (!joint->limotP.limit) {
+        info->c[row] = joint->limotP.vel;
+        info->lo[row] = -joint->limotP.fmax;
+        info->hi[row] = joint->limotP.fmax;
+      }
+      else {
+        // the joint is at a limit, AND is being powered. if the joint is
+        // being powered into the limit then we apply the maximum motor force
+        // in that direction, because the motor is working against the
+        // immovable limit. if the joint is being powered away from the limit
+        // then we have problems because actually we need *two* lcp
+        // constraints to handle this case. so we fake it and apply some
+        // fraction of the maximum force. the fraction to use can be set as
+        // a fudge factor.
+
+        dReal fm = joint->limotP.fmax;
+        dReal vel = joint->limotP.vel;
+        int limit = joint->limotP.limit;
+        if ((vel > 0) || (vel==0 && limit==2)) fm = -fm;
+
+        // if we're powering away from the limit, apply the fudge factor
+        if ((limit==1 && vel > 0) || (limit==2 && vel < 0))
+          fm *= joint->limotP.fudge_factor;
+
+
+        dBodyAddForce (joint->node[0].body,-fm*axP[0],-fm*axP[1],-fm*axP[2]);
+
+				if (joint->node[1].body) {
+					dBodyAddForce (joint->node[1].body,fm*axP[0],fm*axP[1],fm*axP[2]);
+
+					// linear limot torque decoupling step: refer to above discussion
+					dBodyAddTorque (joint->node[0].body,-fm*ltd[0],-fm*ltd[1],
+													-fm*ltd[2]);
+					dBodyAddTorque (joint->node[1].body,-fm*ltd[0],-fm*ltd[1],
+													-fm*ltd[2]);
+				}
+      }
+    }
+
+		if (joint->limotP.limit) {
+      dReal k = info->fps * joint->limotP.stop_erp;
+      info->c[row] = -k * joint->limotP.limit_err;
+      info->cfm[row] = joint->limotP.stop_cfm;
+
+      if (joint->limotP.lostop == joint->limotP.histop) {
+				// limited low and high simultaneously
+				info->lo[row] = -dInfinity;
+				info->hi[row] = dInfinity;
+      }
+      else {
+        if (joint->limotP.limit == 1) {
+					// low limit
+					info->lo[row] = 0;
+					info->hi[row] = dInfinity;
+				}
+				else {
+					// high limit
+					info->lo[row] = -dInfinity;
+					info->hi[row] = 0;
+				}
+
+				// deal with bounce
+        if (joint->limotP.bounce > 0) {
+					// calculate joint velocity
+          dReal vel;
+          vel = dDOT(joint->node[0].body->lvel, axP);
+          if (joint->node[1].body)
+            vel -= dDOT(joint->node[1].body->lvel, axP);
+
+					// only apply bounce if the velocity is incoming, and if the
+					// resulting c[] exceeds what we already have.
+          if (joint->limotP.limit == 1) {
+						// low limit
+						if (vel < 0) {
+              dReal newc = -joint->limotP.bounce * vel;
+							if (newc > info->c[row]) info->c[row] = newc;
+						}
+					}
+					else {
+						// high limit - all those computations are reversed
+						if (vel > 0) {
+              dReal newc = -joint->limotP.bounce * vel;
+							if (newc < info->c[row]) info->c[row] = newc;
+						}
+					}
+				}
+      }
+    }
+  }
+}
+
+
+// compute initial relative rotation body1 -> body2, or env -> body1
+static void PRComputeInitialRelativeRotation (dxJointPR *joint)
+{
+  if (joint->node[0].body) {
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+    }
+    else {
+      // set joint->qrel to the transpose of the first body q
+      joint->qrel[0] = joint->node[0].body->q[0];
+      for (int i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+      // WARNING do we need the - in -joint->node[0].body->q[i]; or not
+    }
+  }
+}
+
+void dJointSetPRAnchor (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+
+  dVector3 dummy;
+  setAnchors (joint,x,y,z,dummy,joint->anchor2);
+}
+
+
+void dJointSetPRAxis1 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a  Prismatic and Rotoide");
+
+  setAxes (joint,x,y,z,joint->axisP1, 0);
+
+  PRComputeInitialRelativeRotation (joint);
+
+  // compute initial relative rotation body1 -> body2, or env -> body1
+  // also compute distance between anchor of body1 w.r.t center of body 2
+  dVector3 c;
+  if (joint->node[1].body) {
+    dVector3 anchor2;
+    dMULTIPLY0_331 (anchor2,joint->node[1].body->posr.R, joint->anchor2);
+
+    c[0] = ( joint->node[1].body->posr.pos[0] + anchor2[0] -
+             joint->node[0].body->posr.pos[0] );
+    c[1] = ( joint->node[1].body->posr.pos[1] + anchor2[1] -
+             joint->node[0].body->posr.pos[1] );
+    c[2] = ( joint->node[1].body->posr.pos[2] + anchor2[2] -
+             joint->node[0].body->posr.pos[2] );
+  }
+  else if (joint->node[0].body) {
+    c[0] = joint->anchor2[0] - joint->node[0].body->posr.pos[0];
+    c[1] = joint->anchor2[1] - joint->node[0].body->posr.pos[1];
+    c[2] = joint->anchor2[2] - joint->node[0].body->posr.pos[2];
+  }
+	else
+	{
+    joint->offset[0] = joint->anchor2[0];
+		joint->offset[1] = joint->anchor2[1];
+		joint->offset[2] = joint->anchor2[2];
+
+		return;
+	}
+
+
+  dMULTIPLY1_331 (joint->offset,joint->node[0].body->posr.R,c);
+}
+
+
+void dJointSetPRAxis2 (dJointID j, dReal x, dReal y, dReal z)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+  setAxes (joint,x,y,z,joint->axisR1,joint->axisR2);
+  PRComputeInitialRelativeRotation (joint);
+}
+
+
+void dJointSetPRParam (dJointID j, int parameter, dReal value)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+  if ((parameter & 0xff00) == 0x100) {
+    joint->limotR.set (parameter,value);
+  }
+  else {
+    joint->limotP.set (parameter & 0xff,value);
+  }
+}
+
+void dJointGetPRAnchor (dJointID j, dVector3 result)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+
+  if (joint->node[1].body)
+    getAnchor2 (joint,result,joint->anchor2);
+  else
+  {
+    result[0] = joint->anchor2[0];
+    result[1] = joint->anchor2[1];
+    result[2] = joint->anchor2[2];
+  }
+
+}
+
+void dJointGetPRAxis1 (dJointID j, dVector3 result)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+  getAxis(joint, result, joint->axisP1);
+}
+
+void dJointGetPRAxis2 (dJointID j, dVector3 result)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(result,"bad result argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+  getAxis(joint, result, joint->axisR1);
+}
+
+dReal dJointGetPRParam (dJointID j, int parameter)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not Prismatic and Rotoide");
+  if ((parameter & 0xff00) == 0x100) {
+    return joint->limotR.get (parameter & 0xff);
+  }
+	else {
+		return joint->limotP.get (parameter);
+	}
+}
+
+void dJointAddPRTorque (dJointID j, dReal torque)
+{
+  dxJointPR* joint = (dxJointPR*)j;
+  dVector3 axis;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dPR_vtable,"joint is not a Prismatic and Rotoide");
+
+  if (joint->flags & dJOINT_REVERSE)
+    torque = -torque;
+
+  getAxis (joint,axis,joint->axisR1);
+  axis[0] *= torque;
+  axis[1] *= torque;
+  axis[2] *= torque;
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body, axis[0], axis[1], axis[2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axis[0], -axis[1], -axis[2]);
+}
+
+
+dxJoint::Vtable __dPR_vtable = {
+  sizeof(dxJointPR),
+  (dxJoint::init_fn*) PRInit,
+  (dxJoint::getInfo1_fn*) PRGetInfo1,
+  (dxJoint::getInfo2_fn*) PRGetInfo2,
+  dJointTypePR
+};
+
+
+//****************************************************************************
+// angular motor
+
+static void amotorInit (dxJointAMotor *j)
+{
+  int i;
+  j->num = 0;
+  j->mode = dAMotorUser;
+  for (i=0; i<3; i++) {
+    j->rel[i] = 0;
+    dSetZero (j->axis[i],4);
+    j->limot[i].init (j->world);
+    j->angle[i] = 0;
+  }
+  dSetZero (j->reference1,4);
+  dSetZero (j->reference2,4);
+}
+
+
+// compute the 3 axes in global coordinates
+
+static void amotorComputeGlobalAxes (dxJointAMotor *joint, dVector3 ax[3])
+{
+  if (joint->mode == dAMotorEuler) {
+    // special handling for euler mode
+    dMULTIPLY0_331 (ax[0],joint->node[0].body->posr.R,joint->axis[0]);
+    if (joint->node[1].body) {
+      dMULTIPLY0_331 (ax[2],joint->node[1].body->posr.R,joint->axis[2]);
+    }
+    else {
+      ax[2][0] = joint->axis[2][0];
+      ax[2][1] = joint->axis[2][1];
+      ax[2][2] = joint->axis[2][2];
+    }
+    dCROSS (ax[1],=,ax[2],ax[0]);
+    dNormalize3 (ax[1]);
+  }
+  else {
+    for (int i=0; i < joint->num; i++) {
+      if (joint->rel[i] == 1) {
+	// relative to b1
+	dMULTIPLY0_331 (ax[i],joint->node[0].body->posr.R,joint->axis[i]);
+      }
+      else if (joint->rel[i] == 2) {
+	// relative to b2
+	if (joint->node[1].body) {   // jds: don't assert, just ignore
+	        dMULTIPLY0_331 (ax[i],joint->node[1].body->posr.R,joint->axis[i]);
+        }
+      }
+      else {
+	// global - just copy it
+	ax[i][0] = joint->axis[i][0];
+	ax[i][1] = joint->axis[i][1];
+	ax[i][2] = joint->axis[i][2];
+      }
+    }
+  }
+}
+
+
+static void amotorComputeEulerAngles (dxJointAMotor *joint, dVector3 ax[3])
+{
+  // assumptions:
+  //   global axes already calculated --> ax
+  //   axis[0] is relative to body 1 --> global ax[0]
+  //   axis[2] is relative to body 2 --> global ax[2]
+  //   ax[1] = ax[2] x ax[0]
+  //   original ax[0] and ax[2] are perpendicular
+  //   reference1 is perpendicular to ax[0] (in body 1 frame)
+  //   reference2 is perpendicular to ax[2] (in body 2 frame)
+  //   all ax[] and reference vectors are unit length
+
+  // calculate references in global frame
+  dVector3 ref1,ref2;
+  dMULTIPLY0_331 (ref1,joint->node[0].body->posr.R,joint->reference1);
+  if (joint->node[1].body) {
+    dMULTIPLY0_331 (ref2,joint->node[1].body->posr.R,joint->reference2);
+  }
+  else {
+    ref2[0] = joint->reference2[0];
+    ref2[1] = joint->reference2[1];
+    ref2[2] = joint->reference2[2];
+  }
+
+  // get q perpendicular to both ax[0] and ref1, get first euler angle
+  dVector3 q;
+  dCROSS (q,=,ax[0],ref1);
+  joint->angle[0] = -dAtan2 (dDOT(ax[2],q),dDOT(ax[2],ref1));
+
+  // get q perpendicular to both ax[0] and ax[1], get second euler angle
+  dCROSS (q,=,ax[0],ax[1]);
+  joint->angle[1] = -dAtan2 (dDOT(ax[2],ax[0]),dDOT(ax[2],q));
+
+  // get q perpendicular to both ax[1] and ax[2], get third euler angle
+  dCROSS (q,=,ax[1],ax[2]);
+  joint->angle[2] = -dAtan2 (dDOT(ref2,ax[1]), dDOT(ref2,q));
+}
+
+
+// set the reference vectors as follows:
+//   * reference1 = current axis[2] relative to body 1
+//   * reference2 = current axis[0] relative to body 2
+// this assumes that:
+//    * axis[0] is relative to body 1
+//    * axis[2] is relative to body 2
+
+static void amotorSetEulerReferenceVectors (dxJointAMotor *j)
+{
+  if (j->node[0].body && j->node[1].body) {
+    dVector3 r;		// axis[2] and axis[0] in global coordinates
+    dMULTIPLY0_331 (r,j->node[1].body->posr.R,j->axis[2]);
+    dMULTIPLY1_331 (j->reference1,j->node[0].body->posr.R,r);
+    dMULTIPLY0_331 (r,j->node[0].body->posr.R,j->axis[0]);
+    dMULTIPLY1_331 (j->reference2,j->node[1].body->posr.R,r);
+  }
+
+  else {   // jds
+    // else if (j->node[0].body) {
+    // dMULTIPLY1_331 (j->reference1,j->node[0].body->posr.R,j->axis[2]);
+    // dMULTIPLY0_331 (j->reference2,j->node[0].body->posr.R,j->axis[0]);
+
+    // We want to handle angular motors attached to passive geoms
+    dVector3 r;		// axis[2] and axis[0] in global coordinates
+    r[0] = j->axis[2][0]; r[1] = j->axis[2][1]; r[2] = j->axis[2][2]; r[3] = j->axis[2][3];
+    dMULTIPLY1_331 (j->reference1,j->node[0].body->posr.R,r);
+    dMULTIPLY0_331 (r,j->node[0].body->posr.R,j->axis[0]);
+    j->reference2[0] += r[0]; j->reference2[1] += r[1];
+    j->reference2[2] += r[2]; j->reference2[3] += r[3];
+  }
+}
+
+
+static void amotorGetInfo1 (dxJointAMotor *j, dxJoint::Info1 *info)
+{
+  info->m = 0;
+  info->nub = 0;
+
+  // compute the axes and angles, if in euler mode
+  if (j->mode == dAMotorEuler) {
+    dVector3 ax[3];
+    amotorComputeGlobalAxes (j,ax);
+    amotorComputeEulerAngles (j,ax);
+  }
+
+  // see if we're powered or at a joint limit for each axis
+  for (int i=0; i < j->num; i++) {
+    if (j->limot[i].testRotationalLimit (j->angle[i]) ||
+	j->limot[i].fmax > 0) {
+      info->m++;
+    }
+  }
+}
+
+
+static void amotorGetInfo2 (dxJointAMotor *joint, dxJoint::Info2 *info)
+{
+  int i;
+
+  // compute the axes (if not global)
+  dVector3 ax[3];
+  amotorComputeGlobalAxes (joint,ax);
+
+  // in euler angle mode we do not actually constrain the angular velocity
+  // along the axes axis[0] and axis[2] (although we do use axis[1]) :
+  //
+  //    to get			constrain w2-w1 along		...not
+  //    ------			---------------------		------
+  //    d(angle[0])/dt = 0	ax[1] x ax[2]			ax[0]
+  //    d(angle[1])/dt = 0	ax[1]
+  //    d(angle[2])/dt = 0	ax[0] x ax[1]			ax[2]
+  //
+  // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+  // to prove the result for angle[0], write the expression for angle[0] from
+  // GetInfo1 then take the derivative. to prove this for angle[2] it is
+  // easier to take the euler rate expression for d(angle[2])/dt with respect
+  // to the components of w and set that to 0.
+
+  dVector3 *axptr[3];
+  axptr[0] = &ax[0];
+  axptr[1] = &ax[1];
+  axptr[2] = &ax[2];
+
+  dVector3 ax0_cross_ax1;
+  dVector3 ax1_cross_ax2;
+  if (joint->mode == dAMotorEuler) {
+    dCROSS (ax0_cross_ax1,=,ax[0],ax[1]);
+    axptr[2] = &ax0_cross_ax1;
+    dCROSS (ax1_cross_ax2,=,ax[1],ax[2]);
+    axptr[0] = &ax1_cross_ax2;
+  }
+
+  int row=0;
+  for (i=0; i < joint->num; i++) {
+    row += joint->limot[i].addLimot (joint,info,row,*(axptr[i]),1);
+  }
+}
+
+
+void dJointSetAMotorNumAxes (dJointID j, int num)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint && num >= 0 && num <= 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (joint->mode == dAMotorEuler) {
+    joint->num = 3;
+  }
+  else {
+    if (num < 0) num = 0;
+    if (num > 3) num = 3;
+    joint->num = num;
+  }
+}
+
+
+void dJointSetAMotorAxis (dJointID j, int anum, int rel, dReal x, dReal y, dReal z)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  dUASSERT(!(!joint->node[1].body &&  (joint->flags & dJOINT_REVERSE) && rel == 1),"no first body, can't set axis rel=1");
+  dUASSERT(!(!joint->node[1].body && !(joint->flags & dJOINT_REVERSE) && rel == 2),"no second body, can't set axis rel=2");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+
+  // adjust rel to match the internal body order
+  if (!joint->node[1].body && rel==2) rel = 1;
+
+  joint->rel[anum] = rel;
+
+  // x,y,z is always in global coordinates regardless of rel, so we may have
+  // to convert it to be relative to a body
+  dVector3 r;
+  r[0] = x;
+  r[1] = y;
+  r[2] = z;
+  r[3] = 0;
+  if (rel > 0) {
+    if (rel==1) {
+      dMULTIPLY1_331 (joint->axis[anum],joint->node[0].body->posr.R,r);
+    }
+    else {
+      // don't assert; handle the case of attachment to a bodiless geom
+      if (joint->node[1].body) {   // jds
+      dMULTIPLY1_331 (joint->axis[anum],joint->node[1].body->posr.R,r);
+    }
+      else {
+	joint->axis[anum][0] = r[0]; joint->axis[anum][1] = r[1];
+	joint->axis[anum][2] = r[2]; joint->axis[anum][3] = r[3];
+      }
+    }
+  }
+  else {
+    joint->axis[anum][0] = r[0];
+    joint->axis[anum][1] = r[1];
+    joint->axis[anum][2] = r[2];
+  }
+  dNormalize3 (joint->axis[anum]);
+  if (joint->mode == dAMotorEuler) amotorSetEulerReferenceVectors (joint);
+}
+
+
+void dJointSetAMotorAngle (dJointID j, int anum, dReal angle)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (joint->mode == dAMotorUser) {
+    if (anum < 0) anum = 0;
+    if (anum > 3) anum = 3;
+    joint->angle[anum] = angle;
+  }
+}
+
+
+void dJointSetAMotorParam (dJointID j, int parameter, dReal value)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  int anum = parameter >> 8;
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  parameter &= 0xff;
+  joint->limot[anum].set (parameter, value);
+}
+
+
+void dJointSetAMotorMode (dJointID j, int mode)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  joint->mode = mode;
+  if (joint->mode == dAMotorEuler) {
+    joint->num = 3;
+    amotorSetEulerReferenceVectors (joint);
+  }
+}
+
+
+int dJointGetAMotorNumAxes (dJointID j)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  return joint->num;
+}
+
+
+void dJointGetAMotorAxis (dJointID j, int anum, dVector3 result)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  if (joint->rel[anum] > 0) {
+    if (joint->rel[anum]==1) {
+      dMULTIPLY0_331 (result,joint->node[0].body->posr.R,joint->axis[anum]);
+    }
+    else {
+      if (joint->node[1].body) {   // jds
+      dMULTIPLY0_331 (result,joint->node[1].body->posr.R,joint->axis[anum]);
+      }
+      else {
+	result[0] = joint->axis[anum][0]; result[1] = joint->axis[anum][1];
+	result[2] = joint->axis[anum][2]; result[3] = joint->axis[anum][3];
+      }
+    }
+  }
+  else {
+    result[0] = joint->axis[anum][0];
+    result[1] = joint->axis[anum][1];
+    result[2] = joint->axis[anum][2];
+  }
+}
+
+
+int dJointGetAMotorAxisRel (dJointID j, int anum)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  return joint->rel[anum];
+}
+
+
+dReal dJointGetAMotorAngle (dJointID j, int anum)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  if (anum < 0) anum = 0;
+  if (anum > 3) anum = 3;
+  return joint->angle[anum];
+}
+
+
+dReal dJointGetAMotorAngleRate (dJointID j, int anum)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  // @@@
+  dDebug (0,"not yet implemented");
+  return 0;
+}
+
+
+dReal dJointGetAMotorParam (dJointID j, int parameter)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  int anum = parameter >> 8;
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  parameter &= 0xff;
+  return joint->limot[anum].get (parameter);
+}
+
+
+int dJointGetAMotorMode (dJointID j)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+  return joint->mode;
+}
+
+
+void dJointAddAMotorTorques (dJointID j, dReal torque1, dReal torque2, dReal torque3)
+{
+  dxJointAMotor* joint = (dxJointAMotor*)j;
+  dVector3 axes[3];
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__damotor_vtable,"joint is not an amotor");
+
+  if (joint->num == 0)
+    return;
+  dUASSERT((joint->flags & dJOINT_REVERSE) == 0, "dJointAddAMotorTorques not yet implemented for reverse AMotor joints");
+
+  amotorComputeGlobalAxes (joint,axes);
+  axes[0][0] *= torque1;
+  axes[0][1] *= torque1;
+  axes[0][2] *= torque1;
+  if (joint->num >= 2) {
+    axes[0][0] += axes[1][0] * torque2;
+    axes[0][1] += axes[1][1] * torque2;
+    axes[0][2] += axes[1][2] * torque2;
+    if (joint->num >= 3) {
+      axes[0][0] += axes[2][0] * torque3;
+      axes[0][1] += axes[2][1] * torque3;
+      axes[0][2] += axes[2][2] * torque3;
+    }
+  }
+
+  if (joint->node[0].body != 0)
+    dBodyAddTorque (joint->node[0].body,axes[0][0],axes[0][1],axes[0][2]);
+  if (joint->node[1].body != 0)
+    dBodyAddTorque(joint->node[1].body, -axes[0][0], -axes[0][1], -axes[0][2]);
+}
+
+
+dxJoint::Vtable __damotor_vtable = {
+  sizeof(dxJointAMotor),
+  (dxJoint::init_fn*) amotorInit,
+  (dxJoint::getInfo1_fn*) amotorGetInfo1,
+  (dxJoint::getInfo2_fn*) amotorGetInfo2,
+  dJointTypeAMotor};
+
+
+
+//****************************************************************************
+// lmotor joint
+static void lmotorInit (dxJointLMotor *j)
+{
+  int i;
+  j->num = 0;
+  for (i=0;i<3;i++) {
+    dSetZero(j->axis[i],4);
+    j->limot[i].init(j->world);
+  }
+}
+
+static void lmotorComputeGlobalAxes (dxJointLMotor *joint, dVector3 ax[3])
+{
+  for (int i=0; i< joint->num; i++) {
+    if (joint->rel[i] == 1) {
+      dMULTIPLY0_331 (ax[i],joint->node[0].body->posr.R,joint->axis[i]);
+    }
+    else if (joint->rel[i] == 2) {
+      if (joint->node[1].body) {   // jds: don't assert, just ignore
+        dMULTIPLY0_331 (ax[i],joint->node[1].body->posr.R,joint->axis[i]);
+      }
+    } else {
+      ax[i][0] = joint->axis[i][0];
+      ax[i][1] = joint->axis[i][1];
+      ax[i][2] = joint->axis[i][2];
+    }
+  }
+}
+
+static void lmotorGetInfo1 (dxJointLMotor *j, dxJoint::Info1 *info)
+{
+  info->m = 0;
+  info->nub = 0;
+  for (int i=0; i < j->num; i++) {
+    if (j->limot[i].fmax > 0) {
+      info->m++;
+    }
+  }
+}
+
+static void lmotorGetInfo2 (dxJointLMotor *joint, dxJoint::Info2 *info)
+{
+  int row=0;
+  dVector3 ax[3];
+  lmotorComputeGlobalAxes(joint, ax);
+
+  for (int i=0;i<joint->num;i++) {
+    row += joint->limot[i].addLimot(joint,info,row,ax[i], 0);
+  }
+}
+
+void dJointSetLMotorAxis (dJointID j, int anum, int rel, dReal x, dReal y, dReal z)
+{
+  dxJointLMotor* joint = (dxJointLMotor*)j;
+//for now we are ignoring rel!
+  dAASSERT(joint && anum >= 0 && anum <= 2 && rel >= 0 && rel <= 2);
+  dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+
+  if (!joint->node[1].body && rel==2) rel = 1; //ref 1
+
+  joint->rel[anum] = rel;
+
+  dVector3 r;
+  r[0] = x;
+  r[1] = y;
+  r[2] = z;
+  r[3] = 0;
+  if (rel > 0) {
+    if (rel==1) {
+      dMULTIPLY1_331 (joint->axis[anum],joint->node[0].body->posr.R,r);
+	} else {
+	  //second body has to exists thanks to ref 1 line
+      dMULTIPLY1_331 (joint->axis[anum],joint->node[1].body->posr.R,r);
+	}
+  } else {
+    joint->axis[anum][0] = r[0];
+    joint->axis[anum][1] = r[1];
+    joint->axis[anum][2] = r[2];
+  }
+
+  dNormalize3 (joint->axis[anum]);
+}
+
+void dJointSetLMotorNumAxes (dJointID j, int num)
+{
+  dxJointLMotor* joint = (dxJointLMotor*)j;
+  dAASSERT(joint && num >= 0 && num <= 3);
+  dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
+  if (num < 0) num = 0;
+  if (num > 3) num = 3;
+  joint->num = num;
+}
+
+void dJointSetLMotorParam (dJointID j, int parameter, dReal value)
+{
+  dxJointLMotor* joint = (dxJointLMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
+  int anum = parameter >> 8;
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  parameter &= 0xff;
+  joint->limot[anum].set (parameter, value);
+}
+
+int dJointGetLMotorNumAxes (dJointID j)
+{
+  dxJointLMotor* joint = (dxJointLMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
+  return joint->num;
+}
+
+
+void dJointGetLMotorAxis (dJointID j, int anum, dVector3 result)
+{
+  dxJointLMotor* joint = (dxJointLMotor*)j;
+  dAASSERT(joint && anum >= 0 && anum < 3);
+  dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  result[0] = joint->axis[anum][0];
+  result[1] = joint->axis[anum][1];
+  result[2] = joint->axis[anum][2];
+}
+
+dReal dJointGetLMotorParam (dJointID j, int parameter)
+{
+  dxJointLMotor* joint = (dxJointLMotor*)j;
+  dAASSERT(joint);
+  dUASSERT(joint->vtable == &__dlmotor_vtable,"joint is not an lmotor");
+  int anum = parameter >> 8;
+  if (anum < 0) anum = 0;
+  if (anum > 2) anum = 2;
+  parameter &= 0xff;
+  return joint->limot[anum].get (parameter);
+}
+
+dxJoint::Vtable __dlmotor_vtable = {
+  sizeof(dxJointLMotor),
+	(dxJoint::init_fn*) lmotorInit,
+	(dxJoint::getInfo1_fn*) lmotorGetInfo1,
+	(dxJoint::getInfo2_fn*) lmotorGetInfo2,
+	dJointTypeLMotor
+};
+
+
+//****************************************************************************
+// fixed joint
+
+static void fixedInit (dxJointFixed *j)
+{
+  dSetZero (j->offset,4);
+  dSetZero (j->qrel,4);
+  j->erp = j->world->global_erp;
+  j->cfm = j->world->global_cfm;
+}
+
+
+static void fixedGetInfo1 (dxJointFixed *j, dxJoint::Info1 *info)
+{
+  info->m = 6;
+  info->nub = 6;
+}
+
+
+static void fixedGetInfo2 (dxJointFixed *joint, dxJoint::Info2 *info)
+{
+  int s = info->rowskip;
+
+  // Three rows for orientation
+  setFixedOrientation(joint, info, joint->qrel, 3);
+
+  // Three rows for position.
+  // set jacobian
+  info->J1l[0] = 1;
+  info->J1l[s+1] = 1;
+  info->J1l[2*s+2] = 1;
+
+  info->erp = joint->erp;
+  info->cfm[0] = joint->cfm;
+  info->cfm[1] = joint->cfm;
+  info->cfm[2] = joint->cfm;
+
+  dVector3 ofs;
+  dMULTIPLY0_331 (ofs,joint->node[0].body->posr.R,joint->offset);
+  if (joint->node[1].body) {
+    dCROSSMAT (info->J1a,ofs,s,+,-);
+    info->J2l[0] = -1;
+    info->J2l[s+1] = -1;
+    info->J2l[2*s+2] = -1;
+  }
+
+  // set right hand side for the first three rows (linear)
+  dReal k = info->fps * info->erp;
+  if (joint->node[1].body) {
+    for (int j=0; j<3; j++)
+      info->c[j] = k * (joint->node[1].body->posr.pos[j] -
+			joint->node[0].body->posr.pos[j] + ofs[j]);
+  }
+  else {
+    for (int j=0; j<3; j++)
+      info->c[j] = k * (joint->offset[j] - joint->node[0].body->posr.pos[j]);
+  }
+}
+
+
+void dJointSetFixed (dJointID j)
+{
+  dxJointFixed* joint = (dxJointFixed*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not fixed");
+  int i;
+
+  // This code is taken from sJointSetSliderAxis(), we should really put the
+  // common code in its own function.
+  // compute the offset between the bodies
+  if (joint->node[0].body) {
+    if (joint->node[1].body) {
+      dQMultiply1 (joint->qrel,joint->node[0].body->q,joint->node[1].body->q);
+      dReal ofs[4];
+      for (i=0; i<4; i++) ofs[i] = joint->node[0].body->posr.pos[i];
+      for (i=0; i<4; i++) ofs[i] -= joint->node[1].body->posr.pos[i];
+      dMULTIPLY1_331 (joint->offset,joint->node[0].body->posr.R,ofs);
+    }
+    else {
+      // set joint->qrel to the transpose of the first body's q
+      joint->qrel[0] = joint->node[0].body->q[0];
+      for (i=1; i<4; i++) joint->qrel[i] = -joint->node[0].body->q[i];
+      for (i=0; i<4; i++) joint->offset[i] = joint->node[0].body->posr.pos[i];
+    }
+  }
+}
+
+void dxJointFixed::set (int num, dReal value)
+{
+  switch (num) {
+  case dParamCFM:
+    cfm = value;
+    break;
+  case dParamERP:
+    erp = value;
+    break;
+  }
+}
+ 
+
+dReal dxJointFixed::get (int num)
+{
+  switch (num) {
+  case dParamCFM:
+    return cfm;
+  case dParamERP:
+    return erp;
+  default:
+	return 0;
+  }
+}
+
+
+void dJointSetFixedParam (dJointID j, int parameter, dReal value)
+{
+  dxJointFixed* joint = (dxJointFixed*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not a fixed joint");
+  joint->set (parameter,value);
+}
+
+
+dReal dJointGetFixedParam (dJointID j, int parameter)
+{
+  dxJointFixed* joint = (dxJointFixed*)j;
+  dUASSERT(joint,"bad joint argument");
+  dUASSERT(joint->vtable == &__dfixed_vtable,"joint is not a fixed joint");
+  return joint->get (parameter);
+}
+
+
+dxJoint::Vtable __dfixed_vtable = {
+  sizeof(dxJointFixed),
+  (dxJoint::init_fn*) fixedInit,
+  (dxJoint::getInfo1_fn*) fixedGetInfo1,
+  (dxJoint::getInfo2_fn*) fixedGetInfo2,
+  dJointTypeFixed};
+
+//****************************************************************************
+// null joint
+
+static void nullGetInfo1 (dxJointNull *j, dxJoint::Info1 *info)
+{
+  info->m = 0;
+  info->nub = 0;
+}
+
+
+static void nullGetInfo2 (dxJointNull *joint, dxJoint::Info2 *info)
+{
+  dDebug (0,"this should never get called");
+}
+
+
+dxJoint::Vtable __dnull_vtable = {
+  sizeof(dxJointNull),
+  (dxJoint::init_fn*) 0,
+  (dxJoint::getInfo1_fn*) nullGetInfo1,
+  (dxJoint::getInfo2_fn*) nullGetInfo2,
+  dJointTypeNull};
+
+
+
+
+/*
+    This code is part of the Plane2D ODE joint
+    by psero@gmx.de
+    Wed Apr 23 18:53:43 CEST 2003
+
+    Add this code to the file: ode/src/joint.cpp
+*/
+
+
+# define        VoXYZ(v1, o1, x, y, z) \
+                    ( \
+                        (v1)[0] o1 (x), \
+                        (v1)[1] o1 (y), \
+                        (v1)[2] o1 (z)  \
+                    )
+
+static dReal   Midentity[3][3] =
+                {
+                    {   1,  0,  0   },
+                    {   0,  1,  0   },
+                    {   0,  0,  1,  }
+                };
+
+
+
+static void     plane2dInit (dxJointPlane2D *j)
+/*********************************************/
+{
+    /* MINFO ("plane2dInit ()"); */
+    j->motor_x.init (j->world);
+    j->motor_y.init (j->world);
+    j->motor_angle.init (j->world);
+}
+
+
+
+static void     plane2dGetInfo1 (dxJointPlane2D *j, dxJoint::Info1 *info)
+/***********************************************************************/
+{
+  /* MINFO ("plane2dGetInfo1 ()"); */
+
+  info->nub = 3;
+  info->m = 3;
+
+  if (j->motor_x.fmax > 0)
+      j->row_motor_x = info->m ++;
+  if (j->motor_y.fmax > 0)
+      j->row_motor_y = info->m ++;
+  if (j->motor_angle.fmax > 0)
+      j->row_motor_angle = info->m ++;
+}
+
+
+
+static void     plane2dGetInfo2 (dxJointPlane2D *joint, dxJoint::Info2 *info)
+/***************************************************************************/
+{
+    int         r0 = 0,
+                r1 = info->rowskip,
+                r2 = 2 * r1;
+    dReal       eps = info->fps * info->erp;
+
+    /* MINFO ("plane2dGetInfo2 ()"); */
+
+/*
+    v = v1, w = omega1
+    (v2, omega2 not important (== static environment))
+
+    constraint equations:
+        xz = 0
+        wx = 0
+        wy = 0
+
+    <=> ( 0 0 1 ) (vx)   ( 0 0 0 ) (wx)   ( 0 )
+        ( 0 0 0 ) (vy) + ( 1 0 0 ) (wy) = ( 0 )
+        ( 0 0 0 ) (vz)   ( 0 1 0 ) (wz)   ( 0 )
+        J1/J1l           Omega1/J1a
+*/
+
+    // fill in linear and angular coeff. for left hand side:
+
+    VoXYZ (&info->J1l[r0], =, 0, 0, 1);
+    VoXYZ (&info->J1l[r1], =, 0, 0, 0);
+    VoXYZ (&info->J1l[r2], =, 0, 0, 0);
+
+    VoXYZ (&info->J1a[r0], =, 0, 0, 0);
+    VoXYZ (&info->J1a[r1], =, 1, 0, 0);
+    VoXYZ (&info->J1a[r2], =, 0, 1, 0);
+
+    // error correction (against drift):
+
+    // a) linear vz, so that z (== pos[2]) == 0
+    info->c[0] = eps * -joint->node[0].body->posr.pos[2];
+
+# if 0
+    // b) angular correction? -> left to application !!!
+    dReal       *body_z_axis = &joint->node[0].body->R[8];
+    info->c[1] = eps * +atan2 (body_z_axis[1], body_z_axis[2]); // wx error
+    info->c[2] = eps * -atan2 (body_z_axis[0], body_z_axis[2]); // wy error
+# endif
+
+    // if the slider is powered, or has joint limits, add in the extra row:
+
+    if (joint->row_motor_x > 0)
+        joint->motor_x.addLimot (
+            joint, info, joint->row_motor_x, Midentity[0], 0);
+
+    if (joint->row_motor_y > 0)
+        joint->motor_y.addLimot (
+            joint, info, joint->row_motor_y, Midentity[1], 0);
+
+    if (joint->row_motor_angle > 0)
+        joint->motor_angle.addLimot (
+            joint, info, joint->row_motor_angle, Midentity[2], 1);
+}
+
+
+
+dxJoint::Vtable __dplane2d_vtable =
+{
+  sizeof (dxJointPlane2D),
+  (dxJoint::init_fn*) plane2dInit,
+  (dxJoint::getInfo1_fn*) plane2dGetInfo1,
+  (dxJoint::getInfo2_fn*) plane2dGetInfo2,
+  dJointTypePlane2D
+};
+
+
+void dJointSetPlane2DXParam (dxJoint *joint,
+                      int parameter, dReal value)
+{
+	dUASSERT (joint, "bad joint argument");
+	dUASSERT (joint->vtable == &__dplane2d_vtable, "joint is not a plane2d");
+	dxJointPlane2D* joint2d = (dxJointPlane2D*)( joint );
+	joint2d->motor_x.set (parameter, value);
+}
+
+
+void dJointSetPlane2DYParam (dxJoint *joint,
+                      int parameter, dReal value)
+{
+	dUASSERT (joint, "bad joint argument");
+	dUASSERT (joint->vtable == &__dplane2d_vtable, "joint is not a plane2d");
+	dxJointPlane2D* joint2d = (dxJointPlane2D*)( joint );
+	joint2d->motor_y.set (parameter, value);
+}
+
+
+
+void dJointSetPlane2DAngleParam (dxJoint *joint,
+                      int parameter, dReal value)
+{
+	dUASSERT (joint, "bad joint argument");
+	dUASSERT (joint->vtable == &__dplane2d_vtable, "joint is not a plane2d");
+	dxJointPlane2D* joint2d = (dxJointPlane2D*)( joint );
+	joint2d->motor_angle.set (parameter, value);
+}
+
+
+
Index: /code/branches/ode/ode-0.9/ode/src/joint.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/joint.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/joint.h	(revision 216)
@@ -0,0 +1,346 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_JOINT_H_
+#define _ODE_JOINT_H_
+
+
+#include "objects.h"
+#include <ode/contact.h>
+#include "obstack.h"
+
+
+// joint flags
+enum {
+  // if this flag is set, the joint was allocated in a joint group
+  dJOINT_INGROUP = 1,
+
+  // if this flag is set, the joint was attached with arguments (0,body).
+  // our convention is to treat all attaches as (body,0), i.e. so node[0].body
+  // is always nonzero, so this flag records the fact that the arguments were
+  // swapped.
+  dJOINT_REVERSE = 2,
+
+  // if this flag is set, the joint can not have just one body attached to it,
+  // it must have either zero or two bodies attached.
+  dJOINT_TWOBODIES = 4
+};
+
+
+// there are two of these nodes in the joint, one for each connection to a
+// body. these are node of a linked list kept by each body of it's connecting
+// joints. but note that the body pointer in each node points to the body that
+// makes use of the *other* node, not this node. this trick makes it a bit
+// easier to traverse the body/joint graph.
+
+struct dxJointNode {
+  dxJoint *joint;		// pointer to enclosing dxJoint object
+  dxBody *body;			// *other* body this joint is connected to
+  dxJointNode *next;		// next node in body's list of connected joints
+};
+
+
+struct dxJoint : public dObject {
+  // naming convention: the "first" body this is connected to is node[0].body,
+  // and the "second" body is node[1].body. if this joint is only connected
+  // to one body then the second body is 0.
+
+  // info returned by getInfo1 function. the constraint dimension is m (<=6).
+  // i.e. that is the total number of rows in the jacobian. `nub' is the
+  // number of unbounded variables (which have lo,hi = -/+ infinity).
+
+  struct Info1 {
+    int m,nub;
+  };
+
+  // info returned by getInfo2 function
+
+  struct Info2 {
+    // integrator parameters: frames per second (1/stepsize), default error
+    // reduction parameter (0..1).
+    dReal fps,erp;
+
+    // for the first and second body, pointers to two (linear and angular)
+    // n*3 jacobian sub matrices, stored by rows. these matrices will have
+    // been initialized to 0 on entry. if the second body is zero then the
+    // J2xx pointers may be 0.
+    dReal *J1l,*J1a,*J2l,*J2a;
+
+    // elements to jump from one row to the next in J's
+    int rowskip;
+
+    // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+    // "constraint force mixing" vector. c is set to zero on entry, cfm is
+    // set to a constant value (typically very small or zero) value on entry.
+    dReal *c,*cfm;
+
+    // lo and hi limits for variables (set to -/+ infinity on entry).
+    dReal *lo,*hi;
+
+    // findex vector for variables. see the LCP solver interface for a
+    // description of what this does. this is set to -1 on entry.
+    // note that the returned indexes are relative to the first index of
+    // the constraint.
+    int *findex;
+  };
+
+  // virtual function table: size of the joint structure, function pointers.
+  // we do it this way instead of using C++ virtual functions because
+  // sometimes we need to allocate joints ourself within a memory pool.
+
+  typedef void init_fn (dxJoint *joint);
+  typedef void getInfo1_fn (dxJoint *joint, Info1 *info);
+  typedef void getInfo2_fn (dxJoint *joint, Info2 *info);
+  struct Vtable {
+    int size;
+    init_fn *init;
+    getInfo1_fn *getInfo1;
+    getInfo2_fn *getInfo2;
+    int typenum;		// a dJointTypeXXX type number
+  };
+
+  Vtable *vtable;		// virtual function table
+  int flags;			// dJOINT_xxx flags
+  dxJointNode node[2];		// connections to bodies. node[1].body can be 0
+  dJointFeedback *feedback;	// optional feedback structure
+  dReal lambda[6];		// lambda generated by last step
+};
+
+
+// joint group. NOTE: any joints in the group that have their world destroyed
+// will have their world pointer set to 0.
+
+struct dxJointGroup : public dBase {
+  int num;		// number of joints on the stack
+  dObStack stack;	// a stack of (possibly differently sized) dxJoint
+};			// objects.
+
+
+// common limit and motor information for a single joint axis of movement
+struct dxJointLimitMotor {
+  dReal vel,fmax;		// powered joint: velocity, max force
+  dReal lostop,histop;		// joint limits, relative to initial position
+  dReal fudge_factor;		// when powering away from joint limits
+  dReal normal_cfm;		// cfm to use when not at a stop
+  dReal stop_erp,stop_cfm;	// erp and cfm for when at joint limit
+  dReal bounce;			// restitution factor
+  // variables used between getInfo1() and getInfo2()
+  int limit;			// 0=free, 1=at lo limit, 2=at hi limit
+  dReal limit_err;		// if at limit, amount over limit
+
+  void init (dxWorld *);
+  void set (int num, dReal value);
+  dReal get (int num);
+  int testRotationalLimit (dReal angle);
+  int addLimot (dxJoint *joint, dxJoint::Info2 *info, int row,
+		dVector3 ax1, int rotational);
+};
+
+
+// ball and socket
+
+struct dxJointBall : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dReal erp;			// error reduction
+  dReal cfm;			// constraint force mix in
+  void set (int num, dReal value);
+  dReal get (int num);
+};
+extern struct dxJoint::Vtable __dball_vtable;
+
+
+// hinge
+
+struct dxJointHinge : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dVector3 axis1;		// axis w.r.t first body
+  dVector3 axis2;		// axis w.r.t second body
+  dQuaternion qrel;		// initial relative rotation body1 -> body2
+  dxJointLimitMotor limot;	// limit and motor information
+};
+extern struct dxJoint::Vtable __dhinge_vtable;
+
+
+// universal
+
+struct dxJointUniversal : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dVector3 axis1;		// axis w.r.t first body
+  dVector3 axis2;		// axis w.r.t second body
+  dQuaternion qrel1;	// initial relative rotation body1 -> virtual cross piece
+  dQuaternion qrel2;    // initial relative rotation virtual cross piece -> body2
+  dxJointLimitMotor limot1;	// limit and motor information for axis1
+  dxJointLimitMotor limot2;	// limit and motor information for axis2
+};
+extern struct dxJoint::Vtable __duniversal_vtable;
+
+
+/**
+ * The axisP must be perpendicular to axis2
+ * <PRE>
+ *                                        +-------------+
+ *                                        |      x      |
+ *                                        +------------\+
+ * Prismatic articulation                   ..     ..
+ *                       |                ..     ..
+ *                      \/              ..      ..
+ * +--------------+    --|        __..      ..  anchor2
+ * |      x       | .....|.......(__)     ..
+ * +--------------+    --|         ^     <
+ *        |----------------------->|
+ *            Offset               |--- Rotoide articulation
+ * </PRE>
+ */
+struct dxJointPR : public dxJoint {
+
+  dVector3 anchor2;         ///< @brief Position of the rotoide articulation
+                            ///<        w.r.t second body.
+                            ///< @note Position of body 2 in world frame +
+                            ///< anchor2 in world frame give the position
+                            ///< of the rotoide articulation
+  dVector3 axisR1;          ///< axis of the rotoide articulation w.r.t first body.
+                            ///< @note This is considered as axis1 from the parameter
+                            ///< view.
+  dVector3 axisR2;          ///< axis of the rotoide articulation w.r.t second body.
+                            ///< @note This is considered also as axis1 from the
+                            ///< parameter view
+  dVector3 axisP1;          ///< axis for the prismatic articulation w.r.t first body.
+                            ///< @note This is considered as axis2 in from the parameter
+                            ///< view
+  dQuaternion qrel;         ///< initial relative rotation body1 -> body2.
+  dVector3 offset;          ///< @brief vector between the body1 and the rotoide
+                            ///< articulation.
+                            ///<
+                            ///< Going from the first to the second in the frame
+                            ///<  of body1.
+                            ///< That should be aligned with body1 center along axisP
+                            ///< This is calculated whe the axis are set.
+  dxJointLimitMotor limotR; ///< limit and motor information for the rotoide articulation.
+  dxJointLimitMotor limotP; ///< limit and motor information for the prismatic articulation.
+};
+extern struct dxJoint::Vtable __dPR_vtable;
+
+
+
+// slider. if body2 is 0 then qrel is the absolute rotation of body1 and
+// offset is the position of body1 center along axis1.
+
+struct dxJointSlider : public dxJoint {
+  dVector3 axis1;		// axis w.r.t first body
+  dQuaternion qrel;		// initial relative rotation body1 -> body2
+  dVector3 offset;		// point relative to body2 that should be
+				// aligned with body1 center along axis1
+  dxJointLimitMotor limot;	// limit and motor information
+};
+extern struct dxJoint::Vtable __dslider_vtable;
+
+
+// contact
+
+struct dxJointContact : public dxJoint {
+  int the_m;			// number of rows computed by getInfo1
+  dContact contact;
+};
+extern struct dxJoint::Vtable __dcontact_vtable;
+
+
+// hinge 2
+
+struct dxJointHinge2 : public dxJoint {
+  dVector3 anchor1;		// anchor w.r.t first body
+  dVector3 anchor2;		// anchor w.r.t second body
+  dVector3 axis1;		// axis 1 w.r.t first body
+  dVector3 axis2;		// axis 2 w.r.t second body
+  dReal c0,s0;			// cos,sin of desired angle between axis 1,2
+  dVector3 v1,v2;		// angle ref vectors embedded in first body
+  dxJointLimitMotor limot1;	// limit+motor info for axis 1
+  dxJointLimitMotor limot2;	// limit+motor info for axis 2
+  dReal susp_erp,susp_cfm;	// suspension parameters (erp,cfm)
+};
+extern struct dxJoint::Vtable __dhinge2_vtable;
+
+
+// angular motor
+
+struct dxJointAMotor : public dxJoint {
+  int num;			// number of axes (0..3)
+  int mode;			// a dAMotorXXX constant
+  int rel[3];			// what the axes are relative to (global,b1,b2)
+  dVector3 axis[3];		// three axes
+  dxJointLimitMotor limot[3];	// limit+motor info for axes
+  dReal angle[3];		// user-supplied angles for axes
+  // these vectors are used for calculating euler angles
+  dVector3 reference1;		// original axis[2], relative to body 1
+  dVector3 reference2;		// original axis[0], relative to body 2
+};
+extern struct dxJoint::Vtable __damotor_vtable;
+
+
+struct dxJointLMotor : public dxJoint {
+  int num;
+  int rel[3];
+  dVector3 axis[3];
+  dxJointLimitMotor limot[3];
+};
+
+extern struct dxJoint::Vtable __dlmotor_vtable;
+
+
+// 2d joint, constrains to z == 0
+
+struct dxJointPlane2D : public dxJoint
+{
+    int                 row_motor_x;
+    int                 row_motor_y;
+    int                 row_motor_angle;
+    dxJointLimitMotor   motor_x;
+    dxJointLimitMotor   motor_y;
+    dxJointLimitMotor   motor_angle;
+};
+
+extern struct dxJoint::Vtable __dplane2d_vtable;
+
+
+// fixed
+
+struct dxJointFixed : public dxJoint {
+  dQuaternion qrel;		// initial relative rotation body1 -> body2
+  dVector3 offset;		// relative offset between the bodies
+  dReal erp;			// error reduction parameter
+  dReal cfm;			// constraint force mix-in
+  void set (int num, dReal value);
+  dReal get (int num);
+};
+extern struct dxJoint::Vtable __dfixed_vtable;
+
+
+// null joint, for testing only
+
+struct dxJointNull : public dxJoint {
+};
+extern struct dxJoint::Vtable __dnull_vtable;
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/lcp.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/lcp.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/lcp.cpp	(revision 216)
@@ -0,0 +1,2007 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+
+THE ALGORITHM
+-------------
+
+solve A*x = b+w, with x and w subject to certain LCP conditions.
+each x(i),w(i) must lie on one of the three line segments in the following
+diagram. each line segment corresponds to one index set :
+
+     w(i)
+     /|\      |           :
+      |       |           :
+      |       |i in N     :
+  w>0 |       |state[i]=0 :
+      |       |           :
+      |       |           :  i in C
+  w=0 +       +-----------------------+
+      |                   :           |
+      |                   :           |
+  w<0 |                   :           |i in N
+      |                   :           |state[i]=1
+      |                   :           |
+      |                   :           |
+      +-------|-----------|-----------|----------> x(i)
+             lo           0           hi
+
+the Dantzig algorithm proceeds as follows:
+  for i=1:n
+    * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or
+      negative towards the line. as this is done, the other (x(j),w(j))
+      for j<i are constrained to be on the line. if any (x,w) reaches the
+      end of a line segment then it is switched between index sets.
+    * i is added to the appropriate index set depending on what line segment
+      it hits.
+
+we restrict lo(i) <= 0 and hi(i) >= 0. this makes the algorithm a bit
+simpler, because the starting point for x(i),w(i) is always on the dotted
+line x=0 and x will only ever increase in one direction, so it can only hit
+two out of the three line segments.
+
+
+NOTES
+-----
+
+this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m".
+the implementation is split into an LCP problem object (dLCP) and an LCP
+driver function. most optimization occurs in the dLCP object.
+
+a naive implementation of the algorithm requires either a lot of data motion
+or a lot of permutation-array lookup, because we are constantly re-ordering
+rows and columns. to avoid this and make a more optimized algorithm, a
+non-trivial data structure is used to represent the matrix A (this is
+implemented in the fast version of the dLCP object).
+
+during execution of this algorithm, some indexes in A are clamped (set C),
+some are non-clamped (set N), and some are "don't care" (where x=0).
+A,x,b,w (and other problem vectors) are permuted such that the clamped
+indexes are first, the unclamped indexes are next, and the don't-care
+indexes are last. this permutation is recorded in the array `p'.
+initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped,
+the corresponding elements of p are swapped.
+
+because the C and N elements are grouped together in the rows of A, we can do
+lots of work with a fast dot product function. if A,x,etc were not permuted
+and we only had a permutation array, then those dot products would be much
+slower as we would have a permutation array lookup in some inner loops.
+
+A is accessed through an array of row pointers, so that element (i,j) of the
+permuted matrix is A[i][j]. this makes row swapping fast. for column swapping
+we still have to actually move the data.
+
+during execution of this algorithm we maintain an L*D*L' factorization of
+the clamped submatrix of A (call it `AC') which is the top left nC*nC
+submatrix of A. there are two ways we could arrange the rows/columns in AC.
+
+(1) AC is always permuted such that L*D*L' = AC. this causes a problem
+    when a row/column is removed from C, because then all the rows/columns of A
+    between the deleted index and the end of C need to be rotated downward.
+    this results in a lot of data motion and slows things down.
+(2) L*D*L' is actually a factorization of a *permutation* of AC (which is
+    itself a permutation of the underlying A). this is what we do - the
+    permutation is recorded in the vector C. call this permutation A[C,C].
+    when a row/column is removed from C, all we have to do is swap two
+    rows/columns and manipulate C.
+
+*/
+
+#include <ode/common.h>
+#include "lcp.h"
+#include <ode/matrix.h>
+#include <ode/misc.h>
+#include "mat.h"		// for testing
+#include <ode/timer.h>		// for testing
+
+//***************************************************************************
+// code generation parameters
+
+// LCP debugging (mosty for fast dLCP) - this slows things down a lot
+//#define DEBUG_LCP
+
+//#define dLCP_SLOW		// use slow dLCP object
+#define dLCP_FAST		// use fast dLCP object
+
+// option 1 : matrix row pointers (less data copying)
+#define ROWPTRS
+#define ATYPE dReal **
+#define AROW(i) (A[i])
+
+// option 2 : no matrix row pointers (slightly faster inner loops)
+//#define NOROWPTRS
+//#define ATYPE dReal *
+//#define AROW(i) (A+(i)*nskip)
+
+// use protected, non-stack memory allocation system
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+extern unsigned int dMemoryFlag;
+
+#define ALLOCA(t,v,s) t* v = (t*) malloc(s)
+#define UNALLOCA(t)  free(t)
+
+#else
+
+#define ALLOCA(t,v,s) t* v =(t*)dALLOCA16(s)
+#define UNALLOCA(t)  /* nothing */
+
+#endif
+
+#define NUB_OPTIMIZATIONS
+
+//***************************************************************************
+
+// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of
+// A is nskip. this only references and swaps the lower triangle.
+// if `do_fast_row_swaps' is nonzero and row pointers are being used, then
+// rows will be swapped by exchanging row pointers. otherwise the data will
+// be copied.
+
+static void swapRowsAndCols (ATYPE A, int n, int i1, int i2, int nskip,
+			     int do_fast_row_swaps)
+{
+  int i;
+  dAASSERT (A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
+	    nskip >= n && i1 < i2);
+
+# ifdef ROWPTRS
+  for (i=i1+1; i<i2; i++) A[i1][i] = A[i][i1];
+  for (i=i1+1; i<i2; i++) A[i][i1] = A[i2][i];
+  A[i1][i2] = A[i1][i1];
+  A[i1][i1] = A[i2][i1];
+  A[i2][i1] = A[i2][i2];
+  // swap rows, by swapping row pointers
+  if (do_fast_row_swaps) {
+    dReal *tmpp;
+    tmpp = A[i1];
+    A[i1] = A[i2];
+    A[i2] = tmpp;
+  }
+  else {
+    ALLOCA (dReal,tmprow,n * sizeof(dReal));
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmprow == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;      
+      return;
+    }
+#endif
+
+    memcpy (tmprow,A[i1],n * sizeof(dReal));
+    memcpy (A[i1],A[i2],n * sizeof(dReal));
+    memcpy (A[i2],tmprow,n * sizeof(dReal));
+    UNALLOCA(tmprow);
+  }
+  // swap columns the hard way
+  for (i=i2+1; i<n; i++) {
+    dReal tmp = A[i][i1];
+    A[i][i1] = A[i][i2];
+    A[i][i2] = tmp;
+  }
+# else
+  dReal tmp;
+  ALLOCA (dReal,tmprow,n * sizeof(dReal));
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (tmprow == NULL) {
+    return;
+  }
+#endif
+
+  if (i1 > 0) {
+    memcpy (tmprow,A+i1*nskip,i1*sizeof(dReal));
+    memcpy (A+i1*nskip,A+i2*nskip,i1*sizeof(dReal));
+    memcpy (A+i2*nskip,tmprow,i1*sizeof(dReal));
+  }
+  for (i=i1+1; i<i2; i++) {
+    tmp = A[i2*nskip+i];
+    A[i2*nskip+i] = A[i*nskip+i1];
+    A[i*nskip+i1] = tmp;
+  }
+  tmp = A[i1*nskip+i1];
+  A[i1*nskip+i1] = A[i2*nskip+i2];
+  A[i2*nskip+i2] = tmp;
+  for (i=i2+1; i<n; i++) {
+    tmp = A[i*nskip+i1];
+    A[i*nskip+i1] = A[i*nskip+i2];
+    A[i*nskip+i2] = tmp;
+  }
+  UNALLOCA(tmprow);
+# endif
+
+}
+
+
+// swap two indexes in the n*n LCP problem. i1 must be <= i2.
+
+static void swapProblem (ATYPE A, dReal *x, dReal *b, dReal *w, dReal *lo,
+			 dReal *hi, int *p, int *state, int *findex,
+			 int n, int i1, int i2, int nskip,
+			 int do_fast_row_swaps)
+{
+  dReal tmp;
+  int tmpi;
+  dIASSERT (n>0 && i1 >=0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n &&
+	    i1 <= i2);
+  if (i1==i2) return;
+  swapRowsAndCols (A,n,i1,i2,nskip,do_fast_row_swaps);
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY)
+    return;
+#endif
+  tmp = x[i1];
+  x[i1] = x[i2];
+  x[i2] = tmp;
+  tmp = b[i1];
+  b[i1] = b[i2];
+  b[i2] = tmp;
+  tmp = w[i1];
+  w[i1] = w[i2];
+  w[i2] = tmp;
+  tmp = lo[i1];
+  lo[i1] = lo[i2];
+  lo[i2] = tmp;
+  tmp = hi[i1];
+  hi[i1] = hi[i2];
+  hi[i2] = tmp;
+  tmpi = p[i1];
+  p[i1] = p[i2];
+  p[i2] = tmpi;
+  tmpi = state[i1];
+  state[i1] = state[i2];
+  state[i2] = tmpi;
+  if (findex) {
+    tmpi = findex[i1];
+    findex[i1] = findex[i2];
+    findex[i2] = tmpi;
+  }
+}
+
+
+// for debugging - check that L,d is the factorization of A[C,C].
+// A[C,C] has size nC*nC and leading dimension nskip.
+// L has size nC*nC and leading dimension nskip.
+// d has size nC.
+
+#ifdef DEBUG_LCP
+
+static void checkFactorization (ATYPE A, dReal *_L, dReal *_d,
+				int nC, int *C, int nskip)
+{
+  int i,j;
+  if (nC==0) return;
+
+  // get A1=A, copy the lower triangle to the upper triangle, get A2=A[C,C]
+  dMatrix A1 (nC,nC);
+  for (i=0; i<nC; i++) {
+    for (j=0; j<=i; j++) A1(i,j) = A1(j,i) = AROW(i)[j];
+  }
+  dMatrix A2 = A1.select (nC,C,nC,C);
+
+  // printf ("A1=\n"); A1.print(); printf ("\n");
+  // printf ("A2=\n"); A2.print(); printf ("\n");
+
+  // compute A3 = L*D*L'
+  dMatrix L (nC,nC,_L,nskip,1);
+  dMatrix D (nC,nC);
+  for (i=0; i<nC; i++) D(i,i) = 1/_d[i];
+  L.clearUpperTriangle();
+  for (i=0; i<nC; i++) L(i,i) = 1;
+  dMatrix A3 = L * D * L.transpose();
+
+  // printf ("L=\n"); L.print(); printf ("\n");
+  // printf ("D=\n"); D.print(); printf ("\n");
+  // printf ("A3=\n"); A2.print(); printf ("\n");
+
+  // compare A2 and A3
+  dReal diff = A2.maxDifference (A3);
+  if (diff > 1e-8)
+    dDebug (0,"L*D*L' check, maximum difference = %.6e\n",diff);
+}
+
+#endif
+
+
+// for debugging
+
+#ifdef DEBUG_LCP
+
+static void checkPermutations (int i, int n, int nC, int nN, int *p, int *C)
+{
+  int j,k;
+  dIASSERT (nC>=0 && nN>=0 && (nC+nN)==i && i < n);
+  for (k=0; k<i; k++) dIASSERT (p[k] >= 0 && p[k] < i);
+  for (k=i; k<n; k++) dIASSERT (p[k] == k);
+  for (j=0; j<nC; j++) {
+    int C_is_bad = 1;
+    for (k=0; k<nC; k++) if (C[k]==j) C_is_bad = 0;
+    dIASSERT (C_is_bad==0);
+  }
+}
+
+#endif
+
+//***************************************************************************
+// dLCP manipulator object. this represents an n*n LCP problem.
+//
+// two index sets C and N are kept. each set holds a subset of
+// the variable indexes 0..n-1. an index can only be in one set.
+// initially both sets are empty.
+//
+// the index set C is special: solutions to A(C,C)\A(C,i) can be generated.
+
+#ifdef dLCP_SLOW
+
+// simple but slow implementation of dLCP, for testing the LCP drivers.
+
+#include "array.h"
+
+struct dLCP {
+  int n,nub,nskip;
+  dReal *Adata,*x,*b,*w,*lo,*hi;	// LCP problem data
+  ATYPE A;				// A rows
+  dArray<int> C,N;			// index sets
+  int last_i_for_solve1;		// last i value given to solve1
+
+  dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
+	dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
+	dReal *_Dell, dReal *_ell, dReal *_tmp,
+	int *_state, int *_findex, int *_p, int *_C, dReal **Arows);
+  // the constructor is given an initial problem description (A,x,b,w) and
+  // space for other working data (which the caller may allocate on the stack).
+  // some of this data is specific to the fast dLCP implementation.
+  // the matrices A and L have size n*n, vectors have size n*1.
+  // A represents a symmetric matrix but only the lower triangle is valid.
+  // `nub' is the number of unbounded indexes at the start. all the indexes
+  // 0..nub-1 will be put into C.
+
+  ~dLCP();
+
+  int getNub() { return nub; }
+  // return the value of `nub'. the constructor may want to change it,
+  // so the caller should find out its new value.
+
+  // transfer functions: transfer index i to the given set (C or N). indexes
+  // less than `nub' can never be given. A,x,b,w,etc may be permuted by these
+  // functions, the caller must be robust to this.
+
+  void transfer_i_to_C (int i);
+    // this assumes C and N span 1:i-1. this also assumes that solve1() has
+    // been recently called for the same i without any other transfer
+    // functions in between (thereby allowing some data reuse for the fast
+    // implementation).
+  void transfer_i_to_N (int i);
+    // this assumes C and N span 1:i-1.
+  void transfer_i_from_N_to_C (int i);
+  void transfer_i_from_C_to_N (int i);
+
+  int numC();
+  int numN();
+  // return the number of indexes in set C/N
+
+  int indexC (int i);
+  int indexN (int i);
+  // return index i in set C/N.
+
+  // accessor and arithmetic functions. Aij translates as A(i,j), etc.
+  // make sure that only the lower triangle of A is ever referenced.
+
+  dReal Aii (int i);
+  dReal AiC_times_qC (int i, dReal *q);
+  dReal AiN_times_qN (int i, dReal *q);			// for all Nj
+  void pN_equals_ANC_times_qC (dReal *p, dReal *q);	// for all Nj
+  void pN_plusequals_ANi (dReal *p, int i, int sign=1);
+    // for all Nj. sign = +1,-1. assumes i > maximum index in N.
+  void pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q);
+  void pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q); // for all Nj
+  void solve1 (dReal *a, int i, int dir=1, int only_transfer=0);
+    // get a(C) = - dir * A(C,C) \ A(C,i). dir must be +/- 1.
+    // the fast version of this function computes some data that is needed by
+    // transfer_i_to_C(). if only_transfer is nonzero then this function
+    // *only* computes that data, it does not set a(C).
+
+  void unpermute();
+  // call this at the end of the LCP function. if the x/w values have been
+  // permuted then this will unscramble them.
+};
+
+
+dLCP::dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
+	    dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
+	    dReal *_Dell, dReal *_ell, dReal *_tmp,
+	    int *_state, int *_findex, int *_p, int *_C, dReal **Arows)
+{
+  dUASSERT (_findex==0,"slow dLCP object does not support findex array");
+
+  n = _n;
+  nub = _nub;
+  Adata = _Adata;
+  A = 0;
+  x = _x;
+  b = _b;
+  w = _w;
+  lo = _lo;
+  hi = _hi;
+  nskip = dPAD(n);
+  dSetZero (x,n);
+  last_i_for_solve1 = -1;
+
+  int i,j;
+  C.setSize (n);
+  N.setSize (n);
+  for (i=0; i<n; i++) {
+    C[i] = 0;
+    N[i] = 0;
+  }
+
+# ifdef ROWPTRS
+  // make matrix row pointers
+  A = Arows;
+  for (i=0; i<n; i++) A[i] = Adata + i*nskip;
+# else
+  A = Adata;
+# endif
+
+  // lets make A symmetric
+  for (i=0; i<n; i++) {
+    for (j=i+1; j<n; j++) AROW(i)[j] = AROW(j)[i];
+  }
+
+  // if nub>0, put all indexes 0..nub-1 into C and solve for x
+  if (nub > 0) {
+    for (i=0; i<nub; i++) memcpy (_L+i*nskip,AROW(i),(i+1)*sizeof(dReal));
+    dFactorLDLT (_L,_d,nub,nskip);
+    memcpy (x,b,nub*sizeof(dReal));
+    dSolveLDLT (_L,_d,x,nub,nskip);
+    dSetZero (_w,nub);
+    for (i=0; i<nub; i++) C[i] = 1;
+  }
+}
+
+
+dLCP::~dLCP()
+{
+}
+
+
+void dLCP::transfer_i_to_C (int i)
+{
+  if (i < nub) dDebug (0,"bad i");
+  if (C[i]) dDebug (0,"i already in C");
+  if (N[i]) dDebug (0,"i already in N");
+  for (int k=0; k<i; k++) {
+    if (!(C[k] ^ N[k])) dDebug (0,"assumptions for C and N violated");
+  }
+  for (int k=i; k<n; k++)
+    if (C[k] || N[k]) dDebug (0,"assumptions for C and N violated");
+  if (i != last_i_for_solve1) dDebug (0,"assumptions for i violated");
+  last_i_for_solve1 = -1;
+  C[i] = 1;
+}
+
+
+void dLCP::transfer_i_to_N (int i)
+{
+  if (i < nub) dDebug (0,"bad i");
+  if (C[i]) dDebug (0,"i already in C");
+  if (N[i]) dDebug (0,"i already in N");
+  for (int k=0; k<i; k++)
+    if (!C[k] && !N[k]) dDebug (0,"assumptions for C and N violated");
+  for (int k=i; k<n; k++)
+    if (C[k] || N[k]) dDebug (0,"assumptions for C and N violated");
+  last_i_for_solve1 = -1;
+  N[i] = 1;
+}
+
+
+void dLCP::transfer_i_from_N_to_C (int i)
+{
+  if (i < nub) dDebug (0,"bad i");
+  if (C[i]) dDebug (0,"i already in C");
+  if (!N[i]) dDebug (0,"i not in N");
+  last_i_for_solve1 = -1;
+  N[i] = 0;
+  C[i] = 1;
+}
+
+
+void dLCP::transfer_i_from_C_to_N (int i)
+{
+  if (i < nub) dDebug (0,"bad i");
+  if (N[i]) dDebug (0,"i already in N");
+  if (!C[i]) dDebug (0,"i not in C");
+  last_i_for_solve1 = -1;
+  C[i] = 0;
+  N[i] = 1;
+}
+
+
+int dLCP::numC()
+{
+  int i,count=0;
+  for (i=0; i<n; i++) if (C[i]) count++;
+  return count;
+}
+
+
+int dLCP::numN()
+{
+  int i,count=0;
+  for (i=0; i<n; i++) if (N[i]) count++;
+  return count;
+}
+
+
+int dLCP::indexC (int i)
+{
+  int k,count=0;
+  for (k=0; k<n; k++) {
+    if (C[k]) {
+      if (count==i) return k;
+      count++;
+    }
+  }
+  dDebug (0,"bad index C (%d)",i);
+  return 0;
+}
+
+
+int dLCP::indexN (int i)
+{
+  int k,count=0;
+  for (k=0; k<n; k++) {
+    if (N[k]) {
+      if (count==i) return k;
+      count++;
+    }
+  }
+  dDebug (0,"bad index into N");
+  return 0;
+}
+
+
+dReal dLCP::Aii (int i)
+{
+  return AROW(i)[i];
+}
+
+
+dReal dLCP::AiC_times_qC (int i, dReal *q)
+{
+  dReal sum = 0;
+  for (int k=0; k<n; k++) if (C[k]) sum += AROW(i)[k] * q[k];
+  return sum;
+}
+
+
+dReal dLCP::AiN_times_qN (int i, dReal *q)
+{
+  dReal sum = 0;
+  for (int k=0; k<n; k++) if (N[k]) sum += AROW(i)[k] * q[k];
+  return sum;
+}
+
+
+void dLCP::pN_equals_ANC_times_qC (dReal *p, dReal *q)
+{
+  dReal sum;
+  for (int ii=0; ii<n; ii++) if (N[ii]) {
+    sum = 0;
+    for (int jj=0; jj<n; jj++) if (C[jj]) sum += AROW(ii)[jj] * q[jj];
+    p[ii] = sum;
+  }
+}
+
+
+void dLCP::pN_plusequals_ANi (dReal *p, int i, int sign)
+{
+  int k;
+  for (k=0; k<n; k++) if (N[k] && k >= i) dDebug (0,"N assumption violated");
+  if (sign > 0) {
+    for (k=0; k<n; k++) if (N[k]) p[k] += AROW(i)[k];
+  }
+  else {
+    for (k=0; k<n; k++) if (N[k]) p[k] -= AROW(i)[k];
+  }
+}
+
+
+void dLCP::pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q)
+{
+  for (int k=0; k<n; k++) if (C[k]) p[k] += s*q[k];
+}
+
+
+void dLCP::pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q)
+{
+  for (int k=0; k<n; k++) if (N[k]) p[k] += s*q[k];
+}
+
+
+void dLCP::solve1 (dReal *a, int i, int dir, int only_transfer)
+{
+
+  ALLOCA (dReal,AA,n*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (AA == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,dd,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dd == NULL) {
+      UNALLOCA(AA);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,bb,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (bb == NULL) {
+      UNALLOCA(AA);
+      UNALLOCA(dd);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  int ii,jj,AAi,AAj;
+
+  last_i_for_solve1 = i;
+  AAi = 0;
+  for (ii=0; ii<n; ii++) if (C[ii]) {
+    AAj = 0;
+    for (jj=0; jj<n; jj++) if (C[jj]) {
+      AA[AAi*nskip+AAj] = AROW(ii)[jj];
+      AAj++;
+    }
+    bb[AAi] = AROW(i)[ii];
+    AAi++;
+  }
+  if (AAi==0) {
+      UNALLOCA (AA);
+      UNALLOCA (dd);
+      UNALLOCA (bb);
+      return;
+  }
+
+  dFactorLDLT (AA,dd,AAi,nskip);
+  dSolveLDLT (AA,dd,bb,AAi,nskip);
+
+  AAi=0;
+  if (dir > 0) {
+    for (ii=0; ii<n; ii++) if (C[ii]) a[ii] = -bb[AAi++];
+  }
+  else {
+    for (ii=0; ii<n; ii++) if (C[ii]) a[ii] = bb[AAi++];
+  }
+
+  UNALLOCA (AA);
+  UNALLOCA (dd);
+  UNALLOCA (bb);
+}
+
+
+void dLCP::unpermute()
+{
+}
+
+#endif // dLCP_SLOW
+
+//***************************************************************************
+// fast implementation of dLCP. see the above definition of dLCP for
+// interface comments.
+//
+// `p' records the permutation of A,x,b,w,etc. p is initially 1:n and is
+// permuted as the other vectors/matrices are permuted.
+//
+// A,x,b,w,lo,hi,state,findex,p,c are permuted such that sets C,N have
+// contiguous indexes. the don't-care indexes follow N.
+//
+// an L*D*L' factorization is maintained of A(C,C), and whenever indexes are
+// added or removed from the set C the factorization is updated.
+// thus L*D*L'=A[C,C], i.e. a permuted top left nC*nC submatrix of A.
+// the leading dimension of the matrix L is always `nskip'.
+//
+// at the start there may be other indexes that are unbounded but are not
+// included in `nub'. dLCP will permute the matrix so that absolutely all
+// unbounded vectors are at the start. thus there may be some initial
+// permutation.
+//
+// the algorithms here assume certain patterns, particularly with respect to
+// index transfer.
+
+#ifdef dLCP_FAST
+
+struct dLCP {
+  int n,nskip,nub;
+  ATYPE A;				// A rows
+  dReal *Adata,*x,*b,*w,*lo,*hi;	// permuted LCP problem data
+  dReal *L,*d;				// L*D*L' factorization of set C
+  dReal *Dell,*ell,*tmp;
+  int *state,*findex,*p,*C;
+  int nC,nN;				// size of each index set
+
+  dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
+	dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
+	dReal *_Dell, dReal *_ell, dReal *_tmp,
+	int *_state, int *_findex, int *_p, int *_C, dReal **Arows);
+  int getNub() { return nub; }
+  void transfer_i_to_C (int i);
+  void transfer_i_to_N (int i)
+    { nN++; }			// because we can assume C and N span 1:i-1
+  void transfer_i_from_N_to_C (int i);
+  void transfer_i_from_C_to_N (int i);
+  int numC() { return nC; }
+  int numN() { return nN; }
+  int indexC (int i) { return i; }
+  int indexN (int i) { return i+nC; }
+  dReal Aii (int i) { return AROW(i)[i]; }
+  dReal AiC_times_qC (int i, dReal *q) { return dDot (AROW(i),q,nC); }
+  dReal AiN_times_qN (int i, dReal *q) { return dDot (AROW(i)+nC,q+nC,nN); }
+  void pN_equals_ANC_times_qC (dReal *p, dReal *q);
+  void pN_plusequals_ANi (dReal *p, int i, int sign=1);
+  void pC_plusequals_s_times_qC (dReal *p, dReal s, dReal *q)
+    { for (int i=0; i<nC; i++) p[i] += s*q[i]; }
+  void pN_plusequals_s_times_qN (dReal *p, dReal s, dReal *q)
+    { for (int i=0; i<nN; i++) p[i+nC] += s*q[i+nC]; }
+  void solve1 (dReal *a, int i, int dir=1, int only_transfer=0);
+  void unpermute();
+};
+
+
+dLCP::dLCP (int _n, int _nub, dReal *_Adata, dReal *_x, dReal *_b, dReal *_w,
+	    dReal *_lo, dReal *_hi, dReal *_L, dReal *_d,
+	    dReal *_Dell, dReal *_ell, dReal *_tmp,
+	    int *_state, int *_findex, int *_p, int *_C, dReal **Arows)
+{
+  n = _n;
+  nub = _nub;
+  Adata = _Adata;
+  A = 0;
+  x = _x;
+  b = _b;
+  w = _w;
+  lo = _lo;
+  hi = _hi;
+  L = _L;
+  d = _d;
+  Dell = _Dell;
+  ell = _ell;
+  tmp = _tmp;
+  state = _state;
+  findex = _findex;
+  p = _p;
+  C = _C;
+  nskip = dPAD(n);
+  dSetZero (x,n);
+
+  int k;
+
+# ifdef ROWPTRS
+  // make matrix row pointers
+  A = Arows;
+  for (k=0; k<n; k++) A[k] = Adata + k*nskip;
+# else
+  A = Adata;
+# endif
+
+  nC = 0;
+  nN = 0;
+  for (k=0; k<n; k++) p[k]=k;		// initially unpermuted
+
+  /*
+  // for testing, we can do some random swaps in the area i > nub
+  if (nub < n) {
+    for (k=0; k<100; k++) {
+      int i1,i2;
+      do {
+	i1 = dRandInt(n-nub)+nub;
+	i2 = dRandInt(n-nub)+nub;
+      }
+      while (i1 > i2); 
+      //printf ("--> %d %d\n",i1,i2);
+      swapProblem (A,x,b,w,lo,hi,p,state,findex,n,i1,i2,nskip,0);
+    }
+  }
+  */
+
+  // permute the problem so that *all* the unbounded variables are at the
+  // start, i.e. look for unbounded variables not included in `nub'. we can
+  // potentially push up `nub' this way and get a bigger initial factorization.
+  // note that when we swap rows/cols here we must not just swap row pointers,
+  // as the initial factorization relies on the data being all in one chunk.
+  // variables that have findex >= 0 are *not* considered to be unbounded even
+  // if lo=-inf and hi=inf - this is because these limits may change during the
+  // solution process.
+
+  for (k=nub; k<n; k++) {
+    if (findex && findex[k] >= 0) continue;
+    if (lo[k]==-dInfinity && hi[k]==dInfinity) {
+      swapProblem (A,x,b,w,lo,hi,p,state,findex,n,nub,k,nskip,0);
+      nub++;
+    }
+  }
+
+  // if there are unbounded variables at the start, factorize A up to that
+  // point and solve for x. this puts all indexes 0..nub-1 into C.
+  if (nub > 0) {
+    for (k=0; k<nub; k++) memcpy (L+k*nskip,AROW(k),(k+1)*sizeof(dReal));
+    dFactorLDLT (L,d,nub,nskip);
+    memcpy (x,b,nub*sizeof(dReal));
+    dSolveLDLT (L,d,x,nub,nskip);
+    dSetZero (w,nub);
+    for (k=0; k<nub; k++) C[k] = k;
+    nC = nub;
+  }
+
+  // permute the indexes > nub such that all findex variables are at the end
+  if (findex) {
+    int num_at_end = 0;
+    for (k=n-1; k >= nub; k--) {
+      if (findex[k] >= 0) {
+	swapProblem (A,x,b,w,lo,hi,p,state,findex,n,k,n-1-num_at_end,nskip,1);
+	num_at_end++;
+      }
+    }
+  }
+
+  // print info about indexes
+  /*
+  for (k=0; k<n; k++) {
+    if (k<nub) printf ("C");
+    else if (lo[k]==-dInfinity && hi[k]==dInfinity) printf ("c");
+    else printf (".");
+  }
+  printf ("\n");
+  */
+}
+
+
+void dLCP::transfer_i_to_C (int i)
+{
+  int j;
+  if (nC > 0) {
+    // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
+    for (j=0; j<nC; j++) L[nC*nskip+j] = ell[j];
+    d[nC] = dRecip (AROW(i)[i] - dDot(ell,Dell,nC));
+  }
+  else {
+    d[0] = dRecip (AROW(i)[i]);
+  }
+  swapProblem (A,x,b,w,lo,hi,p,state,findex,n,nC,i,nskip,1);
+  C[nC] = nC;
+  nC++;
+
+# ifdef DEBUG_LCP
+  checkFactorization (A,L,d,nC,C,nskip);
+  if (i < (n-1)) checkPermutations (i+1,n,nC,nN,p,C);
+# endif
+}
+
+
+void dLCP::transfer_i_from_N_to_C (int i)
+{
+  int j;
+  if (nC > 0) {
+    dReal *aptr = AROW(i);
+#   ifdef NUB_OPTIMIZATIONS
+    // if nub>0, initial part of aptr unpermuted
+    for (j=0; j<nub; j++) Dell[j] = aptr[j];
+    for (j=nub; j<nC; j++) Dell[j] = aptr[C[j]];
+#   else
+    for (j=0; j<nC; j++) Dell[j] = aptr[C[j]];
+#   endif
+    dSolveL1 (L,Dell,nC,nskip);
+    for (j=0; j<nC; j++) ell[j] = Dell[j] * d[j];
+    for (j=0; j<nC; j++) L[nC*nskip+j] = ell[j];
+    d[nC] = dRecip (AROW(i)[i] - dDot(ell,Dell,nC));
+  }
+  else {
+    d[0] = dRecip (AROW(i)[i]);
+  }
+  swapProblem (A,x,b,w,lo,hi,p,state,findex,n,nC,i,nskip,1);
+  C[nC] = nC;
+  nN--;
+  nC++;
+
+  // @@@ TO DO LATER
+  // if we just finish here then we'll go back and re-solve for
+  // delta_x. but actually we can be more efficient and incrementally
+  // update delta_x here. but if we do this, we wont have ell and Dell
+  // to use in updating the factorization later.
+
+# ifdef DEBUG_LCP
+  checkFactorization (A,L,d,nC,C,nskip);
+# endif
+}
+
+
+void dLCP::transfer_i_from_C_to_N (int i)
+{
+  // remove a row/column from the factorization, and adjust the
+  // indexes (black magic!)
+  int j,k;
+  for (j=0; j<nC; j++) if (C[j]==i) {
+    dLDLTRemove (A,C,L,d,n,nC,j,nskip);
+    for (k=0; k<nC; k++) if (C[k]==nC-1) {
+      C[k] = C[j];
+      if (j < (nC-1)) memmove (C+j,C+j+1,(nC-j-1)*sizeof(int));
+      break;
+    }
+    dIASSERT (k < nC);
+    break;
+  }
+  dIASSERT (j < nC);
+  swapProblem (A,x,b,w,lo,hi,p,state,findex,n,i,nC-1,nskip,1);
+  nC--;
+  nN++;
+
+# ifdef DEBUG_LCP
+  checkFactorization (A,L,d,nC,C,nskip);
+# endif
+}
+
+
+void dLCP::pN_equals_ANC_times_qC (dReal *p, dReal *q)
+{
+  // we could try to make this matrix-vector multiplication faster using
+  // outer product matrix tricks, e.g. with the dMultidotX() functions.
+  // but i tried it and it actually made things slower on random 100x100
+  // problems because of the overhead involved. so we'll stick with the
+  // simple method for now.
+  for (int i=0; i<nN; i++) p[i+nC] = dDot (AROW(i+nC),q,nC);
+}
+
+
+void dLCP::pN_plusequals_ANi (dReal *p, int i, int sign)
+{
+  dReal *aptr = AROW(i)+nC;
+  if (sign > 0) {
+    for (int i=0; i<nN; i++) p[i+nC] += aptr[i];
+  }
+  else {
+    for (int i=0; i<nN; i++) p[i+nC] -= aptr[i];
+  }
+}
+
+
+void dLCP::solve1 (dReal *a, int i, int dir, int only_transfer)
+{
+  // the `Dell' and `ell' that are computed here are saved. if index i is
+  // later added to the factorization then they can be reused.
+  //
+  // @@@ question: do we need to solve for entire delta_x??? yes, but
+  //     only if an x goes below 0 during the step.
+
+  int j;
+  if (nC > 0) {
+    dReal *aptr = AROW(i);
+#   ifdef NUB_OPTIMIZATIONS
+    // if nub>0, initial part of aptr[] is guaranteed unpermuted
+    for (j=0; j<nub; j++) Dell[j] = aptr[j];
+    for (j=nub; j<nC; j++) Dell[j] = aptr[C[j]];
+#   else
+    for (j=0; j<nC; j++) Dell[j] = aptr[C[j]];
+#   endif
+    dSolveL1 (L,Dell,nC,nskip);
+    for (j=0; j<nC; j++) ell[j] = Dell[j] * d[j];
+
+    if (!only_transfer) {
+      for (j=0; j<nC; j++) tmp[j] = ell[j];
+      dSolveL1T (L,tmp,nC,nskip);
+      if (dir > 0) {
+	for (j=0; j<nC; j++) a[C[j]] = -tmp[j];
+      }
+      else {
+	for (j=0; j<nC; j++) a[C[j]] = tmp[j];
+      }
+    }
+  }
+}
+
+
+void dLCP::unpermute()
+{
+  // now we have to un-permute x and w
+  int j;
+  ALLOCA (dReal,tmp,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  memcpy (tmp,x,n*sizeof(dReal));
+  for (j=0; j<n; j++) x[p[j]] = tmp[j];
+  memcpy (tmp,w,n*sizeof(dReal));
+  for (j=0; j<n; j++) w[p[j]] = tmp[j];
+
+  UNALLOCA (tmp);
+}
+
+#endif // dLCP_FAST
+
+//***************************************************************************
+// an unoptimized Dantzig LCP driver routine for the basic LCP problem.
+// must have lo=0, hi=dInfinity, and nub=0.
+
+void dSolveLCPBasic (int n, dReal *A, dReal *x, dReal *b,
+		     dReal *w, int nub, dReal *lo, dReal *hi)
+{
+  dAASSERT (n>0 && A && x && b && w && nub == 0);
+
+  int i,k;
+  int nskip = dPAD(n);
+  ALLOCA (dReal,L,n*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (L == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,d,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (d == NULL) {
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,delta_x,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (delta_x == NULL) {
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,delta_w,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (delta_w == NULL) {
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,Dell,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (Dell == NULL) {
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,ell,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (ell == NULL) {
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,tmp,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp == NULL) {
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal*,Arows,n*sizeof(dReal*));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (Arows == NULL) {
+      UNALLOCA(tmp);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (int,p,n*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (p == NULL) {
+      UNALLOCA(Arows);
+      UNALLOCA(tmp);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (int,C,n*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (C == NULL) {
+      UNALLOCA(p);
+      UNALLOCA(Arows);
+      UNALLOCA(tmp);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (int,dummy,n*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dummy == NULL) {
+      UNALLOCA(C);
+      UNALLOCA(p);
+      UNALLOCA(Arows);
+      UNALLOCA(tmp);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+
+  dLCP lcp (n,0,A,x,b,w,tmp,tmp,L,d,Dell,ell,tmp,dummy,dummy,p,C,Arows);
+  nub = lcp.getNub();
+
+  for (i=0; i<n; i++) {
+    w[i] = lcp.AiC_times_qC (i,x) - b[i];
+    if (w[i] >= 0) {
+      lcp.transfer_i_to_N (i);
+    }
+    else {
+      for (;;) {
+	// compute: delta_x(C) = -A(C,C)\A(C,i)
+	dSetZero (delta_x,n);
+	lcp.solve1 (delta_x,i);
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+	if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+	  UNALLOCA(dummy);
+	  UNALLOCA(C);
+	  UNALLOCA(p);
+	  UNALLOCA(Arows);
+	  UNALLOCA(tmp);
+	  UNALLOCA(ell);
+	  UNALLOCA(Dell);
+	  UNALLOCA(delta_w);
+	  UNALLOCA(delta_x);
+	  UNALLOCA(d);
+	  UNALLOCA(L);
+	  return;
+	}
+#endif
+	delta_x[i] = 1;
+
+	// compute: delta_w = A*delta_x
+	dSetZero (delta_w,n);
+	lcp.pN_equals_ANC_times_qC (delta_w,delta_x);
+	lcp.pN_plusequals_ANi (delta_w,i);
+        delta_w[i] = lcp.AiC_times_qC (i,delta_x) + lcp.Aii(i);
+
+	// find index to switch
+	int si = i;		// si = switch index
+	int si_in_N = 0;	// set to 1 if si in N
+	dReal s = -w[i]/delta_w[i];
+
+	if (s <= 0) {
+	  dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",s);
+	  if (i < (n-1)) {
+	    dSetZero (x+i,n-i);
+	    dSetZero (w+i,n-i);
+	  }
+	  goto done;
+	}
+
+	for (k=0; k < lcp.numN(); k++) {
+	  if (delta_w[lcp.indexN(k)] < 0) {
+	    dReal s2 = -w[lcp.indexN(k)] / delta_w[lcp.indexN(k)];
+	    if (s2 < s) {
+	      s = s2;
+	      si = lcp.indexN(k);
+	      si_in_N = 1;
+	    }
+	  }
+	}
+	for (k=0; k < lcp.numC(); k++) {
+	  if (delta_x[lcp.indexC(k)] < 0) {
+	    dReal s2 = -x[lcp.indexC(k)] / delta_x[lcp.indexC(k)];
+	    if (s2 < s) {
+	      s = s2;
+	      si = lcp.indexC(k);
+	      si_in_N = 0;
+	    }
+	  }
+	}
+
+	// apply x = x + s * delta_x
+	lcp.pC_plusequals_s_times_qC (x,s,delta_x);
+	x[i] += s;
+	lcp.pN_plusequals_s_times_qN (w,s,delta_w);
+	w[i] += s * delta_w[i];
+
+	// switch indexes between sets if necessary
+	if (si==i) {
+	  w[i] = 0;
+	  lcp.transfer_i_to_C (i);
+	  break;
+	}
+	if (si_in_N) {
+          w[si] = 0;
+	  lcp.transfer_i_from_N_to_C (si);
+	}
+	else {
+          x[si] = 0;
+	  lcp.transfer_i_from_C_to_N (si);
+	}
+      }
+    }
+  }
+
+ done:
+  lcp.unpermute();
+
+  UNALLOCA (L);
+  UNALLOCA (d);
+  UNALLOCA (delta_x);
+  UNALLOCA (delta_w);
+  UNALLOCA (Dell);
+  UNALLOCA (ell);
+  UNALLOCA (tmp);
+  UNALLOCA (Arows);
+  UNALLOCA (p);
+  UNALLOCA (C);
+  UNALLOCA (dummy);
+}
+
+//***************************************************************************
+// an optimized Dantzig LCP driver routine for the lo-hi LCP problem.
+
+void dSolveLCP (int n, dReal *A, dReal *x, dReal *b,
+		dReal *w, int nub, dReal *lo, dReal *hi, int *findex)
+{
+  dAASSERT (n>0 && A && x && b && w && lo && hi && nub >= 0 && nub <= n);
+
+  int i,k,hit_first_friction_index = 0;
+  int nskip = dPAD(n);
+
+  // if all the variables are unbounded then we can just factor, solve,
+  // and return
+  if (nub >= n) {
+    dFactorLDLT (A,w,n,nskip);		// use w for d
+    dSolveLDLT (A,w,b,n,nskip);
+    memcpy (x,b,n*sizeof(dReal));
+    dSetZero (w,n);
+
+    return;
+  }
+# ifndef dNODEBUG
+  // check restrictions on lo and hi
+  for (k=0; k<n; k++) dIASSERT (lo[k] <= 0 && hi[k] >= 0);
+# endif
+  ALLOCA (dReal,L,n*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (L == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,d,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (d == NULL) {
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,delta_x,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (delta_x == NULL) {
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,delta_w,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (delta_w == NULL) {
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,Dell,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (Dell == NULL) {
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,ell,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (ell == NULL) {
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal*,Arows,n*sizeof(dReal*));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (Arows == NULL) {
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (int,p,n*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (p == NULL) {
+      UNALLOCA(Arows);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (int,C,n*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (C == NULL) {
+      UNALLOCA(p);
+      UNALLOCA(Arows);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  int dir;
+  dReal dirf;
+
+  // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
+  ALLOCA (int,state,n*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (state == NULL) {
+      UNALLOCA(C);
+      UNALLOCA(p);
+      UNALLOCA(Arows);
+      UNALLOCA(ell);
+      UNALLOCA(Dell);
+      UNALLOCA(delta_w);
+      UNALLOCA(delta_x);
+      UNALLOCA(d);
+      UNALLOCA(L);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  // create LCP object. note that tmp is set to delta_w to save space, this
+  // optimization relies on knowledge of how tmp is used, so be careful!
+  dLCP *lcp=new dLCP(n,nub,A,x,b,w,lo,hi,L,d,Dell,ell,delta_w,state,findex,p,C,Arows);
+  nub = lcp->getNub();
+
+  // loop over all indexes nub..n-1. for index i, if x(i),w(i) satisfy the
+  // LCP conditions then i is added to the appropriate index set. otherwise
+  // x(i),w(i) is driven either +ve or -ve to force it to the valid region.
+  // as we drive x(i), x(C) is also adjusted to keep w(C) at zero.
+  // while driving x(i) we maintain the LCP conditions on the other variables
+  // 0..i-1. we do this by watching out for other x(i),w(i) values going
+  // outside the valid region, and then switching them between index sets
+  // when that happens.
+
+  for (i=nub; i<n; i++) {
+    // the index i is the driving index and indexes i+1..n-1 are "dont care",
+    // i.e. when we make changes to the system those x's will be zero and we
+    // don't care what happens to those w's. in other words, we only consider
+    // an (i+1)*(i+1) sub-problem of A*x=b+w.
+
+    // if we've hit the first friction index, we have to compute the lo and
+    // hi values based on the values of x already computed. we have been
+    // permuting the indexes, so the values stored in the findex vector are
+    // no longer valid. thus we have to temporarily unpermute the x vector. 
+    // for the purposes of this computation, 0*infinity = 0 ... so if the
+    // contact constraint's normal force is 0, there should be no tangential
+    // force applied.
+
+    if (hit_first_friction_index == 0 && findex && findex[i] >= 0) {
+      // un-permute x into delta_w, which is not being used at the moment
+      for (k=0; k<n; k++) delta_w[p[k]] = x[k];
+
+      // set lo and hi values
+      for (k=i; k<n; k++) {
+	dReal wfk = delta_w[findex[k]];
+	if (wfk == 0) {
+	  hi[k] = 0;
+	  lo[k] = 0;
+	}
+	else {
+	  hi[k] = dFabs (hi[k] * wfk);
+	  lo[k] = -hi[k];
+	}
+      }
+      hit_first_friction_index = 1;
+    }
+
+    // thus far we have not even been computing the w values for indexes
+    // greater than i, so compute w[i] now.
+    w[i] = lcp->AiC_times_qC (i,x) + lcp->AiN_times_qN (i,x) - b[i];
+
+    // if lo=hi=0 (which can happen for tangential friction when normals are
+    // 0) then the index will be assigned to set N with some state. however,
+    // set C's line has zero size, so the index will always remain in set N.
+    // with the "normal" switching logic, if w changed sign then the index
+    // would have to switch to set C and then back to set N with an inverted
+    // state. this is pointless, and also computationally expensive. to
+    // prevent this from happening, we use the rule that indexes with lo=hi=0
+    // will never be checked for set changes. this means that the state for
+    // these indexes may be incorrect, but that doesn't matter.
+
+    // see if x(i),w(i) is in a valid region
+    if (lo[i]==0 && w[i] >= 0) {
+      lcp->transfer_i_to_N (i);
+      state[i] = 0;
+    }
+    else if (hi[i]==0 && w[i] <= 0) {
+      lcp->transfer_i_to_N (i);
+      state[i] = 1;
+    }
+    else if (w[i]==0) {
+      // this is a degenerate case. by the time we get to this test we know
+      // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve,
+      // and similarly that hi > 0. this means that the line segment
+      // corresponding to set C is at least finite in extent, and we are on it.
+      // NOTE: we must call lcp->solve1() before lcp->transfer_i_to_C()
+      lcp->solve1 (delta_x,i,0,1);
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+      if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+	UNALLOCA(state);
+	UNALLOCA(C);
+	UNALLOCA(p);
+	UNALLOCA(Arows);
+	UNALLOCA(ell);
+	UNALLOCA(Dell);
+	UNALLOCA(delta_w);
+	UNALLOCA(delta_x);
+	UNALLOCA(d);
+	UNALLOCA(L);
+	return;
+      }
+#endif
+
+      lcp->transfer_i_to_C (i);
+    }
+    else {
+      // we must push x(i) and w(i)
+      for (;;) {
+	// find direction to push on x(i)
+	if (w[i] <= 0) {
+	  dir = 1;
+	  dirf = REAL(1.0);
+	}
+	else {
+	  dir = -1;
+	  dirf = REAL(-1.0);
+	}
+
+	// compute: delta_x(C) = -dir*A(C,C)\A(C,i)
+	lcp->solve1 (delta_x,i,dir);
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+	if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+	  UNALLOCA(state);
+	  UNALLOCA(C);
+	  UNALLOCA(p);
+	  UNALLOCA(Arows);
+	  UNALLOCA(ell);
+	  UNALLOCA(Dell);
+	  UNALLOCA(delta_w);
+	  UNALLOCA(delta_x);
+	  UNALLOCA(d);
+	  UNALLOCA(L);
+	  return;
+	}
+#endif
+
+	// note that delta_x[i] = dirf, but we wont bother to set it
+
+	// compute: delta_w = A*delta_x ... note we only care about
+        // delta_w(N) and delta_w(i), the rest is ignored
+	lcp->pN_equals_ANC_times_qC (delta_w,delta_x);
+	lcp->pN_plusequals_ANi (delta_w,i,dir);
+        delta_w[i] = lcp->AiC_times_qC (i,delta_x) + lcp->Aii(i)*dirf;
+
+	// find largest step we can take (size=s), either to drive x(i),w(i)
+	// to the valid LCP region or to drive an already-valid variable
+	// outside the valid region.
+
+	int cmd = 1;		// index switching command
+	int si = 0;		// si = index to switch if cmd>3
+	dReal s = -w[i]/delta_w[i];
+	if (dir > 0) {
+	  if (hi[i] < dInfinity) {
+	    dReal s2 = (hi[i]-x[i])/dirf;		// step to x(i)=hi(i)
+	    if (s2 < s) {
+	      s = s2;
+	      cmd = 3;
+	    }
+	  }
+	}
+	else {
+	  if (lo[i] > -dInfinity) {
+	    dReal s2 = (lo[i]-x[i])/dirf;		// step to x(i)=lo(i)
+	    if (s2 < s) {
+	      s = s2;
+	      cmd = 2;
+	    }
+	  }
+	}
+
+	for (k=0; k < lcp->numN(); k++) {
+	  if ((state[lcp->indexN(k)]==0 && delta_w[lcp->indexN(k)] < 0) ||
+	      (state[lcp->indexN(k)]!=0 && delta_w[lcp->indexN(k)] > 0)) {
+	    // don't bother checking if lo=hi=0
+	    if (lo[lcp->indexN(k)] == 0 && hi[lcp->indexN(k)] == 0) continue;
+	    dReal s2 = -w[lcp->indexN(k)] / delta_w[lcp->indexN(k)];
+	    if (s2 < s) {
+	      s = s2;
+	      cmd = 4;
+	      si = lcp->indexN(k);
+	    }
+	  }
+	}
+
+	for (k=nub; k < lcp->numC(); k++) {
+	  if (delta_x[lcp->indexC(k)] < 0 && lo[lcp->indexC(k)] > -dInfinity) {
+	    dReal s2 = (lo[lcp->indexC(k)]-x[lcp->indexC(k)]) /
+	      delta_x[lcp->indexC(k)];
+	    if (s2 < s) {
+	      s = s2;
+	      cmd = 5;
+	      si = lcp->indexC(k);
+	    }
+	  }
+	  if (delta_x[lcp->indexC(k)] > 0 && hi[lcp->indexC(k)] < dInfinity) {
+	    dReal s2 = (hi[lcp->indexC(k)]-x[lcp->indexC(k)]) /
+	      delta_x[lcp->indexC(k)];
+	    if (s2 < s) {
+	      s = s2;
+	      cmd = 6;
+	      si = lcp->indexC(k);
+	    }
+	  }
+	}
+
+	//static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C",
+	//			     "C->NL","C->NH"};
+	//printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i);
+
+	// if s <= 0 then we've got a problem. if we just keep going then
+	// we're going to get stuck in an infinite loop. instead, just cross
+	// our fingers and exit with the current solution.
+	if (s <= 0) {
+	  dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",s);
+	  if (i < (n-1)) {
+	    dSetZero (x+i,n-i);
+	    dSetZero (w+i,n-i);
+	  }
+	  goto done;
+	}
+
+	// apply x = x + s * delta_x
+	lcp->pC_plusequals_s_times_qC (x,s,delta_x);
+	x[i] += s * dirf;
+
+	// apply w = w + s * delta_w
+	lcp->pN_plusequals_s_times_qN (w,s,delta_w);
+	w[i] += s * delta_w[i];
+
+	// switch indexes between sets if necessary
+	switch (cmd) {
+	case 1:		// done
+	  w[i] = 0;
+	  lcp->transfer_i_to_C (i);
+	  break;
+	case 2:		// done
+	  x[i] = lo[i];
+	  state[i] = 0;
+	  lcp->transfer_i_to_N (i);
+	  break;
+	case 3:		// done
+	  x[i] = hi[i];
+	  state[i] = 1;
+	  lcp->transfer_i_to_N (i);
+	  break;
+	case 4:		// keep going
+	  w[si] = 0;
+	  lcp->transfer_i_from_N_to_C (si);
+	  break;
+	case 5:		// keep going
+	  x[si] = lo[si];
+	  state[si] = 0;
+	  lcp->transfer_i_from_C_to_N (si);
+	  break;
+	case 6:		// keep going
+	  x[si] = hi[si];
+	  state[si] = 1;
+	  lcp->transfer_i_from_C_to_N (si);
+	  break;
+	}
+
+	if (cmd <= 3) break;
+      }
+    }
+  }
+
+ done:
+  lcp->unpermute();
+  delete lcp;
+
+  UNALLOCA (L);
+  UNALLOCA (d);
+  UNALLOCA (delta_x);
+  UNALLOCA (delta_w);
+  UNALLOCA (Dell);
+  UNALLOCA (ell);
+  UNALLOCA (Arows);
+  UNALLOCA (p);
+  UNALLOCA (C);
+  UNALLOCA (state);
+}
+
+//***************************************************************************
+// accuracy and timing test
+
+extern "C" ODE_API void dTestSolveLCP()
+{
+  int n = 100;
+  int i,nskip = dPAD(n);
+#ifdef dDOUBLE
+  const dReal tol = REAL(1e-9);
+#endif
+#ifdef dSINGLE
+  const dReal tol = REAL(1e-4);
+#endif
+  printf ("dTestSolveLCP()\n");
+
+  ALLOCA (dReal,A,n*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (A == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,x,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (x == NULL) {
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,b,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (b == NULL) {
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,w,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (w == NULL) {
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,lo,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lo == NULL) {
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,hi,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (hi == NULL) {
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  ALLOCA (dReal,A2,n*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (A2 == NULL) {
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,b2,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (b2 == NULL) {
+      UNALLOCA (A2);
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,lo2,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lo2 == NULL) {
+      UNALLOCA (b2);
+      UNALLOCA (A2);
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,hi2,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (hi2 == NULL) {
+      UNALLOCA (lo2);
+      UNALLOCA (b2);
+      UNALLOCA (A2);
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,tmp1,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp1 == NULL) {
+      UNALLOCA (hi2);
+      UNALLOCA (lo2);
+      UNALLOCA (b2);
+      UNALLOCA (A2);
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA (dReal,tmp2,n*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp2 == NULL) {
+      UNALLOCA (tmp1);
+      UNALLOCA (hi2);
+      UNALLOCA (lo2);
+      UNALLOCA (b2);
+      UNALLOCA (A2);
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  double total_time = 0;
+  for (int count=0; count < 1000; count++) {
+
+    // form (A,b) = a random positive definite LCP problem
+    dMakeRandomMatrix (A2,n,n,1.0);
+    dMultiply2 (A,A2,A2,n,n,n);
+    dMakeRandomMatrix (x,n,1,1.0);
+    dMultiply0 (b,A,x,n,n,1);
+    for (i=0; i<n; i++) b[i] += (dRandReal()*REAL(0.2))-REAL(0.1);
+
+    // choose `nub' in the range 0..n-1
+    int nub = 50; //dRandInt (n);
+
+    // make limits
+    for (i=0; i<nub; i++) lo[i] = -dInfinity;
+    for (i=0; i<nub; i++) hi[i] = dInfinity;
+    //for (i=nub; i<n; i++) lo[i] = 0;
+    //for (i=nub; i<n; i++) hi[i] = dInfinity;
+    //for (i=nub; i<n; i++) lo[i] = -dInfinity;
+    //for (i=nub; i<n; i++) hi[i] = 0;
+    for (i=nub; i<n; i++) lo[i] = -(dRandReal()*REAL(1.0))-REAL(0.01);
+    for (i=nub; i<n; i++) hi[i] =  (dRandReal()*REAL(1.0))+REAL(0.01);
+
+    // set a few limits to lo=hi=0
+    /*
+    for (i=0; i<10; i++) {
+      int j = dRandInt (n-nub) + nub;
+      lo[j] = 0;
+      hi[j] = 0;
+    }
+    */
+
+    // solve the LCP. we must make copy of A,b,lo,hi (A2,b2,lo2,hi2) for
+    // SolveLCP() to permute. also, we'll clear the upper triangle of A2 to
+    // ensure that it doesn't get referenced (if it does, the answer will be
+    // wrong).
+
+    memcpy (A2,A,n*nskip*sizeof(dReal));
+    dClearUpperTriangle (A2,n);
+    memcpy (b2,b,n*sizeof(dReal));
+    memcpy (lo2,lo,n*sizeof(dReal));
+    memcpy (hi2,hi,n*sizeof(dReal));
+    dSetZero (x,n);
+    dSetZero (w,n);
+
+    dStopwatch sw;
+    dStopwatchReset (&sw);
+    dStopwatchStart (&sw);
+
+    dSolveLCP (n,A2,x,b2,w,nub,lo2,hi2,0);
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+      UNALLOCA (tmp2);
+      UNALLOCA (tmp1);
+      UNALLOCA (hi2);
+      UNALLOCA (lo2);
+      UNALLOCA (b2);
+      UNALLOCA (A2);
+      UNALLOCA (hi);
+      UNALLOCA (lo);
+      UNALLOCA (w);
+      UNALLOCA (b);
+      UNALLOCA (x);
+      UNALLOCA (A);
+      return;
+    }
+#endif
+
+    dStopwatchStop (&sw);
+    double time = dStopwatchTime(&sw);
+    total_time += time;
+    double average = total_time / double(count+1) * 1000.0;
+
+    // check the solution
+
+    dMultiply0 (tmp1,A,x,n,n,1);
+    for (i=0; i<n; i++) tmp2[i] = b[i] + w[i];
+    dReal diff = dMaxDifference (tmp1,tmp2,n,1);
+    // printf ("\tA*x = b+w, maximum difference = %.6e - %s (1)\n",diff,
+    //	    diff > tol ? "FAILED" : "passed");
+    if (diff > tol) dDebug (0,"A*x = b+w, maximum difference = %.6e",diff);
+    int n1=0,n2=0,n3=0;
+    for (i=0; i<n; i++) {
+      if (x[i]==lo[i] && w[i] >= 0) {
+	n1++;	// ok
+      }
+      else if (x[i]==hi[i] && w[i] <= 0) {
+	n2++;	// ok
+      }
+      else if (x[i] >= lo[i] && x[i] <= hi[i] && w[i] == 0) {
+	n3++;	// ok
+      }
+      else {
+	dDebug (0,"FAILED: i=%d x=%.4e w=%.4e lo=%.4e hi=%.4e",i,
+		x[i],w[i],lo[i],hi[i]);
+      }
+    }
+
+    // pacifier
+    printf ("passed: NL=%3d NH=%3d C=%3d   ",n1,n2,n3);
+    printf ("time=%10.3f ms  avg=%10.4f\n",time * 1000.0,average);
+  }
+
+  UNALLOCA (A);
+  UNALLOCA (x);
+  UNALLOCA (b);
+  UNALLOCA (w);
+  UNALLOCA (lo);
+  UNALLOCA (hi);
+  UNALLOCA (A2);
+  UNALLOCA (b2);
+  UNALLOCA (lo2);
+  UNALLOCA (hi2);
+  UNALLOCA (tmp1);
+  UNALLOCA (tmp2);
+}
Index: /code/branches/ode/ode-0.9/ode/src/lcp.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/lcp.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/lcp.h	(revision 216)
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+given (A,b,lo,hi), solve the LCP problem: A*x = b+w, where each x(i),w(i)
+satisfies one of
+	(1) x = lo, w >= 0
+	(2) x = hi, w <= 0
+	(3) lo < x < hi, w = 0
+A is a matrix of dimension n*n, everything else is a vector of size n*1.
+lo and hi can be +/- dInfinity as needed. the first `nub' variables are
+unbounded, i.e. hi and lo are assumed to be +/- dInfinity.
+
+we restrict lo(i) <= 0 and hi(i) >= 0.
+
+the original data (A,b) may be modified by this function.
+
+if the `findex' (friction index) parameter is nonzero, it points to an array
+of index values. in this case constraints that have findex[i] >= 0 are
+special. all non-special constraints are solved for, then the lo and hi values
+for the special constraints are set:
+  hi[i] = abs( hi[i] * x[findex[i]] )
+  lo[i] = -hi[i]
+and the solution continues. this mechanism allows a friction approximation
+to be implemented. the first `nub' variables are assumed to have findex < 0.
+
+*/
+
+
+#ifndef _ODE_LCP_H_
+#define _ODE_LCP_H_
+
+
+void dSolveLCP (int n, dReal *A, dReal *x, dReal *b, dReal *w,
+		int nub, dReal *lo, dReal *hi, int *findex);
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/mass.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/mass.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/mass.cpp	(revision 216)
@@ -0,0 +1,529 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/mass.h>
+#include <ode/odemath.h>
+#include <ode/matrix.h>
+
+// Local dependencies
+#include "collision_kernel.h"
+
+#define	SQR(x)			((x)*(x))						//!< Returns x square
+#define	CUBE(x)			((x)*(x)*(x))					//!< Returns x cube
+
+#define _I(i,j) I[(i)*4+(j)]
+
+
+// return 1 if ok, 0 if bad
+
+int dMassCheck (const dMass *m)
+{
+  int i;
+
+  if (m->mass <= 0) {
+    dDEBUGMSG ("mass must be > 0");
+    return 0;
+  }
+  if (!dIsPositiveDefinite (m->I,3)) {
+    dDEBUGMSG ("inertia must be positive definite");
+    return 0;
+  }
+
+  // verify that the center of mass position is consistent with the mass
+  // and inertia matrix. this is done by checking that the inertia around
+  // the center of mass is also positive definite. from the comment in
+  // dMassTranslate(), if the body is translated so that its center of mass
+  // is at the point of reference, then the new inertia is:
+  //   I + mass*crossmat(c)^2
+  // note that requiring this to be positive definite is exactly equivalent
+  // to requiring that the spatial inertia matrix
+  //   [ mass*eye(3,3)   M*crossmat(c)^T ]
+  //   [ M*crossmat(c)   I               ]
+  // is positive definite, given that I is PD and mass>0. see the theorem
+  // about partitioned PD matrices for proof.
+
+  dMatrix3 I2,chat;
+  dSetZero (chat,12);
+  dCROSSMAT (chat,m->c,4,+,-);
+  dMULTIPLY0_333 (I2,chat,chat);
+  for (i=0; i<3; i++) I2[i] = m->I[i] + m->mass*I2[i];
+  for (i=4; i<7; i++) I2[i] = m->I[i] + m->mass*I2[i];
+  for (i=8; i<11; i++) I2[i] = m->I[i] + m->mass*I2[i];
+  if (!dIsPositiveDefinite (I2,3)) {
+    dDEBUGMSG ("center of mass inconsistent with mass parameters");
+    return 0;
+  }
+  return 1;
+}
+
+
+void dMassSetZero (dMass *m)
+{
+  dAASSERT (m);
+  m->mass = REAL(0.0);
+  dSetZero (m->c,sizeof(m->c) / sizeof(dReal));
+  dSetZero (m->I,sizeof(m->I) / sizeof(dReal));
+}
+
+
+void dMassSetParameters (dMass *m, dReal themass,
+			 dReal cgx, dReal cgy, dReal cgz,
+			 dReal I11, dReal I22, dReal I33,
+			 dReal I12, dReal I13, dReal I23)
+{
+  dAASSERT (m);
+  dMassSetZero (m);
+  m->mass = themass;
+  m->c[0] = cgx;
+  m->c[1] = cgy;
+  m->c[2] = cgz;
+  m->_I(0,0) = I11;
+  m->_I(1,1) = I22;
+  m->_I(2,2) = I33;
+  m->_I(0,1) = I12;
+  m->_I(0,2) = I13;
+  m->_I(1,2) = I23;
+  m->_I(1,0) = I12;
+  m->_I(2,0) = I13;
+  m->_I(2,1) = I23;
+  dMassCheck (m);
+}
+
+
+void dMassSetSphere (dMass *m, dReal density, dReal radius)
+{
+  dMassSetSphereTotal (m, (REAL(4.0)/REAL(3.0)) * M_PI *
+			  radius*radius*radius * density, radius);
+}
+
+
+void dMassSetSphereTotal (dMass *m, dReal total_mass, dReal radius)
+{
+  dAASSERT (m);
+  dMassSetZero (m);
+  m->mass = total_mass;
+  dReal II = REAL(0.4) * total_mass * radius*radius;
+  m->_I(0,0) = II;
+  m->_I(1,1) = II;
+  m->_I(2,2) = II;
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+void dMassSetCapsule (dMass *m, dReal density, int direction,
+		      dReal radius, dReal length)
+{
+  dReal M1,M2,Ia,Ib;
+  dAASSERT (m);
+  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
+  dMassSetZero (m);
+  M1 = M_PI*radius*radius*length*density;			// cylinder mass
+  M2 = (REAL(4.0)/REAL(3.0))*M_PI*radius*radius*radius*density;	// total cap mass
+  m->mass = M1+M2;
+  Ia = M1*(REAL(0.25)*radius*radius + (REAL(1.0)/REAL(12.0))*length*length) +
+    M2*(REAL(0.4)*radius*radius + REAL(0.375)*radius*length + REAL(0.25)*length*length);
+  Ib = (M1*REAL(0.5) + M2*REAL(0.4))*radius*radius;
+  m->_I(0,0) = Ia;
+  m->_I(1,1) = Ia;
+  m->_I(2,2) = Ia;
+  m->_I(direction-1,direction-1) = Ib;
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+void dMassSetCapsuleTotal (dMass *m, dReal total_mass, int direction,
+			   dReal a, dReal b)
+{
+  dMassSetCapsule (m, 1.0, direction, a, b);
+  dMassAdjust (m, total_mass);
+}
+
+
+void dMassSetCylinder (dMass *m, dReal density, int direction,
+		       dReal radius, dReal length)
+{
+  dMassSetCylinderTotal (m, M_PI*radius*radius*length*density,
+			    direction, radius, length);
+}
+
+void dMassSetCylinderTotal (dMass *m, dReal total_mass, int direction,
+			    dReal radius, dReal length)
+{
+  dReal r2,I;
+  dAASSERT (m);
+  dUASSERT (direction >= 1 && direction <= 3,"bad direction number");
+  dMassSetZero (m);
+  r2 = radius*radius;
+  m->mass = total_mass;
+  I = total_mass*(REAL(0.25)*r2 + (REAL(1.0)/REAL(12.0))*length*length);
+  m->_I(0,0) = I;
+  m->_I(1,1) = I;
+  m->_I(2,2) = I;
+  m->_I(direction-1,direction-1) = total_mass*REAL(0.5)*r2;
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+void dMassSetBox (dMass *m, dReal density,
+		  dReal lx, dReal ly, dReal lz)
+{
+  dMassSetBoxTotal (m, lx*ly*lz*density, lx, ly, lz);
+}
+
+
+void dMassSetBoxTotal (dMass *m, dReal total_mass,
+		       dReal lx, dReal ly, dReal lz)
+{
+  dAASSERT (m);
+  dMassSetZero (m);
+  m->mass = total_mass;
+  m->_I(0,0) = total_mass/REAL(12.0) * (ly*ly + lz*lz);
+  m->_I(1,1) = total_mass/REAL(12.0) * (lx*lx + lz*lz);
+  m->_I(2,2) = total_mass/REAL(12.0) * (lx*lx + ly*ly);
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+
+
+
+
+#if dTRIMESH_ENABLED
+
+/*
+ * dMassSetTrimesh, implementation by Gero Mueller.
+ * Based on Brian Mirtich, "Fast and Accurate Computation of
+ * Polyhedral Mass Properties," journal of graphics tools, volume 1,
+ * number 2, 1996.
+*/
+void dMassSetTrimesh( dMass *m, dReal density, dGeomID g )
+{
+	dAASSERT (m);
+	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");
+
+	dMassSetZero (m);
+
+	unsigned int triangles = dGeomTriMeshGetTriangleCount( g );
+
+	dReal nx, ny, nz;
+	unsigned int i, A, B, C;
+	// face integrals
+	dReal Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
+
+	// projection integrals
+	dReal P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
+
+	dReal T0 = 0;
+	dReal T1[3] = {0., 0., 0.};
+	dReal T2[3] = {0., 0., 0.};
+	dReal TP[3] = {0., 0., 0.};
+
+	for( i = 0; i < triangles; i++ )	 	
+	{
+		dVector3 v0, v1, v2;	 	  
+		dGeomTriMeshGetTriangle( g, i, &v0, &v1, &v2);
+
+		dVector3 n, a, b;
+		dOP( a, -, v1, v0 ); 
+		dOP( b, -, v2, v0 ); 
+		dCROSS( n, =, b, a );
+		nx = fabs(n[0]);
+		ny = fabs(n[1]);
+		nz = fabs(n[2]);
+
+		if( nx > ny && nx > nz )
+			C = 0;
+		else
+			C = (ny > nz) ? 1 : 2;
+
+		A = (C + 1) % 3;
+		B = (A + 1) % 3;
+
+		// calculate face integrals
+		{
+			dReal w;
+			dReal k1, k2, k3, k4;
+
+			//compProjectionIntegrals(f);
+			{
+				dReal a0, a1, da;
+				dReal b0, b1, db;
+				dReal a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
+				dReal a1_2, a1_3, b1_2, b1_3;
+				dReal C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
+				dReal Cab, Kab, Caab, Kaab, Cabb, Kabb;
+
+				P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
+
+				for( int j = 0; j < 3; j++)
+				{
+					switch(j)
+					{
+					case 0:
+						a0 = v0[A];
+						b0 = v0[B];
+						a1 = v1[A];
+						b1 = v1[B];
+						break;
+					case 1:
+						a0 = v1[A];
+						b0 = v1[B];
+						a1 = v2[A];
+						b1 = v2[B];
+						break;
+					case 2:
+						a0 = v2[A];
+						b0 = v2[B];
+						a1 = v0[A];
+						b1 = v0[B];
+						break;
+					}
+					da = a1 - a0;
+					db = b1 - b0;
+					a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0;
+					b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0;
+					a1_2 = a1 * a1; a1_3 = a1_2 * a1; 
+					b1_2 = b1 * b1; b1_3 = b1_2 * b1;
+
+					C1 = a1 + a0;
+					Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4;
+					Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4;
+					Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2;
+					Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3;
+					Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
+					Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
+
+					P1 += db*C1;
+					Pa += db*Ca;
+					Paa += db*Caa;
+					Paaa += db*Caaa;
+					Pb += da*Cb;
+					Pbb += da*Cbb;
+					Pbbb += da*Cbbb;
+					Pab += db*(b1*Cab + b0*Kab);
+					Paab += db*(b1*Caab + b0*Kaab);
+					Pabb += da*(a1*Cabb + a0*Kabb);
+				}
+
+				P1 /= 2.0;
+				Pa /= 6.0;
+				Paa /= 12.0;
+				Paaa /= 20.0;
+				Pb /= -6.0;
+				Pbb /= -12.0;
+				Pbbb /= -20.0;
+				Pab /= 24.0;
+				Paab /= 60.0;
+				Pabb /= -60.0;
+			}			
+
+			w = - dDOT(n, v0);
+
+			k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1;
+
+			Fa = k1 * Pa;
+			Fb = k1 * Pb;
+			Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
+
+			Faa = k1 * Paa;
+			Fbb = k1 * Pbb;
+			Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb +
+				w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
+
+			Faaa = k1 * Paaa;
+			Fbbb = k1 * Pbbb;
+			Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab 
+				+ 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb
+				+ 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb)
+				+ w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
+
+			Faab = k1 * Paab;
+			Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
+			Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb
+				+ w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
+		}
+
+
+		T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));
+
+		T1[A] += n[A] * Faa;
+		T1[B] += n[B] * Fbb;
+		T1[C] += n[C] * Fcc;
+		T2[A] += n[A] * Faaa;
+		T2[B] += n[B] * Fbbb;
+		T2[C] += n[C] * Fccc;
+		TP[A] += n[A] * Faab;
+		TP[B] += n[B] * Fbbc;
+		TP[C] += n[C] * Fcca;
+	}
+
+	T1[0] /= 2; T1[1] /= 2; T1[2] /= 2;
+	T2[0] /= 3; T2[1] /= 3; T2[2] /= 3;
+	TP[0] /= 2; TP[1] /= 2; TP[2] /= 2;
+
+	m->mass = density * T0;
+	m->_I(0,0) = density * (T2[1] + T2[2]);
+	m->_I(1,1) = density * (T2[2] + T2[0]);
+	m->_I(2,2) = density * (T2[0] + T2[1]);
+	m->_I(0,1) = - density * TP[0];
+	m->_I(1,0) = - density * TP[0];
+	m->_I(2,1) = - density * TP[1];
+	m->_I(1,2) = - density * TP[1];
+	m->_I(2,0) = - density * TP[2];
+	m->_I(0,2) = - density * TP[2];
+
+	// Added to address SF bug 1729095
+	dMassTranslate( m, T1[0] / T0,  T1[1] / T0,  T1[2] / T0 );
+
+# ifndef dNODEBUG
+	dMassCheck (m);
+# endif
+}
+
+
+void dMassSetTrimeshTotal( dMass *m, dReal total_mass, dGeomID g)
+{
+  dAASSERT( m );
+  dUASSERT( g && g->type == dTriMeshClass, "argument not a trimesh" );
+  dMassSetTrimesh( m, 1.0, g );
+  dMassAdjust( m, total_mass );
+}
+
+#endif // dTRIMESH_ENABLED
+
+
+
+
+void dMassAdjust (dMass *m, dReal newmass)
+{
+  dAASSERT (m);
+  dReal scale = newmass / m->mass;
+  m->mass = newmass;
+  for (int i=0; i<3; i++) for (int j=0; j<3; j++) m->_I(i,j) *= scale;
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+void dMassTranslate (dMass *m, dReal x, dReal y, dReal z)
+{
+  // if the body is translated by `a' relative to its point of reference,
+  // the new inertia about the point of reference is:
+  //
+  //   I + mass*(crossmat(c)^2 - crossmat(c+a)^2)
+  //
+  // where c is the existing center of mass and I is the old inertia.
+
+  int i,j;
+  dMatrix3 ahat,chat,t1,t2;
+  dReal a[3];
+
+  dAASSERT (m);
+
+  // adjust inertia matrix
+  dSetZero (chat,12);
+  dCROSSMAT (chat,m->c,4,+,-);
+  a[0] = x + m->c[0];
+  a[1] = y + m->c[1];
+  a[2] = z + m->c[2];
+  dSetZero (ahat,12);
+  dCROSSMAT (ahat,a,4,+,-);
+  dMULTIPLY0_333 (t1,ahat,ahat);
+  dMULTIPLY0_333 (t2,chat,chat);
+  for (i=0; i<3; i++) for (j=0; j<3; j++)
+    m->_I(i,j) += m->mass * (t2[i*4+j]-t1[i*4+j]);
+
+  // ensure perfect symmetry
+  m->_I(1,0) = m->_I(0,1);
+  m->_I(2,0) = m->_I(0,2);
+  m->_I(2,1) = m->_I(1,2);
+
+  // adjust center of mass
+  m->c[0] += x;
+  m->c[1] += y;
+  m->c[2] += z;
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+void dMassRotate (dMass *m, const dMatrix3 R)
+{
+  // if the body is rotated by `R' relative to its point of reference,
+  // the new inertia about the point of reference is:
+  //
+  //   R * I * R'
+  //
+  // where I is the old inertia.
+
+  dMatrix3 t1;
+  dReal t2[3];
+
+  dAASSERT (m);
+
+  // rotate inertia matrix
+  dMULTIPLY2_333 (t1,m->I,R);
+  dMULTIPLY0_333 (m->I,R,t1);
+
+  // ensure perfect symmetry
+  m->_I(1,0) = m->_I(0,1);
+  m->_I(2,0) = m->_I(0,2);
+  m->_I(2,1) = m->_I(1,2);
+
+  // rotate center of mass
+  dMULTIPLY0_331 (t2,R,m->c);
+  m->c[0] = t2[0];
+  m->c[1] = t2[1];
+  m->c[2] = t2[2];
+
+# ifndef dNODEBUG
+  dMassCheck (m);
+# endif
+}
+
+
+void dMassAdd (dMass *a, const dMass *b)
+{
+  int i;
+  dAASSERT (a && b);
+  dReal denom = dRecip (a->mass + b->mass);
+  for (i=0; i<3; i++) a->c[i] = (a->c[i]*a->mass + b->c[i]*b->mass)*denom;
+  a->mass += b->mass;
+  for (i=0; i<12; i++) a->I[i] += b->I[i];
+}
Index: /code/branches/ode/ode-0.9/ode/src/mat.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/mat.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/mat.cpp	(revision 216)
@@ -0,0 +1,230 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/misc.h>
+#include <ode/matrix.h>
+#include <ode/error.h>
+#include <ode/memory.h>
+#include "mat.h"
+
+
+dMatrix::dMatrix()
+{
+  n = 0;
+  m = 0;
+  data = 0;
+}
+
+
+dMatrix::dMatrix (int rows, int cols)
+{
+  if (rows < 1 || cols < 1) dDebug (0,"bad matrix size");
+  n = rows;
+  m = cols;
+  data = (dReal*) dAlloc (n*m*sizeof(dReal));
+  dSetZero (data,n*m);
+}
+
+
+dMatrix::dMatrix (const dMatrix &a)
+{
+  n = a.n;
+  m = a.m;
+  data = (dReal*) dAlloc (n*m*sizeof(dReal));
+  memcpy (data,a.data,n*m*sizeof(dReal));
+}
+
+
+dMatrix::dMatrix (int rows, int cols,
+		    dReal *_data, int rowskip, int colskip)
+{
+  if (rows < 1 || cols < 1) dDebug (0,"bad matrix size");
+  n = rows;
+  m = cols;
+  data = (dReal*) dAlloc (n*m*sizeof(dReal));
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<m; j++) data[i*m+j] = _data[i*rowskip + j*colskip];
+  }
+}
+
+
+dMatrix::~dMatrix()
+{
+  if (data) dFree (data,n*m*sizeof(dReal));
+}
+
+
+dReal & dMatrix::operator () (int i, int j)
+{
+  if (i < 0 || i >= n || j < 0 || j >= m) dDebug (0,"bad matrix (i,j)");
+  return data [i*m+j];
+}
+
+
+void dMatrix::operator= (const dMatrix &a)
+{
+  if (data) dFree (data,n*m*sizeof(dReal));
+  n = a.n;
+  m = a.m;
+  if (n > 0 && m > 0) {
+    data = (dReal*) dAlloc (n*m*sizeof(dReal));
+    memcpy (data,a.data,n*m*sizeof(dReal));
+  }
+  else data = 0;
+}
+
+
+void dMatrix::operator= (dReal a)
+{
+  for (int i=0; i<n*m; i++) data[i] = a;
+}
+
+
+dMatrix dMatrix::transpose()
+{
+  dMatrix r (m,n);
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<m; j++) r.data[j*n+i] = data[i*m+j];
+  }
+  return r;
+}
+
+
+dMatrix dMatrix::select (int np, int *p, int nq, int *q)
+{
+  if (np < 1 || nq < 1) dDebug (0,"Matrix select, bad index array sizes");
+  dMatrix r (np,nq);
+  for (int i=0; i<np; i++) {
+    for (int j=0; j<nq; j++) {
+      if (p[i] < 0 || p[i] >= n || q[i] < 0 || q[i] >= m)
+	dDebug (0,"Matrix select, bad index arrays");
+      r.data[i*nq+j] = data[p[i]*m+q[j]];
+    }
+  }
+  return r;
+}
+
+
+dMatrix dMatrix::operator + (const dMatrix &a)
+{
+  if (n != a.n || m != a.m) dDebug (0,"matrix +, mismatched sizes");
+  dMatrix r (n,m);
+  for (int i=0; i<n*m; i++) r.data[i] = data[i] + a.data[i];
+  return r;
+}
+
+
+dMatrix dMatrix::operator - (const dMatrix &a)
+{
+  if (n != a.n || m != a.m) dDebug (0,"matrix -, mismatched sizes");
+  dMatrix r (n,m);
+  for (int i=0; i<n*m; i++) r.data[i] = data[i] - a.data[i];
+  return r;
+}
+
+
+dMatrix dMatrix::operator - ()
+{
+  dMatrix r (n,m);
+  for (int i=0; i<n*m; i++) r.data[i] = -data[i];
+  return r;
+}
+
+
+dMatrix dMatrix::operator * (const dMatrix &a)
+{
+  if (m != a.n) dDebug (0,"matrix *, mismatched sizes");
+  dMatrix r (n,a.m);
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<a.m; j++) {
+      dReal sum = 0;
+      for (int k=0; k<m; k++) sum += data[i*m+k] * a.data[k*a.m+j];
+      r.data [i*a.m+j] = sum;
+    }
+  }
+  return r;
+}
+
+
+void dMatrix::operator += (const dMatrix &a)
+{
+  if (n != a.n || m != a.m) dDebug (0,"matrix +=, mismatched sizes");
+  for (int i=0; i<n*m; i++) data[i] += a.data[i];
+}
+
+
+void dMatrix::operator -= (const dMatrix &a)
+{
+  if (n != a.n || m != a.m) dDebug (0,"matrix -=, mismatched sizes");
+  for (int i=0; i<n*m; i++) data[i] -= a.data[i];
+}
+
+
+void dMatrix::clearUpperTriangle()
+{
+  if (n != m) dDebug (0,"clearUpperTriangle() only works on square matrices");
+  for (int i=0; i<n; i++) {
+    for (int j=i+1; j<m; j++) data[i*m+j] = 0;
+  }
+}
+
+
+void dMatrix::clearLowerTriangle()
+{
+  if (n != m) dDebug (0,"clearLowerTriangle() only works on square matrices");
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<i; j++) data[i*m+j] = 0;
+  }
+}
+
+
+void dMatrix::makeRandom (dReal range)
+{
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<m; j++)
+      data[i*m+j] = (dRandReal()*REAL(2.0)-REAL(1.0))*range;
+  }
+}
+
+
+void dMatrix::print (char *fmt, FILE *f)
+{
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<m; j++) fprintf (f,fmt,data[i*m+j]);
+    fprintf (f,"\n");
+  }
+}
+
+
+dReal dMatrix::maxDifference (const dMatrix &a)
+{
+  if (n != a.n || m != a.m) dDebug (0,"maxDifference(), mismatched sizes");
+  dReal max = 0;
+  for (int i=0; i<n; i++) {
+    for (int j=0; j<m; j++) {
+      dReal diff = dFabs(data[i*m+j] - a.data[i*m+j]);
+      if (diff > max) max = diff;
+    }
+  }
+  return max;
+}
Index: /code/branches/ode/ode-0.9/ode/src/mat.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/mat.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/mat.h	(revision 216)
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// matrix class. this is mostly for convenience in the testing code, it is
+// not optimized at all. correctness is much more importance here.
+
+#ifndef _ODE_MAT_H_
+#define _ODE_MAT_H_
+
+#include <ode/common.h>
+
+
+class dMatrix {
+  int n,m;		// matrix dimension, n,m >= 0
+  dReal *data;		// if nonzero, n*m elements allocated on the heap
+
+public:
+  // constructors, destructors
+  dMatrix();				// make default 0x0 matrix
+  dMatrix (int rows, int cols);		// construct zero matrix of given size
+  dMatrix (const dMatrix &);		// construct copy of given matrix
+  // create copy of given data - element (i,j) is data[i*rowskip+j*colskip]
+  dMatrix (int rows, int cols, dReal *_data, int rowskip, int colskip);
+  ~dMatrix();				// destructor
+
+  // data movement
+  dReal & operator () (int i, int j);	// reference an element
+  void operator= (const dMatrix &);	// matrix = matrix
+  void operator= (dReal);		// matrix = scalar
+  dMatrix transpose();			// return transposed matrix
+  // return a permuted submatrix of this matrix, made up of the rows in p
+  // and the columns in q. p has np elements, q has nq elements.
+  dMatrix select (int np, int *p, int nq, int *q);
+
+  // operators
+  dMatrix operator + (const dMatrix &);
+  dMatrix operator - (const dMatrix &);
+  dMatrix operator - ();
+  dMatrix operator * (const dMatrix &);
+  void operator += (const dMatrix &);
+  void operator -= (const dMatrix &);
+
+  // utility
+  void clearUpperTriangle();
+  void clearLowerTriangle();
+  void makeRandom (dReal range);
+  void print (char *fmt = "%10.4f ", FILE *f=stdout);
+  dReal maxDifference (const dMatrix &);
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/matrix.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/matrix.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/matrix.cpp	(revision 216)
@@ -0,0 +1,358 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/common.h>
+#include <ode/matrix.h>
+
+// misc defines
+#define ALLOCA dALLOCA16
+
+
+void dSetZero (dReal *a, int n)
+{
+  dAASSERT (a && n >= 0);
+  while (n > 0) {
+    *(a++) = 0;
+    n--;
+  }
+}
+
+
+void dSetValue (dReal *a, int n, dReal value)
+{
+  dAASSERT (a && n >= 0);
+  while (n > 0) {
+    *(a++) = value;
+    n--;
+  }
+}
+
+
+void dMultiply0 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r)
+{
+  int i,j,k,qskip,rskip,rpad;
+  dAASSERT (A && B && C && p>0 && q>0 && r>0);
+  qskip = dPAD(q);
+  rskip = dPAD(r);
+  rpad = rskip - r;
+  dReal sum;
+  const dReal *b,*c,*bb;
+  bb = B;
+  for (i=p; i; i--) {
+    for (j=0 ; j<r; j++) {
+      c = C + j;
+      b = bb;
+      sum = 0;
+      for (k=q; k; k--, c+=rskip) sum += (*(b++))*(*c);
+      *(A++) = sum; 
+    }
+    A += rpad;
+    bb += qskip;
+  }
+}
+
+
+void dMultiply1 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r)
+{
+  int i,j,k,pskip,rskip;
+  dReal sum;
+  dAASSERT (A && B && C && p>0 && q>0 && r>0);
+  pskip = dPAD(p);
+  rskip = dPAD(r);
+  for (i=0; i<p; i++) {
+    for (j=0; j<r; j++) {
+      sum = 0;
+      for (k=0; k<q; k++) sum += B[i+k*pskip] * C[j+k*rskip];
+      A[i*rskip+j] = sum;
+    }
+  }
+}
+
+
+void dMultiply2 (dReal *A, const dReal *B, const dReal *C, int p, int q, int r)
+{
+  int i,j,k,z,rpad,qskip;
+  dReal sum;
+  const dReal *bb,*cc;
+  dAASSERT (A && B && C && p>0 && q>0 && r>0);
+  rpad = dPAD(r) - r;
+  qskip = dPAD(q);
+  bb = B;
+  for (i=p; i; i--) {
+    cc = C;
+    for (j=r; j; j--) {
+      z = 0;
+      sum = 0;
+      for (k=q; k; k--,z++) sum += bb[z] * cc[z];
+      *(A++) = sum; 
+      cc += qskip;
+    }
+    A += rpad;
+    bb += qskip;
+  }
+}
+
+
+int dFactorCholesky (dReal *A, int n)
+{
+  int i,j,k,nskip;
+  dReal sum,*a,*b,*aa,*bb,*cc,*recip;
+  dAASSERT (n > 0 && A);
+  nskip = dPAD (n);
+  recip = (dReal*) ALLOCA (n * sizeof(dReal));
+  aa = A;
+  for (i=0; i<n; i++) {
+    bb = A;
+    cc = A + i*nskip;
+    for (j=0; j<i; j++) {
+      sum = *cc;
+      a = aa;
+      b = bb;
+      for (k=j; k; k--) sum -= (*(a++))*(*(b++));
+      *cc = sum * recip[j];
+      bb += nskip;
+      cc++;
+    }
+    sum = *cc;
+    a = aa;
+    for (k=i; k; k--, a++) sum -= (*a)*(*a);
+    if (sum <= REAL(0.0)) return 0;
+    *cc = dSqrt(sum);
+    recip[i] = dRecip (*cc);
+    aa += nskip;
+  }
+  return 1;
+}
+
+
+void dSolveCholesky (const dReal *L, dReal *b, int n)
+{
+  int i,k,nskip;
+  dReal sum,*y;
+  dAASSERT (n > 0 && L && b);
+  nskip = dPAD (n);
+  y = (dReal*) ALLOCA (n*sizeof(dReal));
+  for (i=0; i<n; i++) {
+    sum = 0;
+    for (k=0; k < i; k++) sum += L[i*nskip+k]*y[k];
+    y[i] = (b[i]-sum)/L[i*nskip+i];
+  }
+  for (i=n-1; i >= 0; i--) {
+    sum = 0;
+    for (k=i+1; k < n; k++) sum += L[k*nskip+i]*b[k];
+    b[i] = (y[i]-sum)/L[i*nskip+i];
+  }
+}
+
+
+int dInvertPDMatrix (const dReal *A, dReal *Ainv, int n)
+{
+  int i,j,nskip;
+  dReal *L,*x;
+  dAASSERT (n > 0 && A && Ainv);
+  nskip = dPAD (n);
+  L = (dReal*) ALLOCA (nskip*n*sizeof(dReal));
+  memcpy (L,A,nskip*n*sizeof(dReal));
+  x = (dReal*) ALLOCA (n*sizeof(dReal));
+  if (dFactorCholesky (L,n)==0) return 0;
+  dSetZero (Ainv,n*nskip);	// make sure all padding elements set to 0
+  for (i=0; i<n; i++) {
+    for (j=0; j<n; j++) x[j] = 0;
+    x[i] = 1;
+    dSolveCholesky (L,x,n);
+    for (j=0; j<n; j++) Ainv[j*nskip+i] = x[j];
+  }
+  return 1;  
+}
+
+
+int dIsPositiveDefinite (const dReal *A, int n)
+{
+  dReal *Acopy;
+  dAASSERT (n > 0 && A);
+  int nskip = dPAD (n);
+  Acopy = (dReal*) ALLOCA (nskip*n * sizeof(dReal));
+  memcpy (Acopy,A,nskip*n * sizeof(dReal));
+  return dFactorCholesky (Acopy,n);
+}
+
+
+/***** this has been replaced by a faster version
+void dSolveL1T (const dReal *L, dReal *b, int n, int nskip)
+{
+  int i,j;
+  dAASSERT (L && b && n >= 0 && nskip >= n);
+  dReal sum;
+  for (i=n-2; i>=0; i--) {
+    sum = 0;
+    for (j=i+1; j<n; j++) sum += L[j*nskip+i]*b[j];
+    b[i] -= sum;
+  }
+}
+*/
+
+
+void dVectorScale (dReal *a, const dReal *d, int n)
+{
+  dAASSERT (a && d && n >= 0);
+  for (int i=0; i<n; i++) a[i] *= d[i];
+}
+
+
+void dSolveLDLT (const dReal *L, const dReal *d, dReal *b, int n, int nskip)
+{
+  dAASSERT (L && d && b && n > 0 && nskip >= n);
+  dSolveL1 (L,b,n,nskip);
+  dVectorScale (b,d,n);
+  dSolveL1T (L,b,n,nskip);
+}
+
+
+void dLDLTAddTL (dReal *L, dReal *d, const dReal *a, int n, int nskip)
+{
+  int j,p;
+  dReal *W1,*W2,W11,W21,alpha1,alpha2,alphanew,gamma1,gamma2,k1,k2,Wp,ell,dee;
+  dAASSERT (L && d && a && n > 0 && nskip >= n);
+
+  if (n < 2) return;
+  W1 = (dReal*) ALLOCA (n*sizeof(dReal));
+  W2 = (dReal*) ALLOCA (n*sizeof(dReal));
+
+  W1[0] = 0;
+  W2[0] = 0;
+  for (j=1; j<n; j++) W1[j] = W2[j] = a[j] * M_SQRT1_2;
+  W11 = (REAL(0.5)*a[0]+1)*M_SQRT1_2;
+  W21 = (REAL(0.5)*a[0]-1)*M_SQRT1_2;
+
+  alpha1=1;
+  alpha2=1;
+
+  dee = d[0];
+  alphanew = alpha1 + (W11*W11)*dee;
+  dee /= alphanew;
+  gamma1 = W11 * dee;
+  dee *= alpha1;
+  alpha1 = alphanew;
+  alphanew = alpha2 - (W21*W21)*dee;
+  dee /= alphanew;
+  gamma2 = W21 * dee;
+  alpha2 = alphanew;
+  k1 = REAL(1.0) - W21*gamma1;
+  k2 = W21*gamma1*W11 - W21;
+  for (p=1; p<n; p++) {
+    Wp = W1[p];
+    ell = L[p*nskip];
+    W1[p] =    Wp - W11*ell;
+    W2[p] = k1*Wp +  k2*ell;
+  }
+
+  for (j=1; j<n; j++) {
+    dee = d[j];
+    alphanew = alpha1 + (W1[j]*W1[j])*dee;
+    dee /= alphanew;
+    gamma1 = W1[j] * dee;
+    dee *= alpha1;
+    alpha1 = alphanew;
+    alphanew = alpha2 - (W2[j]*W2[j])*dee;
+    dee /= alphanew;
+    gamma2 = W2[j] * dee;
+    dee *= alpha2;
+    d[j] = dee;
+    alpha2 = alphanew;
+
+    k1 = W1[j];
+    k2 = W2[j];
+    for (p=j+1; p<n; p++) {
+      ell = L[p*nskip+j];
+      Wp = W1[p] - k1 * ell;
+      ell += gamma1 * Wp;
+      W1[p] = Wp;
+      Wp = W2[p] - k2 * ell;
+      ell -= gamma2 * Wp;
+      W2[p] = Wp;
+      L[p*nskip+j] = ell;
+    }
+  }
+}
+
+
+// macros for dLDLTRemove() for accessing A - either access the matrix
+// directly or access it via row pointers. we are only supposed to reference
+// the lower triangle of A (it is symmetric), but indexes i and j come from
+// permutation vectors so they are not predictable. so do a test on the
+// indexes - this should not slow things down too much, as we don't do this
+// in an inner loop.
+
+#define _GETA(i,j) (A[i][j])
+//#define _GETA(i,j) (A[(i)*nskip+(j)])
+#define GETA(i,j) ((i > j) ? _GETA(i,j) : _GETA(j,i))
+
+
+void dLDLTRemove (dReal **A, const int *p, dReal *L, dReal *d,
+		  int n1, int n2, int r, int nskip)
+{
+  int i;
+  dAASSERT(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
+	   n1 >= n2 && nskip >= n1);
+  #ifndef dNODEBUG
+  for (i=0; i<n2; i++) dIASSERT(p[i] >= 0 && p[i] < n1);
+  #endif
+
+  if (r==n2-1) {
+    return;		// deleting last row/col is easy
+  }
+  else if (r==0) {
+    dReal *a = (dReal*) ALLOCA (n2 * sizeof(dReal));
+    for (i=0; i<n2; i++) a[i] = -GETA(p[i],p[0]);
+    a[0] += REAL(1.0);
+    dLDLTAddTL (L,d,a,n2,nskip);
+  }
+  else {
+    dReal *t = (dReal*) ALLOCA (r * sizeof(dReal));
+    dReal *a = (dReal*) ALLOCA ((n2-r) * sizeof(dReal));
+    for (i=0; i<r; i++) t[i] = L[r*nskip+i] / d[i];
+    for (i=0; i<(n2-r); i++)
+      a[i] = dDot(L+(r+i)*nskip,t,r) - GETA(p[r+i],p[r]);
+    a[0] += REAL(1.0);
+    dLDLTAddTL (L + r*nskip+r, d+r, a, n2-r, nskip);
+  }
+
+  // snip out row/column r from L and d
+  dRemoveRowCol (L,n2,nskip,r);
+  if (r < (n2-1)) memmove (d+r,d+r+1,(n2-r-1)*sizeof(dReal));
+}
+
+
+void dRemoveRowCol (dReal *A, int n, int nskip, int r)
+{
+  int i;
+  dAASSERT(A && n > 0 && nskip >= n && r >= 0 && r < n);
+  if (r >= n-1) return;
+  if (r > 0) {
+    for (i=0; i<r; i++)
+      memmove (A+i*nskip+r,A+i*nskip+r+1,(n-r-1)*sizeof(dReal));
+    for (i=r; i<(n-1); i++)
+      memcpy (A+i*nskip,A+i*nskip+nskip,r*sizeof(dReal));
+  }
+  for (i=r; i<(n-1); i++)
+    memcpy (A+i*nskip+r,A+i*nskip+nskip+r+1,(n-r-1)*sizeof(dReal));
+}
Index: /code/branches/ode/ode-0.9/ode/src/memory.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/memory.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/memory.cpp	(revision 216)
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/memory.h>
+#include <ode/error.h>
+
+
+static dAllocFunction *allocfn = 0;
+static dReallocFunction *reallocfn = 0;
+static dFreeFunction *freefn = 0;
+
+
+
+void dSetAllocHandler (dAllocFunction *fn)
+{
+  allocfn = fn;
+}
+
+
+void dSetReallocHandler (dReallocFunction *fn)
+{
+  reallocfn = fn;
+}
+
+
+void dSetFreeHandler (dFreeFunction *fn)
+{
+  freefn = fn;
+}
+
+
+dAllocFunction *dGetAllocHandler()
+{
+  return allocfn;
+}
+
+
+dReallocFunction *dGetReallocHandler()
+{
+  return reallocfn;
+}
+
+
+dFreeFunction *dGetFreeHandler()
+{
+  return freefn;
+}
+
+
+void * dAlloc (size_t size)
+{
+  if (allocfn) return allocfn (size); else return malloc (size);
+}
+
+
+void * dRealloc (void *ptr, size_t oldsize, size_t newsize)
+{
+  if (reallocfn) return reallocfn (ptr,oldsize,newsize);
+  else return realloc (ptr,newsize);
+}
+
+
+void dFree (void *ptr, size_t size)
+{
+  if (!ptr) return;
+  if (freefn) freefn (ptr,size); else free (ptr);
+}
Index: /code/branches/ode/ode-0.9/ode/src/misc.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/misc.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/misc.cpp	(revision 216)
@@ -0,0 +1,169 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/misc.h>
+#include <ode/matrix.h>
+
+//****************************************************************************
+// random numbers
+
+static unsigned long seed = 0;
+
+unsigned long dRand()
+{
+  seed = (1664525L*seed + 1013904223L) & 0xffffffff;
+  return seed;
+}
+
+
+unsigned long  dRandGetSeed()
+{
+  return seed;
+}
+
+
+void dRandSetSeed (unsigned long s)
+{
+  seed = s;
+}
+
+
+int dTestRand()
+{
+  unsigned long oldseed = seed;
+  int ret = 1;
+  seed = 0;
+  if (dRand() != 0x3c6ef35f || dRand() != 0x47502932 ||
+      dRand() != 0xd1ccf6e9 || dRand() != 0xaaf95334 ||
+      dRand() != 0x6252e503) ret = 0;
+  seed = oldseed;
+  return ret;
+}
+
+
+// adam's all-int straightforward(?) dRandInt (0..n-1)
+int dRandInt (int n)
+{
+  // seems good; xor-fold and modulus
+  const unsigned long un = n;
+  unsigned long r = dRand();
+  
+  // note: probably more aggressive than it needs to be -- might be
+  //       able to get away without one or two of the innermost branches.
+  if (un <= 0x00010000UL) {
+    r ^= (r >> 16);
+    if (un <= 0x00000100UL) {
+      r ^= (r >> 8);
+      if (un <= 0x00000010UL) {
+        r ^= (r >> 4);
+        if (un <= 0x00000004UL) {
+          r ^= (r >> 2);
+          if (un <= 0x00000002UL) {
+            r ^= (r >> 1);
+          }
+        }
+      }
+    }
+  }
+
+  return (int) (r % un);    
+}
+
+
+dReal dRandReal()
+{
+  return ((dReal) dRand()) / ((dReal) 0xffffffff);
+}
+
+//****************************************************************************
+// matrix utility stuff
+
+void dPrintMatrix (const dReal *A, int n, int m, char *fmt, FILE *f)
+{
+  int i,j;
+  int skip = dPAD(m);
+  for (i=0; i<n; i++) {
+    for (j=0; j<m; j++) fprintf (f,fmt,A[i*skip+j]);
+    fprintf (f,"\n");
+  }
+}
+
+
+void dMakeRandomVector (dReal *A, int n, dReal range)
+{
+  int i;
+  for (i=0; i<n; i++) A[i] = (dRandReal()*REAL(2.0)-REAL(1.0))*range;
+}
+
+
+void dMakeRandomMatrix (dReal *A, int n, int m, dReal range)
+{
+  int i,j;
+  int skip = dPAD(m);
+  dSetZero (A,n*skip);
+  for (i=0; i<n; i++) {
+    for (j=0; j<m; j++) A[i*skip+j] = (dRandReal()*REAL(2.0)-REAL(1.0))*range;
+  }
+}
+
+
+void dClearUpperTriangle (dReal *A, int n)
+{
+  int i,j;
+  int skip = dPAD(n);
+  for (i=0; i<n; i++) {
+    for (j=i+1; j<n; j++) A[i*skip+j] = 0;
+  }
+}
+
+
+dReal dMaxDifference (const dReal *A, const dReal *B, int n, int m)
+{
+  int i,j;
+  int skip = dPAD(m);
+  dReal diff,max;
+  max = 0;
+  for (i=0; i<n; i++) {
+    for (j=0; j<m; j++) {
+      diff = dFabs(A[i*skip+j] - B[i*skip+j]);
+      if (diff > max) max = diff;
+    }
+  }
+  return max;
+}
+
+
+dReal dMaxDifferenceLowerTriangle (const dReal *A, const dReal *B, int n)
+{
+  int i,j;
+  int skip = dPAD(n);
+  dReal diff,max;
+  max = 0;
+  for (i=0; i<n; i++) {
+    for (j=0; j<=i; j++) {
+      diff = dFabs(A[i*skip+j] - B[i*skip+j]);
+      if (diff > max) max = diff;
+    }
+  }
+  return max;
+}
Index: /code/branches/ode/ode-0.9/ode/src/objects.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/objects.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/objects.h	(revision 216)
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// object, body, and world structs.
+
+
+#ifndef _ODE_OBJECT_H_
+#define _ODE_OBJECT_H_
+
+#include <ode/common.h>
+#include <ode/memory.h>
+#include <ode/mass.h>
+#include "array.h"
+
+
+// some body flags
+
+enum {
+  dxBodyFlagFiniteRotation = 1,		// use finite rotations
+  dxBodyFlagFiniteRotationAxis = 2,	// use finite rotations only along axis
+  dxBodyDisabled = 4,			// body is disabled
+  dxBodyNoGravity = 8,			// body is not influenced by gravity
+  dxBodyAutoDisable = 16		// enable auto-disable on body
+};
+
+
+// base class that does correct object allocation / deallocation
+
+struct dBase {
+  void *operator new (size_t size) { return dAlloc (size); }
+  void operator delete (void *ptr, size_t size) { dFree (ptr,size); }
+  void *operator new[] (size_t size) { return dAlloc (size); }
+  void operator delete[] (void *ptr, size_t size) { dFree (ptr,size); }
+};
+
+
+// base class for bodies and joints
+
+struct dObject : public dBase {
+  dxWorld *world;		// world this object is in
+  dObject *next;		// next object of this type in list
+  dObject **tome;		// pointer to previous object's next ptr
+  void *userdata;		// user settable data
+  int tag;			// used by dynamics algorithms
+};
+
+
+// auto disable parameters
+struct dxAutoDisable {
+  dReal idle_time;		// time the body needs to be idle to auto-disable it
+  int idle_steps;		// steps the body needs to be idle to auto-disable it
+  dReal linear_average_threshold;   // linear (squared) average velocity threshold
+  dReal angular_average_threshold;  // angular (squared) average velocity threshold
+  unsigned int average_samples;     // size of the average_lvel and average_avel buffers
+};
+
+
+// quick-step parameters
+struct dxQuickStepParameters {
+  int num_iterations;		// number of SOR iterations to perform
+  dReal w;			// the SOR over-relaxation parameter
+};
+
+
+// contact generation parameters
+struct dxContactParameters {
+  dReal max_vel;		// maximum correcting velocity
+  dReal min_depth;		// thickness of 'surface layer'
+};
+
+
+
+// position vector and rotation matrix for geometry objects that are not
+// connected to bodies.
+
+struct dxPosR {
+  dVector3 pos;
+  dMatrix3 R;
+};
+
+struct dxBody : public dObject {
+  dxJointNode *firstjoint;	// list of attached joints
+  int flags;			// some dxBodyFlagXXX flags
+  dGeomID geom;			// first collision geom associated with body
+  dMass mass;			// mass parameters about POR
+  dMatrix3 invI;		// inverse of mass.I
+  dReal invMass;		// 1 / mass.mass
+  dxPosR posr;			// position and orientation of point of reference
+  dQuaternion q;		// orientation quaternion
+  dVector3 lvel,avel;		// linear and angular velocity of POR
+  dVector3 facc,tacc;		// force and torque accumulators
+  dVector3 finite_rot_axis;	// finite rotation axis, unit length or 0=none
+
+  // auto-disable information
+  dxAutoDisable adis;		// auto-disable parameters
+  dReal adis_timeleft;		// time left to be idle
+  int adis_stepsleft;		// steps left to be idle
+  dVector3* average_lvel_buffer;      // buffer for the linear average velocity calculation
+  dVector3* average_avel_buffer;      // buffer for the angular average velocity calculation
+  unsigned int average_counter;      // counter/index to fill the average-buffers
+  int average_ready;        // indicates ( with = 1 ), if the Body's buffers are ready for average-calculations
+};
+
+
+struct dxWorld : public dBase {
+  dxBody *firstbody;		// body linked list
+  dxJoint *firstjoint;		// joint linked list
+  int nb,nj;			// number of bodies and joints in lists
+  dVector3 gravity;		// gravity vector (m/s/s)
+  dReal global_erp;		// global error reduction parameter
+  dReal global_cfm;		// global costraint force mixing parameter
+  dxAutoDisable adis;		// auto-disable parameters
+  int adis_flag;		// auto-disable flag for new bodies
+  dxQuickStepParameters qs;
+  dxContactParameters contactp;
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/obstack.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/obstack.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/obstack.cpp	(revision 216)
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/common.h>
+#include <ode/error.h>
+#include <ode/memory.h>
+#include "obstack.h"
+
+//****************************************************************************
+// macros and constants
+
+#define ROUND_UP_OFFSET_TO_EFFICIENT_SIZE(arena,ofs) \
+  ofs = (size_t) (dEFFICIENT_SIZE( ((intP)(arena)) + ofs ) - ((intP)(arena)) );
+
+#define MAX_ALLOC_SIZE \
+  ((size_t)(dOBSTACK_ARENA_SIZE - sizeof (Arena) - EFFICIENT_ALIGNMENT + 1))
+
+//****************************************************************************
+// dObStack
+
+dObStack::dObStack()
+{
+  first = 0;
+  last = 0;
+  current_arena = 0;
+  current_ofs = 0;
+}
+
+
+dObStack::~dObStack()
+{
+  // free all arenas
+  Arena *a,*nexta;
+  a = first;
+  while (a) {
+    nexta = a->next;
+    dFree (a,dOBSTACK_ARENA_SIZE);
+    a = nexta;
+  }
+}
+
+
+void *dObStack::alloc (int num_bytes)
+{
+  if ((size_t)num_bytes > MAX_ALLOC_SIZE) dDebug (0,"num_bytes too large");
+
+  // allocate or move to a new arena if necessary
+  if (!first) {
+    // allocate the first arena if necessary
+    first = last = (Arena *) dAlloc (dOBSTACK_ARENA_SIZE);
+    first->next = 0;
+    first->used = sizeof (Arena);
+    ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (first,first->used);
+  }
+  else {
+    // we already have one or more arenas, see if a new arena must be used
+    if ((last->used + num_bytes) > dOBSTACK_ARENA_SIZE) {
+      if (!last->next) {
+	last->next = (Arena *) dAlloc (dOBSTACK_ARENA_SIZE);
+	last->next->next = 0;
+      }
+      last = last->next;
+      last->used = sizeof (Arena);
+      ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (last,last->used);
+    }
+  }
+
+  // allocate an area in the arena
+  char *c = ((char*) last) + last->used;
+  last->used += num_bytes;
+  ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (last,last->used);
+  return c;
+}
+
+
+void dObStack::freeAll()
+{
+  last = first;
+  if (first) {
+    first->used = sizeof(Arena);
+    ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (first,first->used);
+  }
+}
+
+
+void *dObStack::rewind()
+{
+  current_arena = first;
+  current_ofs = sizeof (Arena);
+  if (current_arena) {
+    ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current_arena,current_ofs)
+    return ((char*) current_arena) + current_ofs;
+  }
+  else return 0;
+}
+
+
+void *dObStack::next (int num_bytes)
+{
+  // this functions like alloc, except that no new storage is ever allocated
+  if (!current_arena) return 0;
+  current_ofs += num_bytes;
+  ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current_arena,current_ofs);
+  if (current_ofs >= current_arena->used) {
+    current_arena = current_arena->next;
+    if (!current_arena) return 0;
+    current_ofs = sizeof (Arena);
+    ROUND_UP_OFFSET_TO_EFFICIENT_SIZE (current_arena,current_ofs);
+  }
+  return ((char*) current_arena) + current_ofs;
+}
Index: /code/branches/ode/ode-0.9/ode/src/obstack.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/obstack.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/obstack.h	(revision 216)
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_OBSTACK_H_
+#define _ODE_OBSTACK_H_
+
+#include "objects.h" 
+
+// each obstack Arena pointer points to a block of this many bytes
+#define dOBSTACK_ARENA_SIZE 16384
+
+
+struct dObStack : public dBase {
+  struct Arena {
+    Arena *next;	// next arena in linked list
+    size_t used;		// total number of bytes used in this arena, counting
+  };			//   this header
+
+  Arena *first;		// head of the arena linked list. 0 if no arenas yet
+  Arena *last;		// arena where blocks are currently being allocated
+
+  // used for iterator
+  Arena *current_arena;
+  size_t current_ofs;
+
+  dObStack();
+  ~dObStack();
+
+  void *alloc (int num_bytes);
+  // allocate a block in the last arena, allocating a new arena if necessary.
+  // it is a runtime error if num_bytes is larger than the arena size.
+
+  void freeAll();
+  // free all blocks in all arenas. this does not deallocate the arenas
+  // themselves, so future alloc()s will reuse them.
+
+  void *rewind();
+  // rewind the obstack iterator, and return the address of the first
+  // allocated block. return 0 if there are no allocated blocks.
+
+  void *next (int num_bytes);
+  // return the address of the next allocated block. 'num_bytes' is the size
+  // of the previous block. this returns null if there are no more arenas.
+  // the sequence of 'num_bytes' parameters passed to next() during a
+  // traversal of the list must exactly match the parameters passed to alloc().
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/ode.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/ode.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/ode.cpp	(revision 216)
@@ -0,0 +1,1732 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+// this source file is mostly concerned with the data structures, not the
+// numerics.
+
+#include "objects.h"
+#include <ode/ode.h>
+#include "joint.h"
+#include <ode/odemath.h>
+#include <ode/matrix.h>
+#include "step.h"
+#include "quickstep.h"
+#include "util.h"
+#include <ode/memory.h>
+#include <ode/error.h>
+
+// misc defines
+#define ALLOCA dALLOCA16
+
+//****************************************************************************
+// utility
+
+static inline void initObject (dObject *obj, dxWorld *w)
+{
+  obj->world = w;
+  obj->next = 0;
+  obj->tome = 0;
+  obj->userdata = 0;
+  obj->tag = 0;
+}
+
+
+// add an object `obj' to the list who's head pointer is pointed to by `first'.
+
+static inline void addObjectToList (dObject *obj, dObject **first)
+{
+  obj->next = *first;
+  obj->tome = first;
+  if (*first) (*first)->tome = &obj->next;
+  (*first) = obj;
+}
+
+
+// remove the object from the linked list
+
+static inline void removeObjectFromList (dObject *obj)
+{
+  if (obj->next) obj->next->tome = obj->tome;
+  *(obj->tome) = obj->next;
+  // safeguard
+  obj->next = 0;
+  obj->tome = 0;
+}
+
+
+// remove the joint from neighbour lists of all connected bodies
+
+static void removeJointReferencesFromAttachedBodies (dxJoint *j)
+{
+  for (int i=0; i<2; i++) {
+    dxBody *body = j->node[i].body;
+    if (body) {
+      dxJointNode *n = body->firstjoint;
+      dxJointNode *last = 0;
+      while (n) {
+	if (n->joint == j) {
+	  if (last) last->next = n->next;
+	  else body->firstjoint = n->next;
+	  break;
+	}
+	last = n;
+	n = n->next;
+      }
+    }
+  }
+  j->node[0].body = 0;
+  j->node[0].next = 0;
+  j->node[1].body = 0;
+  j->node[1].next = 0;
+}
+
+//****************************************************************************
+// debugging
+
+// see if an object list loops on itself (if so, it's bad).
+
+static int listHasLoops (dObject *first)
+{
+  if (first==0 || first->next==0) return 0;
+  dObject *a=first,*b=first->next;
+  int skip=0;
+  while (b) {
+    if (a==b) return 1;
+    b = b->next;
+    if (skip) a = a->next;
+    skip ^= 1;
+  }
+  return 0;
+}
+
+
+// check the validity of the world data structures
+
+static void checkWorld (dxWorld *w)
+{
+  dxBody *b;
+  dxJoint *j;
+
+  // check there are no loops
+  if (listHasLoops (w->firstbody)) dDebug (0,"body list has loops");
+  if (listHasLoops (w->firstjoint)) dDebug (0,"joint list has loops");
+
+  // check lists are well formed (check `tome' pointers)
+  for (b=w->firstbody; b; b=(dxBody*)b->next) {
+    if (b->next && b->next->tome != &b->next)
+      dDebug (0,"bad tome pointer in body list");
+  }
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    if (j->next && j->next->tome != &j->next)
+      dDebug (0,"bad tome pointer in joint list");
+  }
+
+  // check counts
+  int n = 0;
+  for (b=w->firstbody; b; b=(dxBody*)b->next) n++;
+  if (w->nb != n) dDebug (0,"body count incorrect");
+  n = 0;
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) n++;
+  if (w->nj != n) dDebug (0,"joint count incorrect");
+
+  // set all tag values to a known value
+  static int count = 0;
+  count++;
+  for (b=w->firstbody; b; b=(dxBody*)b->next) b->tag = count;
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) j->tag = count;
+
+  // check all body/joint world pointers are ok
+  for (b=w->firstbody; b; b=(dxBody*)b->next) if (b->world != w)
+    dDebug (0,"bad world pointer in body list");
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) if (j->world != w)
+    dDebug (0,"bad world pointer in joint list");
+
+  /*
+  // check for half-connected joints - actually now these are valid
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    if (j->node[0].body || j->node[1].body) {
+      if (!(j->node[0].body && j->node[1].body))
+	dDebug (0,"half connected joint found");
+    }
+  }
+  */
+
+  // check that every joint node appears in the joint lists of both bodies it
+  // attaches
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    for (int i=0; i<2; i++) {
+      if (j->node[i].body) {
+	int ok = 0;
+	for (dxJointNode *n=j->node[i].body->firstjoint; n; n=n->next) {
+	  if (n->joint == j) ok = 1;
+	}
+	if (ok==0) dDebug (0,"joint not in joint list of attached body");
+      }
+    }
+  }
+
+  // check all body joint lists (correct body ptrs)
+  for (b=w->firstbody; b; b=(dxBody*)b->next) {
+    for (dxJointNode *n=b->firstjoint; n; n=n->next) {
+      if (&n->joint->node[0] == n) {
+	if (n->joint->node[1].body != b)
+	  dDebug (0,"bad body pointer in joint node of body list (1)");
+      }
+      else {
+	if (n->joint->node[0].body != b)
+	  dDebug (0,"bad body pointer in joint node of body list (2)");
+      }
+      if (n->joint->tag != count) dDebug (0,"bad joint node pointer in body");
+    }
+  }
+
+  // check all body pointers in joints, check they are distinct
+  for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
+    if (j->node[0].body && (j->node[0].body == j->node[1].body))
+      dDebug (0,"non-distinct body pointers in joint");
+    if ((j->node[0].body && j->node[0].body->tag != count) ||
+	(j->node[1].body && j->node[1].body->tag != count))
+      dDebug (0,"bad body pointer in joint");
+  }
+}
+
+
+void dWorldCheck (dxWorld *w)
+{
+  checkWorld (w);
+}
+
+//****************************************************************************
+// body
+dxWorld* dBodyGetWorld (dxBody* b)
+{
+  dAASSERT (b);
+  return b->world;
+}
+
+dxBody *dBodyCreate (dxWorld *w)
+{
+  dAASSERT (w);
+  dxBody *b = new dxBody;
+  initObject (b,w);
+  b->firstjoint = 0;
+  b->flags = 0;
+  b->geom = 0;
+  b->average_lvel_buffer = 0;
+  b->average_avel_buffer = 0;
+  dMassSetParameters (&b->mass,1,0,0,0,1,1,1,0,0,0);
+  dSetZero (b->invI,4*3);
+  b->invI[0] = 1;
+  b->invI[5] = 1;
+  b->invI[10] = 1;
+  b->invMass = 1;
+  dSetZero (b->posr.pos,4);
+  dSetZero (b->q,4);
+  b->q[0] = 1;
+  dRSetIdentity (b->posr.R);
+  dSetZero (b->lvel,4);
+  dSetZero (b->avel,4);
+  dSetZero (b->facc,4);
+  dSetZero (b->tacc,4);
+  dSetZero (b->finite_rot_axis,4);
+  addObjectToList (b,(dObject **) &w->firstbody);
+  w->nb++;
+
+  // set auto-disable parameters
+  b->average_avel_buffer = b->average_lvel_buffer = 0; // no buffer at beginnin
+  dBodySetAutoDisableDefaults (b);	// must do this after adding to world
+  b->adis_stepsleft = b->adis.idle_steps;
+  b->adis_timeleft = b->adis.idle_time;
+  b->average_counter = 0;
+  b->average_ready = 0; // average buffer not filled on the beginning
+  dBodySetAutoDisableAverageSamplesCount(b, b->adis.average_samples);
+
+  return b;
+}
+
+
+void dBodyDestroy (dxBody *b)
+{
+  dAASSERT (b);
+
+  // all geoms that link to this body must be notified that the body is about
+  // to disappear. note that the call to dGeomSetBody(geom,0) will result in
+  // dGeomGetBodyNext() returning 0 for the body, so we must get the next body
+  // before setting the body to 0.
+  dxGeom *next_geom = 0;
+  for (dxGeom *geom = b->geom; geom; geom = next_geom) {
+    next_geom = dGeomGetBodyNext (geom);
+    dGeomSetBody (geom,0);
+  }
+
+  // detach all neighbouring joints, then delete this body.
+  dxJointNode *n = b->firstjoint;
+  while (n) {
+    // sneaky trick to speed up removal of joint references (black magic)
+    n->joint->node[(n == n->joint->node)].body = 0;
+
+    dxJointNode *next = n->next;
+    n->next = 0;
+    removeJointReferencesFromAttachedBodies (n->joint);
+    n = next;
+  }
+  removeObjectFromList (b);
+  b->world->nb--;
+
+  // delete the average buffers
+  if(b->average_lvel_buffer)
+  {
+	  delete[] (b->average_lvel_buffer);
+	  b->average_lvel_buffer = 0;
+  }
+  if(b->average_avel_buffer)
+  {
+	  delete[] (b->average_avel_buffer);
+	  b->average_avel_buffer = 0;
+  }
+
+  delete b;
+}
+
+
+void dBodySetData (dBodyID b, void *data)
+{
+  dAASSERT (b);
+  b->userdata = data;
+}
+
+
+void *dBodyGetData (dBodyID b)
+{
+  dAASSERT (b);
+  return b->userdata;
+}
+
+
+void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->posr.pos[0] = x;
+  b->posr.pos[1] = y;
+  b->posr.pos[2] = z;
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+
+void dBodySetRotation (dBodyID b, const dMatrix3 R)
+{
+  dAASSERT (b && R);
+  dQuaternion q;
+  dRtoQ (R,q);
+  dNormalize4 (q);
+  b->q[0] = q[0];
+  b->q[1] = q[1];
+  b->q[2] = q[2];
+  b->q[3] = q[3];
+  dQtoR (b->q,b->posr.R);
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+
+void dBodySetQuaternion (dBodyID b, const dQuaternion q)
+{
+  dAASSERT (b && q);
+  b->q[0] = q[0];
+  b->q[1] = q[1];
+  b->q[2] = q[2];
+  b->q[3] = q[3];
+  dNormalize4 (b->q);
+  dQtoR (b->q,b->posr.R);
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+
+void dBodySetLinearVel  (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->lvel[0] = x;
+  b->lvel[1] = y;
+  b->lvel[2] = z;
+}
+
+
+void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->avel[0] = x;
+  b->avel[1] = y;
+  b->avel[2] = z;
+}
+
+
+const dReal * dBodyGetPosition (dBodyID b)
+{
+  dAASSERT (b);
+  return b->posr.pos;
+}
+
+
+void dBodyCopyPosition (dBodyID b, dVector3 pos)
+{
+	dAASSERT (b);
+	dReal* src = b->posr.pos;
+	pos[0] = src[0];
+	pos[1] = src[1];
+	pos[2] = src[2];
+}
+
+
+const dReal * dBodyGetRotation (dBodyID b)
+{
+  dAASSERT (b);
+  return b->posr.R;
+}
+
+
+void dBodyCopyRotation (dBodyID b, dMatrix3 R)
+{
+	dAASSERT (b);
+	const dReal* src = b->posr.R;
+	R[0] = src[0];
+	R[1] = src[1];
+	R[2] = src[2];
+	R[3] = src[3];
+	R[4] = src[4];
+	R[5] = src[5];
+	R[6] = src[6];
+	R[7] = src[7];
+	R[8] = src[8];
+	R[9] = src[9];
+	R[10] = src[10];
+	R[11] = src[11];
+}
+
+
+const dReal * dBodyGetQuaternion (dBodyID b)
+{
+  dAASSERT (b);
+  return b->q;
+}
+
+
+void dBodyCopyQuaternion (dBodyID b, dQuaternion quat)
+{
+	dAASSERT (b);
+	dReal* src = b->q;
+	quat[0] = src[0];
+	quat[1] = src[1];
+	quat[2] = src[2];
+	quat[3] = src[3];
+}
+
+
+const dReal * dBodyGetLinearVel (dBodyID b)
+{
+  dAASSERT (b);
+  return b->lvel;
+}
+
+
+const dReal * dBodyGetAngularVel (dBodyID b)
+{
+  dAASSERT (b);
+  return b->avel;
+}
+
+
+void dBodySetMass (dBodyID b, const dMass *mass)
+{
+  dAASSERT (b && mass );
+  dIASSERT(dMassCheck(mass));
+
+  // The centre of mass must be at the origin.
+  // Use dMassTranslate( mass, -mass->c[0], -mass->c[1], -mass->c[2] ) to correct it.
+  dUASSERT( fabs( mass->c[0] ) <= dEpsilon &&
+			fabs( mass->c[1] ) <= dEpsilon &&
+			fabs( mass->c[2] ) <= dEpsilon, "The centre of mass must be at the origin." )
+
+  memcpy (&b->mass,mass,sizeof(dMass));
+  if (dInvertPDMatrix (b->mass.I,b->invI,3)==0) {
+    dDEBUGMSG ("inertia must be positive definite!");
+    dRSetIdentity (b->invI);
+  }
+  b->invMass = dRecip(b->mass.mass);
+}
+
+
+void dBodyGetMass (dBodyID b, dMass *mass)
+{
+  dAASSERT (b && mass);
+  memcpy (mass,&b->mass,sizeof(dMass));
+}
+
+
+void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  b->facc[0] += fx;
+  b->facc[1] += fy;
+  b->facc[2] += fz;
+}
+
+
+void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  b->tacc[0] += fx;
+  b->tacc[1] += fy;
+  b->tacc[2] += fz;
+}
+
+
+void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  dVector3 t1,t2;
+  t1[0] = fx;
+  t1[1] = fy;
+  t1[2] = fz;
+  t1[3] = 0;
+  dMULTIPLY0_331 (t2,b->posr.R,t1);
+  b->facc[0] += t2[0];
+  b->facc[1] += t2[1];
+  b->facc[2] += t2[2];
+}
+
+
+void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
+{
+  dAASSERT (b);
+  dVector3 t1,t2;
+  t1[0] = fx;
+  t1[1] = fy;
+  t1[2] = fz;
+  t1[3] = 0;
+  dMULTIPLY0_331 (t2,b->posr.R,t1);
+  b->tacc[0] += t2[0];
+  b->tacc[1] += t2[1];
+  b->tacc[2] += t2[2];
+}
+
+
+void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			 dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  b->facc[0] += fx;
+  b->facc[1] += fy;
+  b->facc[2] += fz;
+  dVector3 f,q;
+  f[0] = fx;
+  f[1] = fy;
+  f[2] = fz;
+  q[0] = px - b->posr.pos[0];
+  q[1] = py - b->posr.pos[1];
+  q[2] = pz - b->posr.pos[2];
+  dCROSS (b->tacc,+=,q,f);
+}
+
+
+void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			    dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  dVector3 prel,f,p;
+  f[0] = fx;
+  f[1] = fy;
+  f[2] = fz;
+  f[3] = 0;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (p,b->posr.R,prel);
+  b->facc[0] += f[0];
+  b->facc[1] += f[1];
+  b->facc[2] += f[2];
+  dCROSS (b->tacc,+=,p,f);
+}
+
+
+void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			    dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  dVector3 frel,f;
+  frel[0] = fx;
+  frel[1] = fy;
+  frel[2] = fz;
+  frel[3] = 0;
+  dMULTIPLY0_331 (f,b->posr.R,frel);
+  b->facc[0] += f[0];
+  b->facc[1] += f[1];
+  b->facc[2] += f[2];
+  dVector3 q;
+  q[0] = px - b->posr.pos[0];
+  q[1] = py - b->posr.pos[1];
+  q[2] = pz - b->posr.pos[2];
+  dCROSS (b->tacc,+=,q,f);
+}
+
+
+void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
+			       dReal px, dReal py, dReal pz)
+{
+  dAASSERT (b);
+  dVector3 frel,prel,f,p;
+  frel[0] = fx;
+  frel[1] = fy;
+  frel[2] = fz;
+  frel[3] = 0;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (f,b->posr.R,frel);
+  dMULTIPLY0_331 (p,b->posr.R,prel);
+  b->facc[0] += f[0];
+  b->facc[1] += f[1];
+  b->facc[2] += f[2];
+  dCROSS (b->tacc,+=,p,f);
+}
+
+
+const dReal * dBodyGetForce (dBodyID b)
+{
+  dAASSERT (b);
+  return b->facc;
+}
+
+
+const dReal * dBodyGetTorque (dBodyID b)
+{
+  dAASSERT (b);
+  return b->tacc;
+}
+
+
+void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->facc[0] = x;
+  b->facc[1] = y;
+  b->facc[2] = z;
+}
+
+
+void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->tacc[0] = x;
+  b->tacc[1] = y;
+  b->tacc[2] = z;
+}
+
+
+void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz,
+			  dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 prel,p;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (p,b->posr.R,prel);
+  result[0] = p[0] + b->posr.pos[0];
+  result[1] = p[1] + b->posr.pos[1];
+  result[2] = p[2] + b->posr.pos[2];
+}
+
+
+void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz,
+			  dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 prel,p;
+  prel[0] = px;
+  prel[1] = py;
+  prel[2] = pz;
+  prel[3] = 0;
+  dMULTIPLY0_331 (p,b->posr.R,prel);
+  result[0] = b->lvel[0];
+  result[1] = b->lvel[1];
+  result[2] = b->lvel[2];
+  dCROSS (result,+=,b->avel,p);
+}
+
+
+void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz,
+		       dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 p;
+  p[0] = px - b->posr.pos[0];
+  p[1] = py - b->posr.pos[1];
+  p[2] = pz - b->posr.pos[2];
+  p[3] = 0;
+  result[0] = b->lvel[0];
+  result[1] = b->lvel[1];
+  result[2] = b->lvel[2];
+  dCROSS (result,+=,b->avel,p);
+}
+
+
+void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz,
+			  dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 prel;
+  prel[0] = px - b->posr.pos[0];
+  prel[1] = py - b->posr.pos[1];
+  prel[2] = pz - b->posr.pos[2];
+  prel[3] = 0;
+  dMULTIPLY1_331 (result,b->posr.R,prel);
+}
+
+
+void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz,
+			 dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 p;
+  p[0] = px;
+  p[1] = py;
+  p[2] = pz;
+  p[3] = 0;
+  dMULTIPLY0_331 (result,b->posr.R,p);
+}
+
+
+void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz,
+			   dVector3 result)
+{
+  dAASSERT (b);
+  dVector3 p;
+  p[0] = px;
+  p[1] = py;
+  p[2] = pz;
+  p[3] = 0;
+  dMULTIPLY1_331 (result,b->posr.R,p);
+}
+
+
+void dBodySetFiniteRotationMode (dBodyID b, int mode)
+{
+  dAASSERT (b);
+  b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis);
+  if (mode) {
+    b->flags |= dxBodyFlagFiniteRotation;
+    if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 ||
+	b->finite_rot_axis[2] != 0) {
+      b->flags |= dxBodyFlagFiniteRotationAxis;
+    }
+  }
+}
+
+
+void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z)
+{
+  dAASSERT (b);
+  b->finite_rot_axis[0] = x;
+  b->finite_rot_axis[1] = y;
+  b->finite_rot_axis[2] = z;
+  if (x != 0 || y != 0 || z != 0) {
+    dNormalize3 (b->finite_rot_axis);
+    b->flags |= dxBodyFlagFiniteRotationAxis;
+  }
+  else {
+    b->flags &= ~dxBodyFlagFiniteRotationAxis;
+  }
+}
+
+
+int dBodyGetFiniteRotationMode (dBodyID b)
+{
+  dAASSERT (b);
+  return ((b->flags & dxBodyFlagFiniteRotation) != 0);
+}
+
+
+void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result)
+{
+  dAASSERT (b);
+  result[0] = b->finite_rot_axis[0];
+  result[1] = b->finite_rot_axis[1];
+  result[2] = b->finite_rot_axis[2];
+}
+
+
+int dBodyGetNumJoints (dBodyID b)
+{
+  dAASSERT (b);
+  int count=0;
+  for (dxJointNode *n=b->firstjoint; n; n=n->next, count++);
+  return count;
+}
+
+
+dJointID dBodyGetJoint (dBodyID b, int index)
+{
+  dAASSERT (b);
+  int i=0;
+  for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) {
+    if (i == index) return n->joint;
+  }
+  return 0;
+}
+
+
+void dBodyEnable (dBodyID b)
+{
+  dAASSERT (b);
+  b->flags &= ~dxBodyDisabled;
+  b->adis_stepsleft = b->adis.idle_steps;
+  b->adis_timeleft = b->adis.idle_time;
+  // no code for average-processing needed here
+}
+
+
+void dBodyDisable (dBodyID b)
+{
+  dAASSERT (b);
+  b->flags |= dxBodyDisabled;
+}
+
+
+int dBodyIsEnabled (dBodyID b)
+{
+  dAASSERT (b);
+  return ((b->flags & dxBodyDisabled) == 0);
+}
+
+
+void dBodySetGravityMode (dBodyID b, int mode)
+{
+  dAASSERT (b);
+  if (mode) b->flags &= ~dxBodyNoGravity;
+  else b->flags |= dxBodyNoGravity;
+}
+
+
+int dBodyGetGravityMode (dBodyID b)
+{
+  dAASSERT (b);
+  return ((b->flags & dxBodyNoGravity) == 0);
+}
+
+
+// body auto-disable functions
+
+dReal dBodyGetAutoDisableLinearThreshold (dBodyID b)
+{
+	dAASSERT(b);
+	return dSqrt (b->adis.linear_average_threshold);
+}
+
+
+void dBodySetAutoDisableLinearThreshold (dBodyID b, dReal linear_average_threshold)
+{
+	dAASSERT(b);
+	b->adis.linear_average_threshold = linear_average_threshold * linear_average_threshold;
+}
+
+
+dReal dBodyGetAutoDisableAngularThreshold (dBodyID b)
+{
+	dAASSERT(b);
+	return dSqrt (b->adis.angular_average_threshold);
+}
+
+
+void dBodySetAutoDisableAngularThreshold (dBodyID b, dReal angular_average_threshold)
+{
+	dAASSERT(b);
+	b->adis.angular_average_threshold = angular_average_threshold * angular_average_threshold;
+}
+
+
+int dBodyGetAutoDisableAverageSamplesCount (dBodyID b)
+{
+	dAASSERT(b);
+	return b->adis.average_samples;
+}
+
+
+void dBodySetAutoDisableAverageSamplesCount (dBodyID b, unsigned int average_samples_count)
+{
+	dAASSERT(b);
+	b->adis.average_samples = average_samples_count;
+	// update the average buffers
+	if(b->average_lvel_buffer)
+	{
+		delete[] b->average_lvel_buffer;
+		b->average_lvel_buffer = 0;
+	}
+	if(b->average_avel_buffer)
+	{
+		delete[] b->average_avel_buffer;
+		b->average_avel_buffer = 0;
+	}
+	if(b->adis.average_samples > 0)
+	{
+		b->average_lvel_buffer = new dVector3[b->adis.average_samples];
+		b->average_avel_buffer = new dVector3[b->adis.average_samples];
+	}
+	else
+	{
+		b->average_lvel_buffer = 0;
+		b->average_avel_buffer = 0;
+	}
+	// new buffer is empty
+	b->average_counter = 0;
+	b->average_ready = 0;
+}
+
+
+int dBodyGetAutoDisableSteps (dBodyID b)
+{
+	dAASSERT(b);
+	return b->adis.idle_steps;
+}
+
+
+void dBodySetAutoDisableSteps (dBodyID b, int steps)
+{
+	dAASSERT(b);
+	b->adis.idle_steps = steps;
+}
+
+
+dReal dBodyGetAutoDisableTime (dBodyID b)
+{
+	dAASSERT(b);
+	return b->adis.idle_time;
+}
+
+
+void dBodySetAutoDisableTime (dBodyID b, dReal time)
+{
+	dAASSERT(b);
+	b->adis.idle_time = time;
+}
+
+
+int dBodyGetAutoDisableFlag (dBodyID b)
+{
+	dAASSERT(b);
+	return ((b->flags & dxBodyAutoDisable) != 0);
+}
+
+
+void dBodySetAutoDisableFlag (dBodyID b, int do_auto_disable)
+{
+	dAASSERT(b);
+	if (!do_auto_disable)
+	{
+		b->flags &= ~dxBodyAutoDisable;
+		// (mg) we should also reset the IsDisabled state to correspond to the DoDisabling flag
+		b->flags &= ~dxBodyDisabled;
+		b->adis.idle_steps = dWorldGetAutoDisableSteps(b->world);
+		b->adis.idle_time = dWorldGetAutoDisableTime(b->world);
+		// resetting the average calculations too
+		dBodySetAutoDisableAverageSamplesCount(b, dWorldGetAutoDisableAverageSamplesCount(b->world) );
+	}
+	else
+	{
+		b->flags |= dxBodyAutoDisable;
+	}
+}
+
+
+void dBodySetAutoDisableDefaults (dBodyID b)
+{
+	dAASSERT(b);
+	dWorldID w = b->world;
+	dAASSERT(w);
+	b->adis = w->adis;
+	dBodySetAutoDisableFlag (b, w->adis_flag);
+}
+
+//****************************************************************************
+// joints
+
+static void dJointInit (dxWorld *w, dxJoint *j)
+{
+  dIASSERT (w && j);
+  initObject (j,w);
+  j->vtable = 0;
+  j->flags = 0;
+  j->node[0].joint = j;
+  j->node[0].body = 0;
+  j->node[0].next = 0;
+  j->node[1].joint = j;
+  j->node[1].body = 0;
+  j->node[1].next = 0;
+  dSetZero (j->lambda,6);
+  addObjectToList (j,(dObject **) &w->firstjoint);
+  w->nj++;
+}
+
+
+static dxJoint *createJoint (dWorldID w, dJointGroupID group,
+			     dxJoint::Vtable *vtable)
+{
+  dIASSERT (w && vtable);
+  dxJoint *j;
+  if (group) {
+    j = (dxJoint*) group->stack.alloc (vtable->size);
+    group->num++;
+  }
+  else j = (dxJoint*) dAlloc (vtable->size);
+  dJointInit (w,j);
+  j->vtable = vtable;
+  if (group) j->flags |= dJOINT_INGROUP;
+  if (vtable->init) vtable->init (j);
+  j->feedback = 0;
+  return j;
+}
+
+
+dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dball_vtable);
+}
+
+
+dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dhinge_vtable);
+}
+
+
+dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dslider_vtable);
+}
+
+
+dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group,
+			       const dContact *c)
+{
+  dAASSERT (w && c);
+  dxJointContact *j = (dxJointContact *)
+    createJoint (w,group,&__dcontact_vtable);
+  j->contact = *c;
+  return j;
+}
+
+
+dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dhinge2_vtable);
+}
+
+
+dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__duniversal_vtable);
+}
+
+dxJoint * dJointCreatePR (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dPR_vtable);
+}
+
+dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dfixed_vtable);
+}
+
+
+dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dnull_vtable);
+}
+
+
+dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__damotor_vtable);
+}
+
+dxJoint * dJointCreateLMotor (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dlmotor_vtable);
+}
+
+dxJoint * dJointCreatePlane2D (dWorldID w, dJointGroupID group)
+{
+  dAASSERT (w);
+  return createJoint (w,group,&__dplane2d_vtable);
+}
+
+void dJointDestroy (dxJoint *j)
+{
+  dAASSERT (j);
+  if (j->flags & dJOINT_INGROUP) return;
+  removeJointReferencesFromAttachedBodies (j);
+  removeObjectFromList (j);
+  j->world->nj--;
+  dFree (j,j->vtable->size);
+}
+
+
+dJointGroupID dJointGroupCreate (int max_size)
+{
+  // not any more ... dUASSERT (max_size > 0,"max size must be > 0");
+  dxJointGroup *group = new dxJointGroup;
+  group->num = 0;
+  return group;
+}
+
+
+void dJointGroupDestroy (dJointGroupID group)
+{
+  dAASSERT (group);
+  dJointGroupEmpty (group);
+  delete group;
+}
+
+
+void dJointGroupEmpty (dJointGroupID group)
+{
+  // the joints in this group are detached starting from the most recently
+  // added (at the top of the stack). this helps ensure that the various
+  // linked lists are not traversed too much, as the joints will hopefully
+  // be at the start of those lists.
+  // if any group joints have their world pointer set to 0, their world was
+  // previously destroyed. no special handling is required for these joints.
+
+  dAASSERT (group);
+  int i;
+  dxJoint **jlist = (dxJoint**) ALLOCA (group->num * sizeof(dxJoint*));
+  dxJoint *j = (dxJoint*) group->stack.rewind();
+  for (i=0; i < group->num; i++) {
+    jlist[i] = j;
+    j = (dxJoint*) (group->stack.next (j->vtable->size));
+  }
+  for (i=group->num-1; i >= 0; i--) {
+    if (jlist[i]->world) {
+      removeJointReferencesFromAttachedBodies (jlist[i]);
+      removeObjectFromList (jlist[i]);
+      jlist[i]->world->nj--;
+    }
+  }
+  group->num = 0;
+  group->stack.freeAll();
+}
+
+
+void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2)
+{
+  // check arguments
+  dUASSERT (joint,"bad joint argument");
+  dUASSERT (body1 == 0 || body1 != body2,"can't have body1==body2");
+  dxWorld *world = joint->world;
+  dUASSERT ( (!body1 || body1->world == world) &&
+	     (!body2 || body2->world == world),
+	     "joint and bodies must be in same world");
+
+  // check if the joint can not be attached to just one body
+  dUASSERT (!((joint->flags & dJOINT_TWOBODIES) &&
+	      ((body1 != 0) ^ (body2 != 0))),
+	    "joint can not be attached to just one body");
+
+  // remove any existing body attachments
+  if (joint->node[0].body || joint->node[1].body) {
+    removeJointReferencesFromAttachedBodies (joint);
+  }
+
+  // if a body is zero, make sure that it is body2, so 0 --> node[1].body
+  if (body1==0) {
+    body1 = body2;
+    body2 = 0;
+    joint->flags |= dJOINT_REVERSE;
+  }
+  else {
+    joint->flags &= (~dJOINT_REVERSE);
+  }
+
+  // attach to new bodies
+  joint->node[0].body = body1;
+  joint->node[1].body = body2;
+  if (body1) {
+    joint->node[1].next = body1->firstjoint;
+    body1->firstjoint = &joint->node[1];
+  }
+  else joint->node[1].next = 0;
+  if (body2) {
+    joint->node[0].next = body2->firstjoint;
+    body2->firstjoint = &joint->node[0];
+  }
+  else {
+    joint->node[0].next = 0;
+  }
+}
+
+
+void dJointSetData (dxJoint *joint, void *data)
+{
+  dAASSERT (joint);
+  joint->userdata = data;
+}
+
+
+void *dJointGetData (dxJoint *joint)
+{
+  dAASSERT (joint);
+  return joint->userdata;
+}
+
+
+int dJointGetType (dxJoint *joint)
+{
+  dAASSERT (joint);
+  return joint->vtable->typenum;
+}
+
+
+dBodyID dJointGetBody (dxJoint *joint, int index)
+{
+  dAASSERT (joint);
+  if (index == 0 || index == 1) {
+    if (joint->flags & dJOINT_REVERSE) return joint->node[1-index].body;
+    else return joint->node[index].body;
+  }
+  else return 0;
+}
+
+
+void dJointSetFeedback (dxJoint *joint, dJointFeedback *f)
+{
+  dAASSERT (joint);
+  joint->feedback = f;
+}
+
+
+dJointFeedback *dJointGetFeedback (dxJoint *joint)
+{
+  dAASSERT (joint);
+  return joint->feedback;
+}
+
+
+
+dJointID dConnectingJoint (dBodyID in_b1, dBodyID in_b2)
+{
+    dAASSERT (in_b1 || in_b2);
+
+	dBodyID b1, b2;
+
+	if (in_b1 == 0) {
+		b1 = in_b2;
+		b2 = in_b1;
+	}
+	else {
+		b1 = in_b1;
+		b2 = in_b2;
+	}
+
+    // look through b1's neighbour list for b2
+    for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
+        if (n->body == b2) return n->joint;
+    }
+
+    return 0;
+}
+
+
+
+int dConnectingJointList (dBodyID in_b1, dBodyID in_b2, dJointID* out_list)
+{
+    dAASSERT (in_b1 || in_b2);
+
+
+	dBodyID b1, b2;
+
+	if (in_b1 == 0) {
+		b1 = in_b2;
+		b2 = in_b1;
+	}
+	else {
+		b1 = in_b1;
+		b2 = in_b2;
+	}
+
+    // look through b1's neighbour list for b2
+    int numConnectingJoints = 0;
+    for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
+        if (n->body == b2)
+            out_list[numConnectingJoints++] = n->joint;
+    }
+
+    return numConnectingJoints;
+}
+
+
+int dAreConnected (dBodyID b1, dBodyID b2)
+{
+  dAASSERT (b1 && b2);
+  // look through b1's neighbour list for b2
+  for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
+    if (n->body == b2) return 1;
+  }
+  return 0;
+}
+
+
+int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type)
+{
+  dAASSERT (b1 && b2);
+  // look through b1's neighbour list for b2
+  for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
+    if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1;
+  }
+  return 0;
+}
+
+//****************************************************************************
+// world
+
+dxWorld * dWorldCreate()
+{
+  dxWorld *w = new dxWorld;
+  w->firstbody = 0;
+  w->firstjoint = 0;
+  w->nb = 0;
+  w->nj = 0;
+  dSetZero (w->gravity,4);
+  w->global_erp = REAL(0.2);
+#if defined(dSINGLE)
+  w->global_cfm = 1e-5f;
+#elif defined(dDOUBLE)
+  w->global_cfm = 1e-10;
+#else
+  #error dSINGLE or dDOUBLE must be defined
+#endif
+
+  w->adis.idle_steps = 10;
+  w->adis.idle_time = 0;
+  w->adis_flag = 0;
+  w->adis.average_samples = 1;		// Default is 1 sample => Instantaneous velocity
+  w->adis.angular_average_threshold = REAL(0.01)*REAL(0.01);	// (magnitude squared)
+  w->adis.linear_average_threshold = REAL(0.01)*REAL(0.01);		// (magnitude squared)
+
+  w->qs.num_iterations = 20;
+  w->qs.w = REAL(1.3);
+
+  w->contactp.max_vel = dInfinity;
+  w->contactp.min_depth = 0;
+
+  return w;
+}
+
+
+void dWorldDestroy (dxWorld *w)
+{
+  // delete all bodies and joints
+  dAASSERT (w);
+  dxBody *nextb, *b = w->firstbody;
+  while (b) {
+    nextb = (dxBody*) b->next;
+    if(b->average_lvel_buffer)
+    {
+      delete[] (b->average_lvel_buffer);
+      b->average_lvel_buffer = 0;
+    }
+    if(b->average_avel_buffer)
+    {
+      delete[] (b->average_avel_buffer);
+      b->average_avel_buffer = 0;
+    }
+    dBodyDestroy(b); // calling here dBodyDestroy for correct destroying! (i.e. the average buffers)
+    b = nextb;
+  }
+  dxJoint *nextj, *j = w->firstjoint;
+  while (j) {
+    nextj = (dxJoint*)j->next;
+    if (j->flags & dJOINT_INGROUP) {
+      // the joint is part of a group, so "deactivate" it instead
+      j->world = 0;
+      j->node[0].body = 0;
+      j->node[0].next = 0;
+      j->node[1].body = 0;
+      j->node[1].next = 0;
+      dMessage (0,"warning: destroying world containing grouped joints");
+    }
+    else {
+      dFree (j,j->vtable->size);
+    }
+    j = nextj;
+  }
+  delete w;
+}
+
+
+void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z)
+{
+  dAASSERT (w);
+  w->gravity[0] = x;
+  w->gravity[1] = y;
+  w->gravity[2] = z;
+}
+
+
+void dWorldGetGravity (dWorldID w, dVector3 g)
+{
+  dAASSERT (w);
+  g[0] = w->gravity[0];
+  g[1] = w->gravity[1];
+  g[2] = w->gravity[2];
+}
+
+
+void dWorldSetERP (dWorldID w, dReal erp)
+{
+  dAASSERT (w);
+  w->global_erp = erp;
+}
+
+
+dReal dWorldGetERP (dWorldID w)
+{
+  dAASSERT (w);
+  return w->global_erp;
+}
+
+
+void dWorldSetCFM (dWorldID w, dReal cfm)
+{
+  dAASSERT (w);
+  w->global_cfm = cfm;
+}
+
+
+dReal dWorldGetCFM (dWorldID w)
+{
+  dAASSERT (w);
+  return w->global_cfm;
+}
+
+
+void dWorldStep (dWorldID w, dReal stepsize)
+{
+  dUASSERT (w,"bad world argument");
+  dUASSERT (stepsize > 0,"stepsize must be > 0");
+  dxProcessIslands (w,stepsize,&dInternalStepIsland);
+}
+
+
+void dWorldQuickStep (dWorldID w, dReal stepsize)
+{
+  dUASSERT (w,"bad world argument");
+  dUASSERT (stepsize > 0,"stepsize must be > 0");
+  dxProcessIslands (w,stepsize,&dxQuickStepper);
+}
+
+
+void dWorldImpulseToForce (dWorldID w, dReal stepsize,
+			   dReal ix, dReal iy, dReal iz,
+			   dVector3 force)
+{
+  dAASSERT (w);
+  stepsize = dRecip(stepsize);
+  force[0] = stepsize * ix;
+  force[1] = stepsize * iy;
+  force[2] = stepsize * iz;
+  // @@@ force[3] = 0;
+}
+
+
+// world auto-disable functions
+
+dReal dWorldGetAutoDisableLinearThreshold (dWorldID w)
+{
+	dAASSERT(w);
+	return dSqrt (w->adis.linear_average_threshold);
+}
+
+
+void dWorldSetAutoDisableLinearThreshold (dWorldID w, dReal linear_average_threshold)
+{
+	dAASSERT(w);
+	w->adis.linear_average_threshold = linear_average_threshold * linear_average_threshold;
+}
+
+
+dReal dWorldGetAutoDisableAngularThreshold (dWorldID w)
+{
+	dAASSERT(w);
+	return dSqrt (w->adis.angular_average_threshold);
+}
+
+
+void dWorldSetAutoDisableAngularThreshold (dWorldID w, dReal angular_average_threshold)
+{
+	dAASSERT(w);
+	w->adis.angular_average_threshold = angular_average_threshold * angular_average_threshold;
+}
+
+
+int dWorldGetAutoDisableAverageSamplesCount (dWorldID w)
+{
+	dAASSERT(w);
+	return w->adis.average_samples;
+}
+
+
+void dWorldSetAutoDisableAverageSamplesCount (dWorldID w, unsigned int average_samples_count)
+{
+	dAASSERT(w);
+	w->adis.average_samples = average_samples_count;
+}
+
+
+int dWorldGetAutoDisableSteps (dWorldID w)
+{
+	dAASSERT(w);
+	return w->adis.idle_steps;
+}
+
+
+void dWorldSetAutoDisableSteps (dWorldID w, int steps)
+{
+	dAASSERT(w);
+	w->adis.idle_steps = steps;
+}
+
+
+dReal dWorldGetAutoDisableTime (dWorldID w)
+{
+	dAASSERT(w);
+	return w->adis.idle_time;
+}
+
+
+void dWorldSetAutoDisableTime (dWorldID w, dReal time)
+{
+	dAASSERT(w);
+	w->adis.idle_time = time;
+}
+
+
+int dWorldGetAutoDisableFlag (dWorldID w)
+{
+	dAASSERT(w);
+	return w->adis_flag;
+}
+
+
+void dWorldSetAutoDisableFlag (dWorldID w, int do_auto_disable)
+{
+	dAASSERT(w);
+	w->adis_flag = (do_auto_disable != 0);
+}
+
+
+void dWorldSetQuickStepNumIterations (dWorldID w, int num)
+{
+	dAASSERT(w);
+	w->qs.num_iterations = num;
+}
+
+
+int dWorldGetQuickStepNumIterations (dWorldID w)
+{
+	dAASSERT(w);
+	return w->qs.num_iterations;
+}
+
+
+void dWorldSetQuickStepW (dWorldID w, dReal param)
+{
+	dAASSERT(w);
+	w->qs.w = param;
+}
+
+
+dReal dWorldGetQuickStepW (dWorldID w)
+{
+	dAASSERT(w);
+	return w->qs.w;
+}
+
+
+void dWorldSetContactMaxCorrectingVel (dWorldID w, dReal vel)
+{
+	dAASSERT(w);
+	w->contactp.max_vel = vel;
+}
+
+
+dReal dWorldGetContactMaxCorrectingVel (dWorldID w)
+{
+	dAASSERT(w);
+	return w->contactp.max_vel;
+}
+
+
+void dWorldSetContactSurfaceLayer (dWorldID w, dReal depth)
+{
+	dAASSERT(w);
+	w->contactp.min_depth = depth;
+}
+
+
+dReal dWorldGetContactSurfaceLayer (dWorldID w)
+{
+	dAASSERT(w);
+	return w->contactp.min_depth;
+}
+
+//****************************************************************************
+// testing
+
+#define NUM 100
+
+#define DO(x)
+
+
+extern "C" void dTestDataStructures()
+{
+  int i;
+  DO(printf ("testDynamicsStuff()\n"));
+
+  dBodyID body [NUM];
+  int nb = 0;
+  dJointID joint [NUM];
+  int nj = 0;
+
+  for (i=0; i<NUM; i++) body[i] = 0;
+  for (i=0; i<NUM; i++) joint[i] = 0;
+
+  DO(printf ("creating world\n"));
+  dWorldID w = dWorldCreate();
+  checkWorld (w);
+
+  for (;;) {
+    if (nb < NUM && dRandReal() > 0.5) {
+      DO(printf ("creating body\n"));
+      body[nb] = dBodyCreate (w);
+      DO(printf ("\t--> %p\n",body[nb]));
+      nb++;
+      checkWorld (w);
+      DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+    }
+    if (nj < NUM && nb > 2 && dRandReal() > 0.5) {
+      dBodyID b1 = body [dRand() % nb];
+      dBodyID b2 = body [dRand() % nb];
+      if (b1 != b2) {
+	DO(printf ("creating joint, attaching to %p,%p\n",b1,b2));
+	joint[nj] = dJointCreateBall (w,0);
+	DO(printf ("\t-->%p\n",joint[nj]));
+	checkWorld (w);
+	dJointAttach (joint[nj],b1,b2);
+	nj++;
+	checkWorld (w);
+	DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+      }
+    }
+    if (nj > 0 && nb > 2 && dRandReal() > 0.5) {
+      dBodyID b1 = body [dRand() % nb];
+      dBodyID b2 = body [dRand() % nb];
+      if (b1 != b2) {
+	int k = dRand() % nj;
+	DO(printf ("reattaching joint %p\n",joint[k]));
+	dJointAttach (joint[k],b1,b2);
+	checkWorld (w);
+	DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+      }
+    }
+    if (nb > 0 && dRandReal() > 0.5) {
+      int k = dRand() % nb;
+      DO(printf ("destroying body %p\n",body[k]));
+      dBodyDestroy (body[k]);
+      checkWorld (w);
+      for (; k < (NUM-1); k++) body[k] = body[k+1];
+      nb--;
+      DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+    }
+    if (nj > 0 && dRandReal() > 0.5) {
+      int k = dRand() % nj;
+      DO(printf ("destroying joint %p\n",joint[k]));
+      dJointDestroy (joint[k]);
+      checkWorld (w);
+      for (; k < (NUM-1); k++) joint[k] = joint[k+1];
+      nj--;
+      DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
+    }
+  }
+
+  /*
+  printf ("creating world\n");
+  dWorldID w = dWorldCreate();
+  checkWorld (w);
+  printf ("creating body\n");
+  dBodyID b1 = dBodyCreate (w);
+  checkWorld (w);
+  printf ("creating body\n");
+  dBodyID b2 = dBodyCreate (w);
+  checkWorld (w);
+  printf ("creating joint\n");
+  dJointID j = dJointCreateBall (w);
+  checkWorld (w);
+  printf ("attaching joint\n");
+  dJointAttach (j,b1,b2);
+  checkWorld (w);
+  printf ("destroying joint\n");
+  dJointDestroy (j);
+  checkWorld (w);
+  printf ("destroying body\n");
+  dBodyDestroy (b1);
+  checkWorld (w);
+  printf ("destroying body\n");
+  dBodyDestroy (b2);
+  checkWorld (w);
+  printf ("destroying world\n");
+  dWorldDestroy (w);
+  */
+}
Index: /code/branches/ode/ode-0.9/ode/src/odemath.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/odemath.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/odemath.cpp	(revision 216)
@@ -0,0 +1,178 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/common.h>
+#include <ode/odemath.h>
+
+// get some math functions under windows
+#ifdef WIN32
+#include <float.h>
+#ifndef CYGWIN			// added by andy for cygwin
+#undef copysign
+#define copysign(a,b) ((dReal)_copysign(a,b))
+#endif				// added by andy for cygwin
+#endif
+
+#undef dNormalize3
+#undef dNormalize4
+
+
+// this may be called for vectors `a' with extremely small magnitude, for
+// example the result of a cross product on two nearly perpendicular vectors.
+// we must be robust to these small vectors. to prevent numerical error,
+// first find the component a[i] with the largest magnitude and then scale
+// all the components by 1/a[i]. then we can compute the length of `a' and
+// scale the components by 1/l. this has been verified to work with vectors
+// containing the smallest representable numbers.
+
+int dSafeNormalize3 (dVector3 a)
+{
+  dReal a0,a1,a2,aa0,aa1,aa2,l;
+  dAASSERT (a);
+  a0 = a[0];
+  a1 = a[1];
+  a2 = a[2];
+  aa0 = dFabs(a0);
+  aa1 = dFabs(a1);
+  aa2 = dFabs(a2);
+  if (aa1 > aa0) {
+    if (aa2 > aa1) {
+      goto aa2_largest;
+    }
+    else {		// aa1 is largest
+      a0 /= aa1;
+      a2 /= aa1;
+      l = dRecipSqrt (a0*a0 + a2*a2 + 1);
+      a[0] = a0*l;
+      a[1] = dCopySign(l,a1);
+      a[2] = a2*l;
+    }
+  }
+  else {
+    if (aa2 > aa0) {
+      aa2_largest:	// aa2 is largest
+      a0 /= aa2;
+      a1 /= aa2;
+      l = dRecipSqrt (a0*a0 + a1*a1 + 1);
+      a[0] = a0*l;
+      a[1] = a1*l;
+      a[2] = dCopySign(l,a2);
+    }
+    else {		// aa0 is largest
+      if (aa0 <= 0) {
+	a[0] = 1;	// if all a's are zero, this is where we'll end up.
+	a[1] = 0;	// return a default unit length vector.
+	a[2] = 0;
+	return 0;
+      }
+      a1 /= aa0;
+      a2 /= aa0;
+      l = dRecipSqrt (a1*a1 + a2*a2 + 1);
+      a[0] = dCopySign(l,a0);
+      a[1] = a1*l;
+      a[2] = a2*l;
+    }
+  }
+  return 1;
+}
+
+/* OLD VERSION */
+/*
+void dNormalize3 (dVector3 a)
+{
+  dIASSERT (a);
+  dReal l = dDOT(a,a);
+  if (l > 0) {
+    l = dRecipSqrt(l);
+    a[0] *= l;
+    a[1] *= l;
+    a[2] *= l;
+  }
+  else {
+    a[0] = 1;
+    a[1] = 0;
+    a[2] = 0;
+  }
+}
+*/
+
+void dNormalize3(dVector3 a)
+{
+	_dNormalize3(a);
+}
+
+
+int dSafeNormalize4 (dVector4 a)
+{
+  dAASSERT (a);
+  dReal l = dDOT(a,a)+a[3]*a[3];
+  if (l > 0) {
+    l = dRecipSqrt(l);
+    a[0] *= l;
+    a[1] *= l;
+    a[2] *= l;
+    a[3] *= l;
+	return 1;
+  }
+  else {
+    a[0] = 1;
+    a[1] = 0;
+    a[2] = 0;
+    a[3] = 0;
+    return 0;
+  }
+}
+
+void dNormalize4(dVector4 a)
+{
+	_dNormalize4(a);
+}
+
+
+void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q)
+{
+  dAASSERT (n && p && q);
+  if (dFabs(n[2]) > M_SQRT1_2) {
+    // choose p in y-z plane
+    dReal a = n[1]*n[1] + n[2]*n[2];
+    dReal k = dRecipSqrt (a);
+    p[0] = 0;
+    p[1] = -n[2]*k;
+    p[2] = n[1]*k;
+    // set q = n x p
+    q[0] = a*k;
+    q[1] = -n[0]*p[2];
+    q[2] = n[0]*p[1];
+  }
+  else {
+    // choose p in x-y plane
+    dReal a = n[0]*n[0] + n[1]*n[1];
+    dReal k = dRecipSqrt (a);
+    p[0] = -n[1]*k;
+    p[1] = n[0]*k;
+    p[2] = 0;
+    // set q = n x p
+    q[0] = -n[2]*p[1];
+    q[1] = n[2]*p[0];
+    q[2] = a*k;
+  }
+}
Index: /code/branches/ode/ode-0.9/ode/src/plane.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/plane.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/plane.cpp	(revision 216)
@@ -0,0 +1,145 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+standard ODE geometry primitives: public API and pairwise collision functions.
+
+the rule is that only the low level primitive collision functions should set
+dContactGeom::g1 and dContactGeom::g2.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// plane public API
+
+static void make_sure_plane_normal_has_unit_length (dxPlane *g)
+{
+  dReal l = g->p[0]*g->p[0] + g->p[1]*g->p[1] + g->p[2]*g->p[2];
+  if (l > 0) {
+    l = dRecipSqrt(l);
+    g->p[0] *= l;
+    g->p[1] *= l;
+    g->p[2] *= l;
+    g->p[3] *= l;
+  }
+  else {
+    g->p[0] = 1;
+    g->p[1] = 0;
+    g->p[2] = 0;
+    g->p[3] = 0;
+  }
+}
+
+
+dxPlane::dxPlane (dSpaceID space, dReal a, dReal b, dReal c, dReal d) :
+  dxGeom (space,0)
+{
+  type = dPlaneClass;
+  p[0] = a;
+  p[1] = b;
+  p[2] = c;
+  p[3] = d;
+  make_sure_plane_normal_has_unit_length (this);
+}
+
+
+void dxPlane::computeAABB()
+{
+	aabb[0] = -dInfinity;
+	aabb[1] = dInfinity;
+	aabb[2] = -dInfinity;
+	aabb[3] = dInfinity;
+	aabb[4] = -dInfinity;
+	aabb[5] = dInfinity;
+
+	// Planes that have normal vectors aligned along an axis can use a
+	// less comprehensive (half space) bounding box.
+
+	if ( p[1] == 0.0f && p[2] == 0.0f ) {
+		// normal aligned with x-axis
+		aabb[0] = (p[0] > 0) ? -dInfinity : -p[3];
+		aabb[1] = (p[0] > 0) ? p[3] : dInfinity;
+	} else
+	if ( p[0] == 0.0f && p[2] == 0.0f ) {
+		// normal aligned with y-axis
+		aabb[2] = (p[1] > 0) ? -dInfinity : -p[3];
+		aabb[3] = (p[1] > 0) ? p[3] : dInfinity;
+	} else
+	if ( p[0] == 0.0f && p[1] == 0.0f ) {
+		// normal aligned with z-axis
+		aabb[4] = (p[2] > 0) ? -dInfinity : -p[3];
+		aabb[5] = (p[2] > 0) ? p[3] : dInfinity;
+	}
+}
+
+
+dGeomID dCreatePlane (dSpaceID space,
+		      dReal a, dReal b, dReal c, dReal d)
+{
+  return new dxPlane (space,a,b,c,d);
+}
+
+
+void dGeomPlaneSetParams (dGeomID g, dReal a, dReal b, dReal c, dReal d)
+{
+  dUASSERT (g && g->type == dPlaneClass,"argument not a plane");
+  dxPlane *p = (dxPlane*) g;
+  p->p[0] = a;
+  p->p[1] = b;
+  p->p[2] = c;
+  p->p[3] = d;
+  make_sure_plane_normal_has_unit_length (p);
+  dGeomMoved (g);
+}
+
+
+void dGeomPlaneGetParams (dGeomID g, dVector4 result)
+{
+  dUASSERT (g && g->type == dPlaneClass,"argument not a plane");
+  dxPlane *p = (dxPlane*) g;
+  result[0] = p->p[0];
+  result[1] = p->p[1];
+  result[2] = p->p[2];
+  result[3] = p->p[3];
+}
+
+
+dReal dGeomPlanePointDepth (dGeomID g, dReal x, dReal y, dReal z)
+{
+  dUASSERT (g && g->type == dPlaneClass,"argument not a plane");
+  dxPlane *p = (dxPlane*) g;
+  return p->p[3] - p->p[0]*x - p->p[1]*y - p->p[2]*z;
+}
Index: /code/branches/ode/ode-0.9/ode/src/quickstep.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/quickstep.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/quickstep.cpp	(revision 216)
@@ -0,0 +1,880 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include "objects.h"
+#include "joint.h"
+#include <ode/config.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/timer.h>
+#include <ode/error.h>
+#include <ode/matrix.h>
+#include <ode/misc.h>
+#include "lcp.h"
+#include "util.h"
+
+#define ALLOCA dALLOCA16
+
+typedef const dReal *dRealPtr;
+typedef dReal *dRealMutablePtr;
+#define dRealArray(name,n) dReal name[n];
+#define dRealAllocaArray(name,n) dReal *name = (dReal*) ALLOCA ((n)*sizeof(dReal));
+
+//***************************************************************************
+// configuration
+
+// for the SOR and CG methods:
+// uncomment the following line to use warm starting. this definitely
+// help for motor-driven joints. unfortunately it appears to hurt
+// with high-friction contacts using the SOR method. use with care
+
+//#define WARM_STARTING 1
+
+
+// for the SOR method:
+// uncomment the following line to determine a new constraint-solving
+// order for each iteration. however, the qsort per iteration is expensive,
+// and the optimal order is somewhat problem dependent.
+// @@@ try the leaf->root ordering.
+
+//#define REORDER_CONSTRAINTS 1
+
+
+// for the SOR method:
+// uncomment the following line to randomly reorder constraint rows
+// during the solution. depending on the situation, this can help a lot
+// or hardly at all, but it doesn't seem to hurt.
+
+#define RANDOMLY_REORDER_CONSTRAINTS 1
+
+//****************************************************************************
+// special matrix multipliers
+
+// multiply block of B matrix (q x 6) with 12 dReal per row with C vektor (q)
+static void Multiply1_12q1 (dReal *A, dReal *B, dReal *C, int q)
+{
+  int k;
+  dReal sum;
+  dIASSERT (q>0 && A && B && C);
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[k*12] * C[k];
+  A[0] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[1+k*12] * C[k];
+  A[1] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[2+k*12] * C[k];
+  A[2] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[3+k*12] * C[k];
+  A[3] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[4+k*12] * C[k];
+  A[4] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[5+k*12] * C[k];
+  A[5] = sum;
+}
+
+//***************************************************************************
+// testing stuff
+
+#ifdef TIMING
+#define IFTIMING(x) x
+#else
+#define IFTIMING(x) /* */
+#endif
+
+//***************************************************************************
+// various common computations involving the matrix J
+
+// compute iMJ = inv(M)*J'
+
+static void compute_invM_JT (int m, dRealMutablePtr J, dRealMutablePtr iMJ, int *jb,
+	dxBody * const *body, dRealPtr invI)
+{
+	int i,j;
+	dRealMutablePtr iMJ_ptr = iMJ;
+	dRealMutablePtr J_ptr = J;
+	for (i=0; i<m; i++) {
+		int b1 = jb[i*2];
+		int b2 = jb[i*2+1];
+		dReal k = body[b1]->invMass;
+		for (j=0; j<3; j++) iMJ_ptr[j] = k*J_ptr[j];
+		dMULTIPLY0_331 (iMJ_ptr + 3, invI + 12*b1, J_ptr + 3);
+		if (b2 >= 0) {
+			k = body[b2]->invMass;
+			for (j=0; j<3; j++) iMJ_ptr[j+6] = k*J_ptr[j+6];
+			dMULTIPLY0_331 (iMJ_ptr + 9, invI + 12*b2, J_ptr + 9);
+		}
+		J_ptr += 12;
+		iMJ_ptr += 12;
+	}
+}
+
+
+// compute out = inv(M)*J'*in.
+
+static void multiply_invM_JT (int m, int nb, dRealMutablePtr iMJ, int *jb,
+	dRealMutablePtr in, dRealMutablePtr out)
+{
+	int i,j;
+	dSetZero (out,6*nb);
+	dRealPtr iMJ_ptr = iMJ;
+	for (i=0; i<m; i++) {
+		int b1 = jb[i*2];
+		int b2 = jb[i*2+1];
+		dRealMutablePtr out_ptr = out + b1*6;
+		for (j=0; j<6; j++) out_ptr[j] += iMJ_ptr[j] * in[i];
+		iMJ_ptr += 6;
+		if (b2 >= 0) {
+			out_ptr = out + b2*6;
+			for (j=0; j<6; j++) out_ptr[j] += iMJ_ptr[j] * in[i];
+		}
+		iMJ_ptr += 6;
+	}
+}
+
+
+// compute out = J*in.
+
+static void multiply_J (int m, dRealMutablePtr J, int *jb,
+	dRealMutablePtr in, dRealMutablePtr out)
+{
+	int i,j;
+	dRealPtr J_ptr = J;
+	for (i=0; i<m; i++) {
+		int b1 = jb[i*2];
+		int b2 = jb[i*2+1];
+		dReal sum = 0;
+		dRealMutablePtr in_ptr = in + b1*6;
+		for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j];
+		J_ptr += 6;
+		if (b2 >= 0) {
+			in_ptr = in + b2*6;
+			for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j];
+		}
+		J_ptr += 6;
+		out[i] = sum;
+	}
+}
+
+
+// compute out = (J*inv(M)*J' + cfm)*in.
+// use z as an nb*6 temporary.
+
+static void multiply_J_invM_JT (int m, int nb, dRealMutablePtr J, dRealMutablePtr iMJ, int *jb,
+	dRealPtr cfm, dRealMutablePtr z, dRealMutablePtr in, dRealMutablePtr out)
+{
+	multiply_invM_JT (m,nb,iMJ,jb,in,z);
+	multiply_J (m,J,jb,z,out);
+
+	// add cfm
+	for (int i=0; i<m; i++) out[i] += cfm[i] * in[i];
+}
+
+//***************************************************************************
+// conjugate gradient method with jacobi preconditioner
+// THIS IS EXPERIMENTAL CODE that doesn't work too well, so it is ifdefed out.
+//
+// adding CFM seems to be critically important to this method.
+
+#if 0
+
+static inline dReal dot (int n, dRealPtr x, dRealPtr y)
+{
+	dReal sum=0;
+	for (int i=0; i<n; i++) sum += x[i]*y[i];
+	return sum;
+}
+
+
+// x = y + z*alpha
+
+static inline void add (int n, dRealMutablePtr x, dRealPtr y, dRealPtr z, dReal alpha)
+{
+	for (int i=0; i<n; i++) x[i] = y[i] + z[i]*alpha;
+}
+
+
+static void CG_LCP (int m, int nb, dRealMutablePtr J, int *jb, dxBody * const *body,
+	dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr fc, dRealMutablePtr b,
+	dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex,
+	dxQuickStepParameters *qs)
+{
+	int i,j;
+	const int num_iterations = qs->num_iterations;
+
+	// precompute iMJ = inv(M)*J'
+	dRealAllocaArray (iMJ,m*12);
+	compute_invM_JT (m,J,iMJ,jb,body,invI);
+
+	dReal last_rho = 0;
+	dRealAllocaArray (r,m);
+	dRealAllocaArray (z,m);
+	dRealAllocaArray (p,m);
+	dRealAllocaArray (q,m);
+
+	// precompute 1 / diagonals of A
+	dRealAllocaArray (Ad,m);
+	dRealPtr iMJ_ptr = iMJ;
+	dRealPtr J_ptr = J;
+	for (i=0; i<m; i++) {
+		dReal sum = 0;
+		for (j=0; j<6; j++) sum += iMJ_ptr[j] * J_ptr[j];
+		if (jb[i*2+1] >= 0) {
+			for (j=6; j<12; j++) sum += iMJ_ptr[j] * J_ptr[j];
+		}
+		iMJ_ptr += 12;
+		J_ptr += 12;
+		Ad[i] = REAL(1.0) / (sum + cfm[i]);
+	}
+
+#ifdef WARM_STARTING
+	// compute residual r = b - A*lambda
+	multiply_J_invM_JT (m,nb,J,iMJ,jb,cfm,fc,lambda,r);
+	for (i=0; i<m; i++) r[i] = b[i] - r[i];
+#else
+	dSetZero (lambda,m);
+	memcpy (r,b,m*sizeof(dReal));		// residual r = b - A*lambda
+#endif
+
+	for (int iteration=0; iteration < num_iterations; iteration++) {
+		for (i=0; i<m; i++) z[i] = r[i]*Ad[i];	// z = inv(M)*r
+		dReal rho = dot (m,r,z);		// rho = r'*z
+
+		// @@@
+		// we must check for convergence, otherwise rho will go to 0 if
+		// we get an exact solution, which will introduce NaNs into the equations.
+		if (rho < 1e-10) {
+			printf ("CG returned at iteration %d\n",iteration);
+			break;
+		}
+
+		if (iteration==0) {
+			memcpy (p,z,m*sizeof(dReal));	// p = z
+		}
+		else {
+			add (m,p,z,p,rho/last_rho);	// p = z + (rho/last_rho)*p
+		}
+
+		// compute q = (J*inv(M)*J')*p
+		multiply_J_invM_JT (m,nb,J,iMJ,jb,cfm,fc,p,q);
+
+		dReal alpha = rho/dot (m,p,q);		// alpha = rho/(p'*q)
+		add (m,lambda,lambda,p,alpha);		// lambda = lambda + alpha*p
+		add (m,r,r,q,-alpha);			// r = r - alpha*q
+		last_rho = rho;
+	}
+
+	// compute fc = inv(M)*J'*lambda
+	multiply_invM_JT (m,nb,iMJ,jb,lambda,fc);
+
+#if 0
+	// measure solution error
+	multiply_J_invM_JT (m,nb,J,iMJ,jb,cfm,fc,lambda,r);
+	dReal error = 0;
+	for (i=0; i<m; i++) error += dFabs(r[i] - b[i]);
+	printf ("lambda error = %10.6e\n",error);
+#endif
+}
+
+#endif
+
+//***************************************************************************
+// SOR-LCP method
+
+// nb is the number of bodies in the body array.
+// J is an m*12 matrix of constraint rows
+// jb is an array of first and second body numbers for each constraint row
+// invI is the global frame inverse inertia for each body (stacked 3x3 matrices)
+//
+// this returns lambda and fc (the constraint force).
+// note: fc is returned as inv(M)*J'*lambda, the constraint force is actually J'*lambda
+//
+// b, lo and hi are modified on exit
+
+
+struct IndexError {
+	dReal error;		// error to sort on
+	int findex;
+	int index;		// row index
+};
+
+
+#ifdef REORDER_CONSTRAINTS
+
+static int compare_index_error (const void *a, const void *b)
+{
+	const IndexError *i1 = (IndexError*) a;
+	const IndexError *i2 = (IndexError*) b;
+	if (i1->findex < 0 && i2->findex >= 0) return -1;
+	if (i1->findex >= 0 && i2->findex < 0) return 1;
+	if (i1->error < i2->error) return -1;
+	if (i1->error > i2->error) return 1;
+	return 0;
+}
+
+#endif
+
+
+static void SOR_LCP (int m, int nb, dRealMutablePtr J, int *jb, dxBody * const *body,
+	dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr fc, dRealMutablePtr b,
+	dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex,
+	dxQuickStepParameters *qs)
+{
+	const int num_iterations = qs->num_iterations;
+	const dReal sor_w = qs->w;		// SOR over-relaxation parameter
+
+	int i,j;
+
+#ifdef WARM_STARTING
+	// for warm starting, this seems to be necessary to prevent
+	// jerkiness in motor-driven joints. i have no idea why this works.
+	for (i=0; i<m; i++) lambda[i] *= 0.9;
+#else
+	dSetZero (lambda,m);
+#endif
+
+#ifdef REORDER_CONSTRAINTS
+	// the lambda computed at the previous iteration.
+	// this is used to measure error for when we are reordering the indexes.
+	dRealAllocaArray (last_lambda,m);
+#endif
+
+	// a copy of the 'hi' vector in case findex[] is being used
+	dRealAllocaArray (hicopy,m);
+	memcpy (hicopy,hi,m*sizeof(dReal));
+
+	// precompute iMJ = inv(M)*J'
+	dRealAllocaArray (iMJ,m*12);
+	compute_invM_JT (m,J,iMJ,jb,body,invI);
+
+	// compute fc=(inv(M)*J')*lambda. we will incrementally maintain fc
+	// as we change lambda.
+#ifdef WARM_STARTING
+	multiply_invM_JT (m,nb,iMJ,jb,lambda,fc);
+#else
+	dSetZero (fc,nb*6);
+#endif
+
+	// precompute 1 / diagonals of A
+	dRealAllocaArray (Ad,m);
+	dRealPtr iMJ_ptr = iMJ;
+	dRealMutablePtr J_ptr = J;
+	for (i=0; i<m; i++) {
+		dReal sum = 0;
+		for (j=0; j<6; j++) sum += iMJ_ptr[j] * J_ptr[j];
+		if (jb[i*2+1] >= 0) {
+			for (j=6; j<12; j++) sum += iMJ_ptr[j] * J_ptr[j];
+		}
+		iMJ_ptr += 12;
+		J_ptr += 12;
+		Ad[i] = sor_w / (sum + cfm[i]);
+	}
+
+	// scale J and b by Ad
+	J_ptr = J;
+	for (i=0; i<m; i++) {
+		for (j=0; j<12; j++) {
+			J_ptr[0] *= Ad[i];
+			J_ptr++;
+		}
+		b[i] *= Ad[i];
+
+		// scale Ad by CFM. N.B. this should be done last since it is used above
+		Ad[i] *= cfm[i];
+	}
+
+	// order to solve constraint rows in
+	IndexError *order = (IndexError*) ALLOCA (m*sizeof(IndexError));
+
+#ifndef REORDER_CONSTRAINTS
+	// make sure constraints with findex < 0 come first.
+	j=0;
+	int k=1;
+
+	// Fill the array from both ends
+	for (i=0; i<m; i++)
+		if (findex[i] < 0)
+			order[j++].index = i; // Place them at the front
+		else
+			order[m-k++].index = i; // Place them at the end
+
+	dIASSERT ((j+k-1)==m); // -1 since k was started at 1 and not 0
+#endif
+
+	for (int iteration=0; iteration < num_iterations; iteration++) {
+
+#ifdef REORDER_CONSTRAINTS
+		// constraints with findex < 0 always come first.
+		if (iteration < 2) {
+			// for the first two iterations, solve the constraints in
+			// the given order
+			for (i=0; i<m; i++) {
+				order[i].error = i;
+				order[i].findex = findex[i];
+				order[i].index = i;
+			}
+		}
+		else {
+			// sort the constraints so that the ones converging slowest
+			// get solved last. use the absolute (not relative) error.
+			for (i=0; i<m; i++) {
+				dReal v1 = dFabs (lambda[i]);
+				dReal v2 = dFabs (last_lambda[i]);
+				dReal max = (v1 > v2) ? v1 : v2;
+				if (max > 0) {
+					//@@@ relative error: order[i].error = dFabs(lambda[i]-last_lambda[i])/max;
+					order[i].error = dFabs(lambda[i]-last_lambda[i]);
+				}
+				else {
+					order[i].error = dInfinity;
+				}
+				order[i].findex = findex[i];
+				order[i].index = i;
+			}
+		}
+		qsort (order,m,sizeof(IndexError),&compare_index_error);
+
+		//@@@ potential optimization: swap lambda and last_lambda pointers rather
+		//    than copying the data. we must make sure lambda is properly
+		//    returned to the caller
+		memcpy (last_lambda,lambda,m*sizeof(dReal));
+#endif
+#ifdef RANDOMLY_REORDER_CONSTRAINTS
+		if ((iteration & 7) == 0) {
+			for (i=1; i<m; ++i) {
+				IndexError tmp = order[i];
+				int swapi = dRandInt(i+1);
+				order[i] = order[swapi];
+				order[swapi] = tmp;
+			}
+		}
+#endif
+
+		for (int i=0; i<m; i++) {
+			// @@@ potential optimization: we could pre-sort J and iMJ, thereby
+			//     linearizing access to those arrays. hmmm, this does not seem
+			//     like a win, but we should think carefully about our memory
+			//     access pattern.
+
+			int index = order[i].index;
+			J_ptr = J + index*12;
+			iMJ_ptr = iMJ + index*12;
+
+			// set the limits for this constraint. note that 'hicopy' is used.
+			// this is the place where the QuickStep method differs from the
+			// direct LCP solving method, since that method only performs this
+			// limit adjustment once per time step, whereas this method performs
+			// once per iteration per constraint row.
+			// the constraints are ordered so that all lambda[] values needed have
+			// already been computed.
+			if (findex[index] >= 0) {
+				hi[index] = dFabs (hicopy[index] * lambda[findex[index]]);
+				lo[index] = -hi[index];
+			}
+
+			int b1 = jb[index*2];
+			int b2 = jb[index*2+1];
+			dReal delta = b[index] - lambda[index]*Ad[index];
+			dRealMutablePtr fc_ptr = fc + 6*b1;
+
+			// @@@ potential optimization: SIMD-ize this and the b2 >= 0 case
+			delta -=fc_ptr[0] * J_ptr[0] + fc_ptr[1] * J_ptr[1] +
+				fc_ptr[2] * J_ptr[2] + fc_ptr[3] * J_ptr[3] +
+				fc_ptr[4] * J_ptr[4] + fc_ptr[5] * J_ptr[5];
+			// @@@ potential optimization: handle 1-body constraints in a separate
+			//     loop to avoid the cost of test & jump?
+			if (b2 >= 0) {
+				fc_ptr = fc + 6*b2;
+				delta -=fc_ptr[0] * J_ptr[6] + fc_ptr[1] * J_ptr[7] +
+					fc_ptr[2] * J_ptr[8] + fc_ptr[3] * J_ptr[9] +
+					fc_ptr[4] * J_ptr[10] + fc_ptr[5] * J_ptr[11];
+			}
+
+			// compute lambda and clamp it to [lo,hi].
+			// @@@ potential optimization: does SSE have clamping instructions
+			//     to save test+jump penalties here?
+			dReal new_lambda = lambda[index] + delta;
+			if (new_lambda < lo[index]) {
+				delta = lo[index]-lambda[index];
+				lambda[index] = lo[index];
+			}
+			else if (new_lambda > hi[index]) {
+				delta = hi[index]-lambda[index];
+				lambda[index] = hi[index];
+			}
+			else {
+				lambda[index] = new_lambda;
+			}
+
+			//@@@ a trick that may or may not help
+			//dReal ramp = (1-((dReal)(iteration+1)/(dReal)num_iterations));
+			//delta *= ramp;
+
+			// update fc.
+			// @@@ potential optimization: SIMD for this and the b2 >= 0 case
+			fc_ptr = fc + 6*b1;
+			fc_ptr[0] += delta * iMJ_ptr[0];
+			fc_ptr[1] += delta * iMJ_ptr[1];
+			fc_ptr[2] += delta * iMJ_ptr[2];
+			fc_ptr[3] += delta * iMJ_ptr[3];
+			fc_ptr[4] += delta * iMJ_ptr[4];
+			fc_ptr[5] += delta * iMJ_ptr[5];
+			// @@@ potential optimization: handle 1-body constraints in a separate
+			//     loop to avoid the cost of test & jump?
+			if (b2 >= 0) {
+				fc_ptr = fc + 6*b2;
+				fc_ptr[0] += delta * iMJ_ptr[6];
+				fc_ptr[1] += delta * iMJ_ptr[7];
+				fc_ptr[2] += delta * iMJ_ptr[8];
+				fc_ptr[3] += delta * iMJ_ptr[9];
+				fc_ptr[4] += delta * iMJ_ptr[10];
+				fc_ptr[5] += delta * iMJ_ptr[11];
+			}
+		}
+	}
+}
+
+
+void dxQuickStepper (dxWorld *world, dxBody * const *body, int nb,
+		     dxJoint * const *_joint, int nj, dReal stepsize)
+{
+	int i,j;
+	IFTIMING(dTimerStart("preprocessing");)
+
+	dReal stepsize1 = dRecip(stepsize);
+
+	// number all bodies in the body list - set their tag values
+	for (i=0; i<nb; i++) body[i]->tag = i;
+
+	// make a local copy of the joint array, because we might want to modify it.
+	// (the "dxJoint *const*" declaration says we're allowed to modify the joints
+	// but not the joint array, because the caller might need it unchanged).
+	//@@@ do we really need to do this? we'll be sorting constraint rows individually, not joints
+	dxJoint **joint = (dxJoint**) ALLOCA (nj * sizeof(dxJoint*));
+	memcpy (joint,_joint,nj * sizeof(dxJoint*));
+
+	// for all bodies, compute the inertia tensor and its inverse in the global
+	// frame, and compute the rotational force and add it to the torque
+	// accumulator. I and invI are a vertical stack of 3x4 matrices, one per body.
+	//dRealAllocaArray (I,3*4*nb);	// need to remember all I's for feedback purposes only
+	dRealAllocaArray (invI,3*4*nb);
+	for (i=0; i<nb; i++) {
+		dMatrix3 tmp;
+
+		// compute inverse inertia tensor in global frame
+		dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->posr.R);
+		dMULTIPLY0_333 (invI+i*12,body[i]->posr.R,tmp);
+#ifdef dGYROSCOPIC
+		dMatrix3 I;
+		// compute inertia tensor in global frame
+		dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->posr.R);
+		//dMULTIPLY0_333 (I+i*12,body[i]->posr.R,tmp);
+		dMULTIPLY0_333 (I,body[i]->posr.R,tmp);
+		// compute rotational force
+		//dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
+		dMULTIPLY0_331 (tmp,I,body[i]->avel);
+		dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
+#endif
+	}
+
+	// add the gravity force to all bodies
+	for (i=0; i<nb; i++) {
+		if ((body[i]->flags & dxBodyNoGravity)==0) {
+			body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
+			body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
+			body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
+		}
+	}
+
+	// get joint information (m = total constraint dimension, nub = number of unbounded variables).
+	// joints with m=0 are inactive and are removed from the joints array
+	// entirely, so that the code that follows does not consider them.
+	//@@@ do we really need to save all the info1's
+	dxJoint::Info1 *info = (dxJoint::Info1*) ALLOCA (nj*sizeof(dxJoint::Info1));
+	for (i=0, j=0; j<nj; j++) {	// i=dest, j=src
+		joint[j]->vtable->getInfo1 (joint[j],info+i);
+		dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m);
+		if (info[i].m > 0) {
+			joint[i] = joint[j];
+			i++;
+		}
+	}
+	nj = i;
+
+	// create the row offset array
+	int m = 0;
+	int *ofs = (int*) ALLOCA (nj*sizeof(int));
+	for (i=0; i<nj; i++) {
+		ofs[i] = m;
+		m += info[i].m;
+	}
+
+	// if there are constraints, compute the constraint force
+	dRealAllocaArray (J,m*12);
+	int *jb = (int*) ALLOCA (m*2*sizeof(int));
+	if (m > 0) {
+		// create a constraint equation right hand side vector `c', a constraint
+		// force mixing vector `cfm', and LCP low and high bound vectors, and an
+		// 'findex' vector.
+		dRealAllocaArray (c,m);
+		dRealAllocaArray (cfm,m);
+		dRealAllocaArray (lo,m);
+		dRealAllocaArray (hi,m);
+		int *findex = (int*) ALLOCA (m*sizeof(int));
+		dSetZero (c,m);
+		dSetValue (cfm,m,world->global_cfm);
+		dSetValue (lo,m,-dInfinity);
+		dSetValue (hi,m, dInfinity);
+		for (i=0; i<m; i++) findex[i] = -1;
+
+		// get jacobian data from constraints. an m*12 matrix will be created
+		// to store the two jacobian blocks from each constraint. it has this
+		// format:
+		//
+		//   l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 \    .
+		//   l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2  }-- jacobian for joint 0, body 1 and body 2 (3 rows)
+		//   l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 /
+		//   l1 l1 l1 a1 a1 a1 l2 l2 l2 a2 a2 a2 }--- jacobian for joint 1, body 1 and body 2 (3 rows)
+		//   etc...
+		//
+		//   (lll) = linear jacobian data
+		//   (aaa) = angular jacobian data
+		//
+		IFTIMING (dTimerNow ("create J");)
+		dSetZero (J,m*12);
+		dxJoint::Info2 Jinfo;
+		Jinfo.rowskip = 12;
+		Jinfo.fps = stepsize1;
+		Jinfo.erp = world->global_erp;
+		int mfb = 0; // number of rows of Jacobian we will have to save for joint feedback
+		for (i=0; i<nj; i++) {
+			Jinfo.J1l = J + ofs[i]*12;
+			Jinfo.J1a = Jinfo.J1l + 3;
+			Jinfo.J2l = Jinfo.J1l + 6;
+			Jinfo.J2a = Jinfo.J1l + 9;
+			Jinfo.c = c + ofs[i];
+			Jinfo.cfm = cfm + ofs[i];
+			Jinfo.lo = lo + ofs[i];
+			Jinfo.hi = hi + ofs[i];
+			Jinfo.findex = findex + ofs[i];
+			joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
+			// adjust returned findex values for global index numbering
+			for (j=0; j<info[i].m; j++) {
+				if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
+			}
+			if (joint[i]->feedback)
+				mfb += info[i].m;
+		}
+
+		// we need a copy of Jacobian for joint feedbacks
+		// because it gets destroyed by SOR solver
+		// instead of saving all Jacobian, we can save just rows
+		// for joints, that requested feedback (which is normaly much less)
+		dRealAllocaArray (Jcopy,mfb*12);
+		if (mfb > 0) {
+			mfb = 0;
+			for (i=0; i<nj; i++)
+				if (joint[i]->feedback) {
+					memcpy(Jcopy+mfb*12, J+ofs[i]*12, info[i].m*12*sizeof(dReal));
+					mfb += info[i].m;
+				}
+		}
+
+
+		// create an array of body numbers for each joint row
+		int *jb_ptr = jb;
+		for (i=0; i<nj; i++) {
+			int b1 = (joint[i]->node[0].body) ? (joint[i]->node[0].body->tag) : -1;
+			int b2 = (joint[i]->node[1].body) ? (joint[i]->node[1].body->tag) : -1;
+			for (j=0; j<info[i].m; j++) {
+				jb_ptr[0] = b1;
+				jb_ptr[1] = b2;
+				jb_ptr += 2;
+			}
+		}
+		dIASSERT (jb_ptr == jb+2*m);
+
+		// compute the right hand side `rhs'
+		IFTIMING (dTimerNow ("compute rhs");)
+		dRealAllocaArray (tmp1,nb*6);
+		// put v/h + invM*fe into tmp1
+		for (i=0; i<nb; i++) {
+			dReal body_invMass = body[i]->invMass;
+			for (j=0; j<3; j++) tmp1[i*6+j] = body[i]->facc[j] * body_invMass + body[i]->lvel[j] * stepsize1;
+			dMULTIPLY0_331 (tmp1 + i*6 + 3,invI + i*12,body[i]->tacc);
+			for (j=0; j<3; j++) tmp1[i*6+3+j] += body[i]->avel[j] * stepsize1;
+		}
+
+		// put J*tmp1 into rhs
+		dRealAllocaArray (rhs,m);
+		multiply_J (m,J,jb,tmp1,rhs);
+
+		// complete rhs
+		for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i];
+
+		// scale CFM
+		for (i=0; i<m; i++) cfm[i] *= stepsize1;
+
+		// load lambda from the value saved on the previous iteration
+		dRealAllocaArray (lambda,m);
+#ifdef WARM_STARTING
+		dSetZero (lambda,m);	//@@@ shouldn't be necessary
+		for (i=0; i<nj; i++) {
+			memcpy (lambda+ofs[i],joint[i]->lambda,info[i].m * sizeof(dReal));
+		}
+#endif
+
+		// solve the LCP problem and get lambda and invM*constraint_force
+		IFTIMING (dTimerNow ("solving LCP problem");)
+		dRealAllocaArray (cforce,nb*6);
+		SOR_LCP (m,nb,J,jb,body,invI,lambda,cforce,rhs,lo,hi,cfm,findex,&world->qs);
+
+#ifdef WARM_STARTING
+		// save lambda for the next iteration
+		//@@@ note that this doesn't work for contact joints yet, as they are
+		// recreated every iteration
+		for (i=0; i<nj; i++) {
+			memcpy (joint[i]->lambda,lambda+ofs[i],info[i].m * sizeof(dReal));
+		}
+#endif
+
+		// note that the SOR method overwrites rhs and J at this point, so
+		// they should not be used again.
+
+		// add stepsize * cforce to the body velocity
+		for (i=0; i<nb; i++) {
+			for (j=0; j<3; j++) body[i]->lvel[j] += stepsize * cforce[i*6+j];
+			for (j=0; j<3; j++) body[i]->avel[j] += stepsize * cforce[i*6+3+j];
+		}
+
+		// if joint feedback is requested, compute the constraint force.
+		// BUT: cforce is inv(M)*J'*lambda, whereas we want just J'*lambda,
+		// so we must compute M*cforce.
+		// @@@ if any joint has a feedback request we compute the entire
+		//     adjusted cforce, which is not the most efficient way to do it.
+		/*for (j=0; j<nj; j++) {
+			if (joint[j]->feedback) {
+				// compute adjusted cforce
+				for (i=0; i<nb; i++) {
+					dReal k = body[i]->mass.mass;
+					cforce [i*6+0] *= k;
+					cforce [i*6+1] *= k;
+					cforce [i*6+2] *= k;
+					dVector3 tmp;
+					dMULTIPLY0_331 (tmp, I + 12*i, cforce + i*6 + 3);
+					cforce [i*6+3] = tmp[0];
+					cforce [i*6+4] = tmp[1];
+					cforce [i*6+5] = tmp[2];
+				}
+				// compute feedback for this and all remaining joints
+				for (; j<nj; j++) {
+					dJointFeedback *fb = joint[j]->feedback;
+					if (fb) {
+						int b1 = joint[j]->node[0].body->tag;
+						memcpy (fb->f1,cforce+b1*6,3*sizeof(dReal));
+						memcpy (fb->t1,cforce+b1*6+3,3*sizeof(dReal));
+						if (joint[j]->node[1].body) {
+							int b2 = joint[j]->node[1].body->tag;
+							memcpy (fb->f2,cforce+b2*6,3*sizeof(dReal));
+							memcpy (fb->t2,cforce+b2*6+3,3*sizeof(dReal));
+						}
+					}
+				}
+			}
+		}*/
+
+		if (mfb > 0) {
+			// straightforward computation of joint constraint forces:
+			// multiply related lambdas with respective J' block for joints
+			// where feedback was requested
+			mfb = 0;
+			for (i=0; i<nj; i++) {
+				if (joint[i]->feedback) {
+					dJointFeedback *fb = joint[i]->feedback;
+					dReal data[6];
+					Multiply1_12q1 (data, Jcopy+mfb*12, lambda+ofs[i], info[i].m);
+					fb->f1[0] = data[0];
+					fb->f1[1] = data[1];
+					fb->f1[2] = data[2];
+					fb->t1[0] = data[3];
+					fb->t1[1] = data[4];
+					fb->t1[2] = data[5];
+					if (joint[i]->node[1].body)
+					{
+						Multiply1_12q1 (data, Jcopy+mfb*12+6, lambda+ofs[i], info[i].m);
+						fb->f2[0] = data[0];
+						fb->f2[1] = data[1];
+						fb->f2[2] = data[2];
+						fb->t2[0] = data[3];
+						fb->t2[1] = data[4];
+						fb->t2[2] = data[5];
+					}
+					mfb += info[i].m;
+				}
+			}
+		}
+	}
+
+	// compute the velocity update:
+	// add stepsize * invM * fe to the body velocity
+
+	IFTIMING (dTimerNow ("compute velocity update");)
+	for (i=0; i<nb; i++) {
+		dReal body_invMass = body[i]->invMass;
+		for (j=0; j<3; j++) body[i]->lvel[j] += stepsize * body_invMass * body[i]->facc[j];
+		for (j=0; j<3; j++) body[i]->tacc[j] *= stepsize;
+		dMULTIPLYADD0_331 (body[i]->avel,invI + i*12,body[i]->tacc);
+	}
+
+#if 0
+	// check that the updated velocity obeys the constraint (this check needs unmodified J)
+	dRealAllocaArray (vel,nb*6);
+	for (i=0; i<nb; i++) {
+		for (j=0; j<3; j++) vel[i*6+j] = body[i]->lvel[j];
+		for (j=0; j<3; j++) vel[i*6+3+j] = body[i]->avel[j];
+	}
+	dRealAllocaArray (tmp,m);
+	multiply_J (m,J,jb,vel,tmp);
+	dReal error = 0;
+	for (i=0; i<m; i++) error += dFabs(tmp[i]);
+	printf ("velocity error = %10.6e\n",error);
+#endif
+
+	// update the position and orientation from the new linear/angular velocity
+	// (over the given timestep)
+	IFTIMING (dTimerNow ("update position");)
+	for (i=0; i<nb; i++) dxStepBody (body[i],stepsize);
+
+	IFTIMING (dTimerNow ("tidy up");)
+
+	// zero all force accumulators
+	for (i=0; i<nb; i++) {
+		dSetZero (body[i]->facc,3);
+		dSetZero (body[i]->tacc,3);
+	}
+
+	IFTIMING (dTimerEnd();)
+	IFTIMING (if (m > 0) dTimerReport (stdout,1);)
+}
Index: /code/branches/ode/ode-0.9/ode/src/quickstep.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/quickstep.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/quickstep.h	(revision 216)
@@ -0,0 +1,33 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_QUICK_STEP_H_
+#define _ODE_QUICK_STEP_H_
+
+#include <ode/common.h>
+
+
+void dxQuickStepper (dxWorld *world, dxBody * const *body, int nb,
+		     dxJoint * const *_joint, int nj, dReal stepsize);
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/ray.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/ray.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/ray.cpp	(revision 216)
@@ -0,0 +1,686 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+standard ODE geometry primitives: public API and pairwise collision functions.
+
+the rule is that only the low level primitive collision functions should set
+dContactGeom::g1 and dContactGeom::g2.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+//****************************************************************************
+// ray public API
+
+dxRay::dxRay (dSpaceID space, dReal _length) : dxGeom (space,1)
+{
+  type = dRayClass;
+  length = _length;
+}
+
+
+void dxRay::computeAABB()
+{
+  dVector3 e;
+  e[0] = final_posr->pos[0] + final_posr->R[0*4+2]*length;
+  e[1] = final_posr->pos[1] + final_posr->R[1*4+2]*length;
+  e[2] = final_posr->pos[2] + final_posr->R[2*4+2]*length;
+
+  if (final_posr->pos[0] < e[0]){
+    aabb[0] = final_posr->pos[0];
+    aabb[1] = e[0];
+  }
+  else{
+    aabb[0] = e[0];
+    aabb[1] = final_posr->pos[0];
+  }
+  
+  if (final_posr->pos[1] < e[1]){
+    aabb[2] = final_posr->pos[1];
+    aabb[3] = e[1];
+  }
+  else{
+    aabb[2] = e[1];
+    aabb[3] = final_posr->pos[1];
+  }
+
+  if (final_posr->pos[2] < e[2]){
+    aabb[4] = final_posr->pos[2];
+    aabb[5] = e[2];
+  }
+  else{
+    aabb[4] = e[2];
+    aabb[5] = final_posr->pos[2];
+  }
+}
+
+
+dGeomID dCreateRay (dSpaceID space, dReal length)
+{
+  return new dxRay (space,length);
+}
+
+
+void dGeomRaySetLength (dGeomID g, dReal length)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+  dxRay *r = (dxRay*) g;
+  r->length = length;
+  dGeomMoved (g);
+}
+
+
+dReal dGeomRayGetLength (dGeomID g)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+  dxRay *r = (dxRay*) g;
+  return r->length;
+}
+
+
+void dGeomRaySet (dGeomID g, dReal px, dReal py, dReal pz,
+		  dReal dx, dReal dy, dReal dz)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+  g->recomputePosr();
+  dReal* rot = g->final_posr->R;
+  dReal* pos = g->final_posr->pos;
+  dVector3 n;
+  pos[0] = px;
+  pos[1] = py;
+  pos[2] = pz;
+
+  n[0] = dx;
+  n[1] = dy;
+  n[2] = dz;
+  dNormalize3(n);
+  rot[0*4+2] = n[0];
+  rot[1*4+2] = n[1];
+  rot[2*4+2] = n[2];
+  dGeomMoved (g);
+}
+
+
+void dGeomRayGet (dGeomID g, dVector3 start, dVector3 dir)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+  g->recomputePosr();
+  start[0] = g->final_posr->pos[0];
+  start[1] = g->final_posr->pos[1];
+  start[2] = g->final_posr->pos[2];
+  dir[0] = g->final_posr->R[0*4+2];
+  dir[1] = g->final_posr->R[1*4+2];
+  dir[2] = g->final_posr->R[2*4+2];
+}
+
+
+void dGeomRaySetParams (dxGeom *g, int FirstContact, int BackfaceCull)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+
+  if (FirstContact){
+    g->gflags |= RAY_FIRSTCONTACT;
+  }
+  else g->gflags &= ~RAY_FIRSTCONTACT;
+
+  if (BackfaceCull){
+    g->gflags |= RAY_BACKFACECULL;
+  }
+  else g->gflags &= ~RAY_BACKFACECULL;
+}
+
+
+void dGeomRayGetParams (dxGeom *g, int *FirstContact, int *BackfaceCull)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+
+  (*FirstContact) = ((g->gflags & RAY_FIRSTCONTACT) != 0);
+  (*BackfaceCull) = ((g->gflags & RAY_BACKFACECULL) != 0);
+}
+
+
+void dGeomRaySetClosestHit (dxGeom *g, int closestHit)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+  if (closestHit){
+    g->gflags |= RAY_CLOSEST_HIT;
+  }
+  else g->gflags &= ~RAY_CLOSEST_HIT;
+}
+
+
+int dGeomRayGetClosestHit (dxGeom *g)
+{
+  dUASSERT (g && g->type == dRayClass,"argument not a ray");
+  return ((g->gflags & RAY_CLOSEST_HIT) != 0);
+}
+
+
+
+// if mode==1 then use the sphere exit contact, not the entry contact
+
+static int ray_sphere_helper (dxRay *ray, dVector3 sphere_pos, dReal radius,
+			      dContactGeom *contact, int mode)
+{
+  dVector3 q;
+  q[0] = ray->final_posr->pos[0] - sphere_pos[0];
+  q[1] = ray->final_posr->pos[1] - sphere_pos[1];
+  q[2] = ray->final_posr->pos[2] - sphere_pos[2];
+  dReal B = dDOT14(q,ray->final_posr->R+2);
+  dReal C = dDOT(q,q) - radius*radius;
+  // note: if C <= 0 then the start of the ray is inside the sphere
+  dReal k = B*B - C;
+  if (k < 0) return 0;
+  k = dSqrt(k);
+  dReal alpha;
+  if (mode && C >= 0) {
+    alpha = -B + k;
+    if (alpha < 0) return 0;
+  }
+  else {
+    alpha = -B - k;
+    if (alpha < 0) {
+      alpha = -B + k;
+      if (alpha < 0) return 0;
+    }
+  }
+  if (alpha > ray->length) return 0;
+  contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
+  contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
+  contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
+  dReal nsign = (C < 0 || mode) ? REAL(-1.0) : REAL(1.0);
+  contact->normal[0] = nsign*(contact->pos[0] - sphere_pos[0]);
+  contact->normal[1] = nsign*(contact->pos[1] - sphere_pos[1]);
+  contact->normal[2] = nsign*(contact->pos[2] - sphere_pos[2]);
+  dNormalize3 (contact->normal);
+  contact->depth = alpha;
+  return 1;
+}
+
+
+int dCollideRaySphere (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dRayClass);
+  dIASSERT (o2->type == dSphereClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxRay *ray = (dxRay*) o1;
+  dxSphere *sphere = (dxSphere*) o2;
+  contact->g1 = ray;
+  contact->g2 = sphere;
+  return ray_sphere_helper (ray,sphere->final_posr->pos,sphere->radius,contact,0);
+}
+
+
+int dCollideRayBox (dxGeom *o1, dxGeom *o2, int flags,
+		    dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dRayClass);
+  dIASSERT (o2->type == dBoxClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxRay *ray = (dxRay*) o1;
+  dxBox *box = (dxBox*) o2;
+
+  contact->g1 = ray;
+  contact->g2 = box;
+
+  int i;
+
+  // compute the start and delta of the ray relative to the box.
+  // we will do all subsequent computations in this box-relative coordinate
+  // system. we have to do a translation and rotation for each point.
+  dVector3 tmp,s,v;
+  tmp[0] = ray->final_posr->pos[0] - box->final_posr->pos[0];
+  tmp[1] = ray->final_posr->pos[1] - box->final_posr->pos[1];
+  tmp[2] = ray->final_posr->pos[2] - box->final_posr->pos[2];
+  dMULTIPLY1_331 (s,box->final_posr->R,tmp);
+  tmp[0] = ray->final_posr->R[0*4+2];
+  tmp[1] = ray->final_posr->R[1*4+2];
+  tmp[2] = ray->final_posr->R[2*4+2];
+  dMULTIPLY1_331 (v,box->final_posr->R,tmp);
+
+  // mirror the line so that v has all components >= 0
+  dVector3 sign;
+  for (i=0; i<3; i++) {
+    if (v[i] < 0) {
+      s[i] = -s[i];
+      v[i] = -v[i];
+      sign[i] = 1;
+    }
+    else sign[i] = -1;
+  }
+
+  // compute the half-sides of the box
+  dReal h[3];
+  h[0] = REAL(0.5) * box->side[0];
+  h[1] = REAL(0.5) * box->side[1];
+  h[2] = REAL(0.5) * box->side[2];
+
+  // do a few early exit tests
+  if ((s[0] < -h[0] && v[0] <= 0) || s[0] >  h[0] ||
+      (s[1] < -h[1] && v[1] <= 0) || s[1] >  h[1] ||
+      (s[2] < -h[2] && v[2] <= 0) || s[2] >  h[2] ||
+      (v[0] == 0 && v[1] == 0 && v[2] == 0)) {
+    return 0;
+  }
+
+  // compute the t=[lo..hi] range for where s+v*t intersects the box
+  dReal lo = -dInfinity;
+  dReal hi = dInfinity;
+  int nlo = 0, nhi = 0;
+  for (i=0; i<3; i++) {
+    if (v[i] != 0) {
+      dReal k = (-h[i] - s[i])/v[i];
+      if (k > lo) {
+	lo = k;
+	nlo = i;
+      }
+      k = (h[i] - s[i])/v[i];
+      if (k < hi) {
+	hi = k;
+	nhi = i;
+      }
+    }
+  }
+
+  // check if the ray intersects
+  if (lo > hi) return 0;
+  dReal alpha;
+  int n;
+  if (lo >= 0) {
+    alpha = lo;
+    n = nlo;
+  }
+  else {
+    alpha = hi;
+    n = nhi;
+  }
+  if (alpha < 0 || alpha > ray->length) return 0;
+  contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
+  contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
+  contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
+  contact->normal[0] = box->final_posr->R[0*4+n] * sign[n];
+  contact->normal[1] = box->final_posr->R[1*4+n] * sign[n];
+  contact->normal[2] = box->final_posr->R[2*4+n] * sign[n];
+  contact->depth = alpha;
+  return 1;
+}
+
+
+int dCollideRayCapsule (dxGeom *o1, dxGeom *o2,
+			  int flags, dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dRayClass);
+  dIASSERT (o2->type == dCapsuleClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxRay *ray = (dxRay*) o1;
+  dxCapsule *ccyl = (dxCapsule*) o2;
+
+  contact->g1 = ray;
+  contact->g2 = ccyl;
+  dReal lz2 = ccyl->lz * REAL(0.5);
+
+  // compute some useful info
+  dVector3 cs,q,r;
+  dReal C,k;
+  cs[0] = ray->final_posr->pos[0] - ccyl->final_posr->pos[0];
+  cs[1] = ray->final_posr->pos[1] - ccyl->final_posr->pos[1];
+  cs[2] = ray->final_posr->pos[2] - ccyl->final_posr->pos[2];
+  k = dDOT41(ccyl->final_posr->R+2,cs);	// position of ray start along ccyl axis
+  q[0] = k*ccyl->final_posr->R[0*4+2] - cs[0];
+  q[1] = k*ccyl->final_posr->R[1*4+2] - cs[1];
+  q[2] = k*ccyl->final_posr->R[2*4+2] - cs[2];
+  C = dDOT(q,q) - ccyl->radius*ccyl->radius;
+  // if C < 0 then ray start position within infinite extension of cylinder
+
+  // see if ray start position is inside the capped cylinder
+  int inside_ccyl = 0;
+  if (C < 0) {
+    if (k < -lz2) k = -lz2;
+    else if (k > lz2) k = lz2;
+    r[0] = ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2];
+    r[1] = ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2];
+    r[2] = ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2];
+    if ((ray->final_posr->pos[0]-r[0])*(ray->final_posr->pos[0]-r[0]) +
+	(ray->final_posr->pos[1]-r[1])*(ray->final_posr->pos[1]-r[1]) +
+	(ray->final_posr->pos[2]-r[2])*(ray->final_posr->pos[2]-r[2]) < ccyl->radius*ccyl->radius) {
+      inside_ccyl = 1;
+    }
+  }
+
+  // compute ray collision with infinite cylinder, except for the case where
+  // the ray is outside the capped cylinder but within the infinite cylinder
+  // (it that case the ray can only hit endcaps)
+  if (!inside_ccyl && C < 0) {
+    // set k to cap position to check
+    if (k < 0) k = -lz2; else k = lz2;
+  }
+  else {
+    dReal uv = dDOT44(ccyl->final_posr->R+2,ray->final_posr->R+2);
+    r[0] = uv*ccyl->final_posr->R[0*4+2] - ray->final_posr->R[0*4+2];
+    r[1] = uv*ccyl->final_posr->R[1*4+2] - ray->final_posr->R[1*4+2];
+    r[2] = uv*ccyl->final_posr->R[2*4+2] - ray->final_posr->R[2*4+2];
+    dReal A = dDOT(r,r);
+    dReal B = 2*dDOT(q,r);
+    k = B*B-4*A*C;
+    if (k < 0) {
+      // the ray does not intersect the infinite cylinder, but if the ray is
+      // inside and parallel to the cylinder axis it may intersect the end
+      // caps. set k to cap position to check.
+      if (!inside_ccyl) return 0;
+      if (uv < 0) k = -lz2; else k = lz2;
+    }
+    else {
+      k = dSqrt(k);
+      A = dRecip (2*A);
+      dReal alpha = (-B-k)*A;
+      if (alpha < 0) {
+	alpha = (-B+k)*A;
+	if (alpha < 0) return 0;
+      }
+      if (alpha > ray->length) return 0;
+
+      // the ray intersects the infinite cylinder. check to see if the
+      // intersection point is between the caps
+      contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
+      contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
+      contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
+      q[0] = contact->pos[0] - ccyl->final_posr->pos[0];
+      q[1] = contact->pos[1] - ccyl->final_posr->pos[1];
+      q[2] = contact->pos[2] - ccyl->final_posr->pos[2];
+      k = dDOT14(q,ccyl->final_posr->R+2);
+      dReal nsign = inside_ccyl ? REAL(-1.0) : REAL(1.0);
+      if (k >= -lz2 && k <= lz2) {
+	contact->normal[0] = nsign * (contact->pos[0] -
+				      (ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2]));
+	contact->normal[1] = nsign * (contact->pos[1] -
+				      (ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2]));
+	contact->normal[2] = nsign * (contact->pos[2] -
+				      (ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2]));
+	dNormalize3 (contact->normal);
+	contact->depth = alpha;
+	return 1;
+      }
+
+      // the infinite cylinder intersection point is not between the caps.
+      // set k to cap position to check.
+      if (k < 0) k = -lz2; else k = lz2;
+    }
+  }
+
+  // check for ray intersection with the caps. k must indicate the cap
+  // position to check
+  q[0] = ccyl->final_posr->pos[0] + k*ccyl->final_posr->R[0*4+2];
+  q[1] = ccyl->final_posr->pos[1] + k*ccyl->final_posr->R[1*4+2];
+  q[2] = ccyl->final_posr->pos[2] + k*ccyl->final_posr->R[2*4+2];
+  return ray_sphere_helper (ray,q,ccyl->radius,contact, inside_ccyl);
+}
+
+
+int dCollideRayPlane (dxGeom *o1, dxGeom *o2, int flags,
+		      dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dRayClass);
+  dIASSERT (o2->type == dPlaneClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxRay *ray = (dxRay*) o1;
+  dxPlane *plane = (dxPlane*) o2;
+
+  dReal alpha = plane->p[3] - dDOT (plane->p,ray->final_posr->pos);
+  // note: if alpha > 0 the starting point is below the plane
+  dReal nsign = (alpha > 0) ? REAL(-1.0) : REAL(1.0);
+  dReal k = dDOT14(plane->p,ray->final_posr->R+2);
+  if (k==0) return 0;		// ray parallel to plane
+  alpha /= k;
+  if (alpha < 0 || alpha > ray->length) return 0;
+  contact->pos[0] = ray->final_posr->pos[0] + alpha*ray->final_posr->R[0*4+2];
+  contact->pos[1] = ray->final_posr->pos[1] + alpha*ray->final_posr->R[1*4+2];
+  contact->pos[2] = ray->final_posr->pos[2] + alpha*ray->final_posr->R[2*4+2];
+  contact->normal[0] = nsign*plane->p[0];
+  contact->normal[1] = nsign*plane->p[1];
+  contact->normal[2] = nsign*plane->p[2];
+  contact->depth = alpha;
+  contact->g1 = ray;
+  contact->g2 = plane;
+  return 1;
+}
+
+// Ray - Cylinder collider by David Walters (June 2006)
+int dCollideRayCylinder( dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip )
+{
+	dIASSERT( skip >= (int)sizeof( dContactGeom ) );
+	dIASSERT( o1->type == dRayClass );
+	dIASSERT( o2->type == dCylinderClass );
+	dIASSERT( (flags & NUMC_MASK) >= 1 );
+
+	dxRay* ray = (dxRay*)( o1 );
+	dxCylinder* cyl = (dxCylinder*)( o2 );
+
+	// Fill in contact information.
+	contact->g1 = ray;
+	contact->g2 = cyl;
+
+	const dReal half_length = cyl->lz * REAL( 0.5 );
+
+	//
+	// Compute some useful info
+	//
+
+	dVector3 q, r;
+	dReal d, C, k;
+
+	// Vector 'r', line segment from C to R (ray start) ( r = R - C )
+	r[ 0 ] = ray->final_posr->pos[0] - cyl->final_posr->pos[0];
+	r[ 1 ] = ray->final_posr->pos[1] - cyl->final_posr->pos[1];
+	r[ 2 ] = ray->final_posr->pos[2] - cyl->final_posr->pos[2];
+
+	// Distance that ray start is along cyl axis ( Z-axis direction )
+	d = dDOT41( cyl->final_posr->R + 2, r );
+
+	//
+	// Compute vector 'q' representing the shortest line from R to the cylinder z-axis (Cz).
+	//
+	// Point on axis ( in world space ):	cp = ( d * Cz ) + C
+	//
+	// Line 'q' from R to cp:				q = cp - R
+	//										q = ( d * Cz ) + C - R
+	//										q = ( d * Cz ) - ( R - C )
+
+	q[ 0 ] = ( d * cyl->final_posr->R[0*4+2] ) - r[ 0 ];
+	q[ 1 ] = ( d * cyl->final_posr->R[1*4+2] ) - r[ 1 ];
+	q[ 2 ] = ( d * cyl->final_posr->R[2*4+2] ) - r[ 2 ];
+
+
+	// Compute square length of 'q'. Subtract from radius squared to
+	// get square distance 'C' between the line q and the radius.
+
+	// if C < 0 then ray start position is within infinite extension of cylinder
+
+	C = dDOT( q, q ) - ( cyl->radius * cyl->radius );
+
+	// Compute the projection of ray direction normal onto cylinder direction normal.
+	dReal uv = dDOT44( cyl->final_posr->R+2, ray->final_posr->R+2 );
+
+
+
+	//
+	// Find ray collision with infinite cylinder
+	//
+
+	// Compute vector from end of ray direction normal to projection on cylinder direction normal.
+	r[ 0 ] = ( uv * cyl->final_posr->R[0*4+2] ) - ray->final_posr->R[0*4+2];
+	r[ 1 ] = ( uv * cyl->final_posr->R[1*4+2] ) - ray->final_posr->R[1*4+2];
+	r[ 2 ] = ( uv * cyl->final_posr->R[2*4+2] ) - ray->final_posr->R[2*4+2];
+
+
+	// Quadratic Formula Magic
+	// Compute discriminant 'k':
+
+	// k < 0 : No intersection
+	// k = 0 : Tangent
+	// k > 0 : Intersection
+
+	dReal A = dDOT( r, r );
+	dReal B = 2 * dDOT( q, r );
+
+	k = B*B - 4*A*C;
+
+
+
+
+	//
+	// Collision with Flat Caps ?
+	//
+
+	// No collision with cylinder edge. ( Use epsilon here or we miss some obvious cases )
+	if ( k < dEpsilon && C <= 0 )
+	{
+		// The ray does not intersect the edge of the infinite cylinder,
+		// but the ray start is inside and so must run parallel to the axis.
+		// It may yet intersect an end cap. The following cases are valid:
+
+		//        -ve-cap , -half              centre               +half , +ve-cap
+		//  <<================|-------------------|------------->>>---|================>>
+		//                    |                                       |
+		//                    |                              d------------------->    1.
+		//   2.    d------------------>                               |
+		//   3.    <------------------d                               |
+		//                    |                              <-------------------d    4.
+		//                    |                                       |
+		//  <<================|-------------------|------------->>>---|===============>>
+
+		// Negative if the ray and cylinder axes point in opposite directions.
+		const dReal uvsign = ( uv < 0 ) ? REAL( -1.0 ) : REAL( 1.0 );
+
+		// Negative if the ray start is inside the cylinder
+		const dReal internal = ( d >= -half_length && d <= +half_length ) ? REAL( -1.0 ) : REAL( 1.0 );
+
+		// Ray and Cylinder axes run in the same direction ( cases 1, 2 )
+		// Ray and Cylinder axes run in opposite directions ( cases 3, 4 )
+		if ( ( ( uv > 0 ) && ( d + ( uvsign * ray->length ) < half_length * internal ) ) ||
+		     ( ( uv < 0 ) && ( d + ( uvsign * ray->length ) > half_length * internal ) ) )
+		{
+			return 0; // No intersection with caps or curved surface.
+		}
+
+		// Compute depth (distance from ray to cylinder)
+		contact->depth = ( ( -uvsign * d ) - ( internal * half_length ) );
+
+		// Compute contact point.
+		contact->pos[0] = ray->final_posr->pos[0] + ( contact->depth * ray->final_posr->R[0*4+2] );
+		contact->pos[1] = ray->final_posr->pos[1] + ( contact->depth * ray->final_posr->R[1*4+2] );
+		contact->pos[2] = ray->final_posr->pos[2] + ( contact->depth * ray->final_posr->R[2*4+2] );
+
+		// Compute reflected contact normal.
+		contact->normal[0] = uvsign * ( cyl->final_posr->R[0*4+2] );
+		contact->normal[1] = uvsign * ( cyl->final_posr->R[1*4+2] );
+		contact->normal[2] = uvsign * ( cyl->final_posr->R[2*4+2] );
+
+		// Contact!
+		return 1;
+	}
+
+
+
+	//
+	// Collision with Curved Edge ?
+	//
+
+	if ( k > 0 )
+	{
+		// Finish off quadratic formula to get intersection co-efficient
+		k = dSqrt( k );
+		A = dRecip( 2 * A );
+
+		// Compute distance along line to contact point.
+		dReal alpha = ( -B - k ) * A;
+		if ( alpha < 0 )
+		{
+			// Flip in the other direction.
+			alpha = ( -B + k ) * A;
+		}
+
+		// Intersection point is within ray length?
+		if ( alpha >= 0 && alpha <= ray->length )
+		{
+			// The ray intersects the infinite cylinder!
+
+			// Compute contact point.
+			contact->pos[0] = ray->final_posr->pos[0] + ( alpha * ray->final_posr->R[0*4+2] );
+			contact->pos[1] = ray->final_posr->pos[1] + ( alpha * ray->final_posr->R[1*4+2] );
+			contact->pos[2] = ray->final_posr->pos[2] + ( alpha * ray->final_posr->R[2*4+2] );
+
+			// q is the vector from the cylinder centre to the contact point.
+			q[0] = contact->pos[0] - cyl->final_posr->pos[0];
+			q[1] = contact->pos[1] - cyl->final_posr->pos[1];
+			q[2] = contact->pos[2] - cyl->final_posr->pos[2];
+
+			// Compute the distance along the cylinder axis of this contact point.
+			d = dDOT14( q, cyl->final_posr->R+2 );
+
+			// Check to see if the intersection point is between the flat end caps
+			if ( d >= -half_length && d <= +half_length )
+			{
+				// Flip the normal if the start point is inside the cylinder.
+				const dReal nsign = ( C < 0 ) ? REAL( -1.0 ) : REAL( 1.0 );
+
+				// Compute contact normal.
+				contact->normal[0] = nsign * (contact->pos[0] - (cyl->final_posr->pos[0] + d*cyl->final_posr->R[0*4+2]));
+				contact->normal[1] = nsign * (contact->pos[1] - (cyl->final_posr->pos[1] + d*cyl->final_posr->R[1*4+2]));
+				contact->normal[2] = nsign * (contact->pos[2] - (cyl->final_posr->pos[2] + d*cyl->final_posr->R[2*4+2]));
+				dNormalize3( contact->normal );
+
+				// Store depth.
+				contact->depth = alpha;
+
+				// Contact!
+				return 1;
+			}
+		}
+	}
+
+	// No contact with anything.
+	return 0;
+}
+
Index: /code/branches/ode/ode-0.9/ode/src/rotation.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/rotation.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/rotation.cpp	(revision 216)
@@ -0,0 +1,316 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+quaternions have the format: (s,vx,vy,vz) where (vx,vy,vz) is the
+"rotation axis" and s is the "rotation angle".
+
+*/
+
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+
+
+#define _R(i,j) R[(i)*4+(j)]
+
+#define SET_3x3_IDENTITY \
+  _R(0,0) = REAL(1.0); \
+  _R(0,1) = REAL(0.0); \
+  _R(0,2) = REAL(0.0); \
+  _R(0,3) = REAL(0.0); \
+  _R(1,0) = REAL(0.0); \
+  _R(1,1) = REAL(1.0); \
+  _R(1,2) = REAL(0.0); \
+  _R(1,3) = REAL(0.0); \
+  _R(2,0) = REAL(0.0); \
+  _R(2,1) = REAL(0.0); \
+  _R(2,2) = REAL(1.0); \
+  _R(2,3) = REAL(0.0);
+
+
+void dRSetIdentity (dMatrix3 R)
+{
+  dAASSERT (R);
+  SET_3x3_IDENTITY;
+}
+
+
+void dRFromAxisAndAngle (dMatrix3 R, dReal ax, dReal ay, dReal az,
+			 dReal angle)
+{
+  dAASSERT (R);
+  dQuaternion q;
+  dQFromAxisAndAngle (q,ax,ay,az,angle);
+  dQtoR (q,R);
+}
+
+
+void dRFromEulerAngles (dMatrix3 R, dReal phi, dReal theta, dReal psi)
+{
+  dReal sphi,cphi,stheta,ctheta,spsi,cpsi;
+  dAASSERT (R);
+  sphi = dSin(phi);
+  cphi = dCos(phi);
+  stheta = dSin(theta);
+  ctheta = dCos(theta);
+  spsi = dSin(psi);
+  cpsi = dCos(psi);
+  _R(0,0) = cpsi*ctheta;
+  _R(0,1) = spsi*ctheta;
+  _R(0,2) =-stheta;
+  _R(0,3) = REAL(0.0);
+  _R(1,0) = cpsi*stheta*sphi - spsi*cphi;
+  _R(1,1) = spsi*stheta*sphi + cpsi*cphi;
+  _R(1,2) = ctheta*sphi;
+  _R(1,3) = REAL(0.0);
+  _R(2,0) = cpsi*stheta*cphi + spsi*sphi;
+  _R(2,1) = spsi*stheta*cphi - cpsi*sphi;
+  _R(2,2) = ctheta*cphi;
+  _R(2,3) = REAL(0.0);
+}
+
+
+void dRFrom2Axes (dMatrix3 R, dReal ax, dReal ay, dReal az,
+		  dReal bx, dReal by, dReal bz)
+{
+  dReal l,k;
+  dAASSERT (R);
+  l = dSqrt (ax*ax + ay*ay + az*az);
+  if (l <= REAL(0.0)) {
+    dDEBUGMSG ("zero length vector");
+    return;
+  }
+  l = dRecip(l);
+  ax *= l;
+  ay *= l;
+  az *= l;
+  k = ax*bx + ay*by + az*bz;
+  bx -= k*ax;
+  by -= k*ay;
+  bz -= k*az;
+  l = dSqrt (bx*bx + by*by + bz*bz);
+  if (l <= REAL(0.0)) {
+    dDEBUGMSG ("zero length vector");
+    return;
+  }
+  l = dRecip(l);
+  bx *= l;
+  by *= l;
+  bz *= l;
+  _R(0,0) = ax;
+  _R(1,0) = ay;
+  _R(2,0) = az;
+  _R(0,1) = bx;
+  _R(1,1) = by;
+  _R(2,1) = bz;
+  _R(0,2) = - by*az + ay*bz;
+  _R(1,2) = - bz*ax + az*bx;
+  _R(2,2) = - bx*ay + ax*by;
+  _R(0,3) = REAL(0.0);
+  _R(1,3) = REAL(0.0);
+  _R(2,3) = REAL(0.0);
+}
+
+
+void dRFromZAxis (dMatrix3 R, dReal ax, dReal ay, dReal az)
+{
+  dVector3 n,p,q;
+  n[0] = ax;
+  n[1] = ay;
+  n[2] = az;
+  dNormalize3 (n);
+  dPlaneSpace (n,p,q);
+  _R(0,0) = p[0];
+  _R(1,0) = p[1];
+  _R(2,0) = p[2];
+  _R(0,1) = q[0];
+  _R(1,1) = q[1];
+  _R(2,1) = q[2];
+  _R(0,2) = n[0];
+  _R(1,2) = n[1];
+  _R(2,2) = n[2];
+  _R(0,3) = REAL(0.0);
+  _R(1,3) = REAL(0.0);
+  _R(2,3) = REAL(0.0);
+}
+
+
+void dQSetIdentity (dQuaternion q)
+{
+  dAASSERT (q);
+  q[0] = 1;
+  q[1] = 0;
+  q[2] = 0;
+  q[3] = 0;
+}
+
+
+void dQFromAxisAndAngle (dQuaternion q, dReal ax, dReal ay, dReal az,
+			 dReal angle)
+{
+  dAASSERT (q);
+  dReal l = ax*ax + ay*ay + az*az;
+  if (l > REAL(0.0)) {
+    angle *= REAL(0.5);
+    q[0] = dCos (angle);
+    l = dSin(angle) * dRecipSqrt(l);
+    q[1] = ax*l;
+    q[2] = ay*l;
+    q[3] = az*l;
+  }
+  else {
+    q[0] = 1;
+    q[1] = 0;
+    q[2] = 0;
+    q[3] = 0;
+  }
+}
+
+
+void dQMultiply0 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
+{
+  dAASSERT (qa && qb && qc);
+  qa[0] = qb[0]*qc[0] - qb[1]*qc[1] - qb[2]*qc[2] - qb[3]*qc[3];
+  qa[1] = qb[0]*qc[1] + qb[1]*qc[0] + qb[2]*qc[3] - qb[3]*qc[2];
+  qa[2] = qb[0]*qc[2] + qb[2]*qc[0] + qb[3]*qc[1] - qb[1]*qc[3];
+  qa[3] = qb[0]*qc[3] + qb[3]*qc[0] + qb[1]*qc[2] - qb[2]*qc[1];
+}
+
+
+void dQMultiply1 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
+{
+  dAASSERT (qa && qb && qc);
+  qa[0] = qb[0]*qc[0] + qb[1]*qc[1] + qb[2]*qc[2] + qb[3]*qc[3];
+  qa[1] = qb[0]*qc[1] - qb[1]*qc[0] - qb[2]*qc[3] + qb[3]*qc[2];
+  qa[2] = qb[0]*qc[2] - qb[2]*qc[0] - qb[3]*qc[1] + qb[1]*qc[3];
+  qa[3] = qb[0]*qc[3] - qb[3]*qc[0] - qb[1]*qc[2] + qb[2]*qc[1];
+}
+
+
+void dQMultiply2 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
+{
+  dAASSERT (qa && qb && qc);
+  qa[0] =  qb[0]*qc[0] + qb[1]*qc[1] + qb[2]*qc[2] + qb[3]*qc[3];
+  qa[1] = -qb[0]*qc[1] + qb[1]*qc[0] - qb[2]*qc[3] + qb[3]*qc[2];
+  qa[2] = -qb[0]*qc[2] + qb[2]*qc[0] - qb[3]*qc[1] + qb[1]*qc[3];
+  qa[3] = -qb[0]*qc[3] + qb[3]*qc[0] - qb[1]*qc[2] + qb[2]*qc[1];
+}
+
+
+void dQMultiply3 (dQuaternion qa, const dQuaternion qb, const dQuaternion qc)
+{
+  dAASSERT (qa && qb && qc);
+  qa[0] =  qb[0]*qc[0] - qb[1]*qc[1] - qb[2]*qc[2] - qb[3]*qc[3];
+  qa[1] = -qb[0]*qc[1] - qb[1]*qc[0] + qb[2]*qc[3] - qb[3]*qc[2];
+  qa[2] = -qb[0]*qc[2] - qb[2]*qc[0] + qb[3]*qc[1] - qb[1]*qc[3];
+  qa[3] = -qb[0]*qc[3] - qb[3]*qc[0] + qb[1]*qc[2] - qb[2]*qc[1];
+}
+
+
+// dRfromQ(), dQfromR() and dDQfromW() are derived from equations in "An Introduction
+// to Physically Based Modeling: Rigid Body Simulation - 1: Unconstrained
+// Rigid Body Dynamics" by David Baraff, Robotics Institute, Carnegie Mellon
+// University, 1997.
+
+void dRfromQ (dMatrix3 R, const dQuaternion q)
+{
+  dAASSERT (q && R);
+  // q = (s,vx,vy,vz)
+  dReal qq1 = 2*q[1]*q[1];
+  dReal qq2 = 2*q[2]*q[2];
+  dReal qq3 = 2*q[3]*q[3];
+  _R(0,0) = 1 - qq2 - qq3;
+  _R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]);
+  _R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]);
+  _R(0,3) = REAL(0.0);
+  _R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]);
+  _R(1,1) = 1 - qq1 - qq3;
+  _R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]);
+  _R(1,3) = REAL(0.0);
+  _R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]);
+  _R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]);
+  _R(2,2) = 1 - qq1 - qq2;
+  _R(2,3) = REAL(0.0);
+}
+
+
+void dQfromR (dQuaternion q, const dMatrix3 R)
+{
+  dAASSERT (q && R);
+  dReal tr,s;
+  tr = _R(0,0) + _R(1,1) + _R(2,2);
+  if (tr >= 0) {
+    s = dSqrt (tr + 1);
+    q[0] = REAL(0.5) * s;
+    s = REAL(0.5) * dRecip(s);
+    q[1] = (_R(2,1) - _R(1,2)) * s;
+    q[2] = (_R(0,2) - _R(2,0)) * s;
+    q[3] = (_R(1,0) - _R(0,1)) * s;
+  }
+  else {
+    // find the largest diagonal element and jump to the appropriate case
+    if (_R(1,1) > _R(0,0)) {
+      if (_R(2,2) > _R(1,1)) goto case_2;
+      goto case_1;
+    }
+    if (_R(2,2) > _R(0,0)) goto case_2;
+    goto case_0;
+
+    case_0:
+    s = dSqrt((_R(0,0) - (_R(1,1) + _R(2,2))) + 1);
+    q[1] = REAL(0.5) * s;
+    s = REAL(0.5) * dRecip(s);
+    q[2] = (_R(0,1) + _R(1,0)) * s;
+    q[3] = (_R(2,0) + _R(0,2)) * s;
+    q[0] = (_R(2,1) - _R(1,2)) * s;
+    return;
+
+    case_1:
+    s = dSqrt((_R(1,1) - (_R(2,2) + _R(0,0))) + 1);
+    q[2] = REAL(0.5) * s;
+    s = REAL(0.5) * dRecip(s);
+    q[3] = (_R(1,2) + _R(2,1)) * s;
+    q[1] = (_R(0,1) + _R(1,0)) * s;
+    q[0] = (_R(0,2) - _R(2,0)) * s;
+    return;
+
+    case_2:
+    s = dSqrt((_R(2,2) - (_R(0,0) + _R(1,1))) + 1);
+    q[3] = REAL(0.5) * s;
+    s = REAL(0.5) * dRecip(s);
+    q[1] = (_R(2,0) + _R(0,2)) * s;
+    q[2] = (_R(1,2) + _R(2,1)) * s;
+    q[0] = (_R(1,0) - _R(0,1)) * s;
+    return;
+  }
+}
+
+
+void dDQfromW (dReal dq[4], const dVector3 w, const dQuaternion q)
+{
+  dAASSERT (w && q && dq);
+  dq[0] = REAL(0.5)*(- w[0]*q[1] - w[1]*q[2] - w[2]*q[3]);
+  dq[1] = REAL(0.5)*(  w[0]*q[0] + w[1]*q[3] - w[2]*q[2]);
+  dq[2] = REAL(0.5)*(- w[0]*q[3] + w[1]*q[0] + w[2]*q[1]);
+  dq[3] = REAL(0.5)*(  w[0]*q[2] - w[1]*q[1] + w[2]*q[0]);
+}
Index: /code/branches/ode/ode-0.9/ode/src/scrapbook.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/scrapbook.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/scrapbook.cpp	(revision 216)
@@ -0,0 +1,485 @@
+
+/*
+
+this is code that was once useful but has now been obseleted.
+
+this file should not be compiled as part of ODE!
+
+*/
+
+//***************************************************************************
+// intersect a line segment with a plane
+
+extern "C" int dClipLineToBox (const dVector3 p1, const dVector3 p2,
+			       const dVector3 p, const dMatrix3 R,
+			       const dVector3 side)
+{
+  // compute the start and end of the line (p1 and p2) relative to the box.
+  // we will do all subsequent computations in this box-relative coordinate
+  // system. we have to do a translation and rotation for each point.
+  dVector3 tmp,s,e;
+  tmp[0] = p1[0] - p[0];
+  tmp[1] = p1[1] - p[1];
+  tmp[2] = p1[2] - p[2];
+  dMULTIPLY1_331 (s,R,tmp);
+  tmp[0] = p2[0] - p[0];
+  tmp[1] = p2[1] - p[1];
+  tmp[2] = p2[2] - p[2];
+  dMULTIPLY1_331 (e,R,tmp);
+
+  // compute the vector 'v' from the start point to the end point
+  dVector3 v;
+  v[0] = e[0] - s[0];
+  v[1] = e[1] - s[1];
+  v[2] = e[2] - s[2];
+
+  // a point on the line is defined by the parameter 't'. t=0 corresponds
+  // to the start of the line, t=1 corresponds to the end of the line.
+  // we will clip the line to the box by finding the range of t where a
+  // point on the line is inside the box. the currently known bounds for
+  // t and tlo..thi.
+  dReal tlo=0,thi=1;
+
+  // clip in the X/Y/Z direction
+  for (int i=0; i<3; i++) {
+    // first adjust s,e for the current t range. this is redundant for the
+    // first iteration, but never mind.
+    e[i] = s[i] + thi*v[i];
+    s[i] = s[i] + tlo*v[i];
+    // compute where t intersects the positive and negative sides.
+    dReal tp = ( side[i] - s[i])/v[i];	// @@@ handle case where denom=0
+    dReal tm = (-side[i] - s[i])/v[i];
+    // handle 9 intersection cases
+    if (s[i] <= -side[i]) {
+      tlo = tm;
+      if (e[i] <= -side[i]) return 0;
+      else if (e[i] >= side[i]) thi = tp;
+    }
+    else if (s[i] <= side[i]) {
+      if (e[i] <= -side[i]) thi = tm;
+      else if (e[i] >= side[i]) thi = tp;
+    }
+    else {
+      tlo = tp;
+      if (e[i] <= -side[i]) thi = tm;
+      else if (e[i] >= side[i]) return 0;
+    }
+  }
+
+  //... @@@ AT HERE @@@
+
+  return 1;
+}
+
+
+//***************************************************************************
+// a nice try at C-B collision. unfortunately it doesn't work. the logic
+// for testing for line-box intersection is correct, but unfortunately the
+// closest-point distance estimates are often too large. as a result contact
+// points are placed incorrectly.
+
+
+int dCollideCB (const dxGeom *o1, const dxGeom *o2, int flags,
+		dContactGeom *contact, int skip)
+{
+  int i;
+
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->_class->num == dCCylinderClass);
+  dIASSERT (o2->_class->num == dBoxClass);
+  contact->g1 = const_cast<dxGeom*> (o1);
+  contact->g2 = const_cast<dxGeom*> (o2);
+  dxCCylinder *cyl = (dxCCylinder*) CLASSDATA(o1);
+  dxBox *box = (dxBox*) CLASSDATA(o2);
+
+  // get p1,p2 = cylinder axis endpoints, get radius
+  dVector3 p1,p2;
+  dReal clen = cyl->lz * REAL(0.5);
+  p1[0] = o1->pos[0] + clen * o1->R[2];
+  p1[1] = o1->pos[1] + clen * o1->R[6];
+  p1[2] = o1->pos[2] + clen * o1->R[10];
+  p2[0] = o1->pos[0] - clen * o1->R[2];
+  p2[1] = o1->pos[1] - clen * o1->R[6];
+  p2[2] = o1->pos[2] - clen * o1->R[10];
+  dReal radius = cyl->radius;
+
+  // copy out box center, rotation matrix, and side array
+  dReal *c = o2->pos;
+  dReal *R = o2->R;
+  dReal *side = box->side;
+
+  // compute the start and end of the line (p1 and p2) relative to the box.
+  // we will do all subsequent computations in this box-relative coordinate
+  // system. we have to do a translation and rotation for each point.
+  dVector3 tmp3,s,e;
+  tmp3[0] = p1[0] - c[0];
+  tmp3[1] = p1[1] - c[1];
+  tmp3[2] = p1[2] - c[2];
+  dMULTIPLY1_331 (s,R,tmp3);
+  tmp3[0] = p2[0] - c[0];
+  tmp3[1] = p2[1] - c[1];
+  tmp3[2] = p2[2] - c[2];
+  dMULTIPLY1_331 (e,R,tmp3);
+
+  // compute the vector 'v' from the start point to the end point
+  dVector3 v;
+  v[0] = e[0] - s[0];
+  v[1] = e[1] - s[1];
+  v[2] = e[2] - s[2];
+
+  // compute the half-sides of the box
+  dReal S0 = side[0] * REAL(0.5);
+  dReal S1 = side[1] * REAL(0.5);
+  dReal S2 = side[2] * REAL(0.5);
+
+  // compute the size of the bounding box around the line segment
+  dReal B0 = dFabs (v[0]);
+  dReal B1 = dFabs (v[1]);
+  dReal B2 = dFabs (v[2]);
+
+  // for all 6 separation axes, measure the penetration depth. if any depth is
+  // less than 0 then the objects don't penetrate at all so we can just
+  // return 0. find the axis with the smallest depth, and record its normal.
+
+  // note: normalR is set to point to a column of R if that is the smallest
+  // depth normal so far. otherwise normalR is 0 and normalC is set to a
+  // vector relative to the box. invert_normal is 1 if the sign of the normal
+  // should be flipped.
+
+  dReal depth,trial_depth,tmp,length;
+  const dReal *normalR=0;
+  dVector3 normalC;
+  int invert_normal = 0;
+  int code = 0;		// 0=no contact, 1-3=face contact, 4-6=edge contact
+
+  depth = dInfinity;
+
+  // look at face-normal axes
+
+#undef TEST
+#define TEST(center,depth_expr,norm,contact_code) \
+  tmp = (center); \
+  trial_depth = radius + REAL(0.5) * ((depth_expr) - dFabs(tmp)); \
+  if (trial_depth < 0) return 0; \
+  if (trial_depth < depth) { \
+    depth = trial_depth; \
+    normalR = (norm); \
+    invert_normal = (tmp < 0); \
+    code = contact_code; \
+  }
+
+  TEST (s[0]+e[0], side[0] + B0, R+0, 1);
+  TEST (s[1]+e[1], side[1] + B1, R+1, 2);
+  TEST (s[2]+e[2], side[2] + B2, R+2, 3);
+
+  // look at v x box-edge axes
+
+#undef TEST
+#define TEST(box_radius,line_offset,nx,ny,nz,contact_code) \
+  tmp = (line_offset); \
+  trial_depth = (box_radius) - dFabs(tmp); \
+  length = dSqrt ((nx)*(nx) + (ny)*(ny) + (nz)*(nz)); \
+  if (length > 0) { \
+    length = dRecip(length); \
+    trial_depth = trial_depth * length + radius; \
+    if (trial_depth < 0) return 0; \
+    if (trial_depth < depth) { \
+      depth = trial_depth; \
+      normalR = 0; \
+      normalC[0] = (nx)*length; \
+      normalC[1] = (ny)*length; \
+      normalC[2] = (nz)*length; \
+      invert_normal = (tmp < 0); \
+      code = contact_code; \
+    } \
+  }
+
+  TEST (B2*S1+B1*S2,v[1]*s[2]-v[2]*s[1], 0,-v[2],v[1], 4);
+  TEST (B2*S0+B0*S2,v[2]*s[0]-v[0]*s[2], v[2],0,-v[0], 5);
+  TEST (B1*S0+B0*S1,v[0]*s[1]-v[1]*s[0], -v[1],v[0],0, 6);
+
+#undef TEST
+
+  // if we get to this point, the box and ccylinder interpenetrate.
+  // compute the normal in global coordinates.
+  dReal *normal = contact[0].normal;
+  if (normalR) {
+    normal[0] = normalR[0];
+    normal[1] = normalR[4];
+    normal[2] = normalR[8];
+  }
+  else {
+    dMULTIPLY0_331 (normal,R,normalC);
+  }
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+
+  // set the depth
+  contact[0].depth = depth;
+
+  if (code == 0) {
+    return 0;		// should never get here
+  }
+  else if (code >= 4) {
+    // handle edge contacts
+    // find an endpoint q1 on the intersecting edge of the box
+    dVector3 q1;
+    dReal sign[3];
+    for (i=0; i<3; i++) q1[i] = c[i];
+    sign[0] = (dDOT14(normal,R+0) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) q1[i] += sign[0] * S0 * R[i*4];
+    sign[1] = (dDOT14(normal,R+1) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) q1[i] += sign[1] * S1 * R[i*4+1];
+    sign[2] = (dDOT14(normal,R+2) > 0) ? REAL(1.0) : REAL(-1.0);
+    for (i=0; i<3; i++) q1[i] += sign[2] * S2 * R[i*4+2];
+
+    // find the other endpoint q2 of the intersecting edge
+    dVector3 q2;
+    for (i=0; i<3; i++)
+      q2[i] = q1[i] - R[code-4 + i*4] * (sign[code-4] * side[code-4]);
+
+    // determine the closest point between the box edge and the line segment
+    dVector3 cp1,cp2;
+    dClosestLineSegmentPoints (q1,q2, p1,p2, cp1,cp2);
+    for (i=0; i<3; i++) contact[0].pos[i] = cp1[i] - REAL(0.5)*normal[i]*depth;
+    return 1;
+  }
+  else {
+    // handle face contacts.
+    // @@@ temporary: make deepest vertex on the line the contact point.
+    // @@@ this kind of works, but we sometimes need two contact points for
+    // @@@ stability.
+
+    // compute 'v' in global coordinates
+    dVector3 gv;
+    for (i=0; i<3; i++) gv[i] = p2[i] - p1[i];
+
+    if (dDOT (normal,gv) > 0) {
+      for (i=0; i<3; i++)
+	contact[0].pos[i] = p1[i] + (depth*REAL(0.5)-radius)*normal[i];
+    }
+    else {
+      for (i=0; i<3; i++)
+	contact[0].pos[i] = p2[i] + (depth*REAL(0.5)-radius)*normal[i];
+    }
+    return 1;
+  }
+}
+
+//***************************************************************************
+// this function works, it's just not being used for anything at the moment:
+
+// given a box (R,side), `R' is the rotation matrix for the box, and `side'
+// is a vector of x/y/z side lengths, return the size of the interval of the
+// box projected along the given axis. if the axis has unit length then the
+// return value will be the actual diameter, otherwise the result will be
+// scaled by the axis length.
+
+static inline dReal boxDiameter (const dMatrix3 R, const dVector3 side,
+				 const dVector3 axis)
+{
+  dVector3 q;
+  dMULTIPLY1_331 (q,R,axis);	// transform axis to body-relative
+  return dFabs(q[0])*side[0] + dFabs(q[1])*side[1] + dFabs(q[2])*side[2];
+}
+
+//***************************************************************************
+// the old capped cylinder to capped cylinder collision code. this fails to
+// detect cap-to-cap contact points when the cylinder axis are aligned, but
+// other that that it is pretty robust.
+
+// this returns at most one contact point when the two cylinder's axes are not
+// aligned, and at most two (for stability) when they are aligned.
+// the algorithm minimizes the distance between two "sample spheres" that are
+// positioned along the cylinder axes according to:
+//    sphere1 = pos1 + alpha1 * axis1
+//    sphere2 = pos2 + alpha2 * axis2
+// alpha1 and alpha2 are limited to +/- half the length of the cylinders.
+// the algorithm works by finding a solution that has both alphas free, or
+// a solution that has one or both alphas fixed to the ends of the cylinder.
+
+int dCollideCCylinderCCylinder (dxGeom *o1, dxGeom *o2,
+				int flags, dContactGeom *contact, int skip)
+{
+  int i;
+  const dReal tolerance = REAL(1e-5);
+
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dCCylinderClass);
+  dIASSERT (o2->type == dCCylinderClass);
+  dxCCylinder *cyl1 = (dxCCylinder*) o1;
+  dxCCylinder *cyl2 = (dxCCylinder*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+
+  // copy out some variables, for convenience
+  dReal lz1 = cyl1->lz * REAL(0.5);
+  dReal lz2 = cyl2->lz * REAL(0.5);
+  dReal *pos1 = o1->pos;
+  dReal *pos2 = o2->pos;
+  dReal axis1[3],axis2[3];
+  axis1[0] = o1->R[2];
+  axis1[1] = o1->R[6];
+  axis1[2] = o1->R[10];
+  axis2[0] = o2->R[2];
+  axis2[1] = o2->R[6];
+  axis2[2] = o2->R[10];
+
+  dReal alpha1,alpha2,sphere1[3],sphere2[3];
+  int fix1 = 0;		// 0 if alpha1 is free, +/-1 to fix at +/- lz1
+  int fix2 = 0;		// 0 if alpha2 is free, +/-1 to fix at +/- lz2
+
+  for (int count=0; count<9; count++) {
+    // find a trial solution by fixing or not fixing the alphas
+    if (fix1) {
+      if (fix2) {
+	// alpha1 and alpha2 are fixed, so the solution is easy
+	if (fix1 > 0) alpha1 = lz1; else alpha1 = -lz1;
+	if (fix2 > 0) alpha2 = lz2; else alpha2 = -lz2;
+	for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
+	for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
+      }
+      else {
+	// fix alpha1 but let alpha2 be free
+	if (fix1 > 0) alpha1 = lz1; else alpha1 = -lz1;
+	for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
+	alpha2 = (axis2[0]*(sphere1[0]-pos2[0]) +
+		  axis2[1]*(sphere1[1]-pos2[1]) +
+		  axis2[2]*(sphere1[2]-pos2[2]));
+	for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
+      }
+    }
+    else {
+      if (fix2) {
+	// fix alpha2 but let alpha1 be free
+	if (fix2 > 0) alpha2 = lz2; else alpha2 = -lz2;
+	for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
+	alpha1 = (axis1[0]*(sphere2[0]-pos1[0]) +
+		  axis1[1]*(sphere2[1]-pos1[1]) +
+		  axis1[2]*(sphere2[2]-pos1[2]));
+	for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
+      }
+      else {
+	// let alpha1 and alpha2 be free
+	// compute determinant of d(d^2)\d(alpha) jacobian
+	dReal a1a2 = dDOT (axis1,axis2);
+	dReal det = REAL(1.0)-a1a2*a1a2;
+	if (det < tolerance) {
+	  // the cylinder axes (almost) parallel, so we will generate up to two
+	  // contacts. the solution matrix is rank deficient so alpha1 and
+	  // alpha2 are related by:
+	  //       alpha2 =   alpha1 + (pos1-pos2)'*axis1   (if axis1==axis2)
+	  //    or alpha2 = -(alpha1 + (pos1-pos2)'*axis1)  (if axis1==-axis2)
+	  // first compute where the two cylinders overlap in alpha1 space:
+	  if (a1a2 < 0) {
+	    axis2[0] = -axis2[0];
+	    axis2[1] = -axis2[1];
+	    axis2[2] = -axis2[2];
+	  }
+	  dReal q[3];
+	  for (i=0; i<3; i++) q[i] = pos1[i]-pos2[i];
+	  dReal k = dDOT (axis1,q);
+	  dReal a1lo = -lz1;
+	  dReal a1hi = lz1;
+	  dReal a2lo = -lz2 - k;
+	  dReal a2hi = lz2 - k;
+	  dReal lo = (a1lo > a2lo) ? a1lo : a2lo;
+	  dReal hi = (a1hi < a2hi) ? a1hi : a2hi;
+	  if (lo <= hi) {
+	    int num_contacts = flags & NUMC_MASK;
+	    if (num_contacts >= 2 && lo < hi) {
+	      // generate up to two contacts. if one of those contacts is
+	      // not made, fall back on the one-contact strategy.
+	      for (i=0; i<3; i++) sphere1[i] = pos1[i] + lo*axis1[i];
+	      for (i=0; i<3; i++) sphere2[i] = pos2[i] + (lo+k)*axis2[i];
+	      int n1 = dCollideSpheres (sphere1,cyl1->radius,
+					sphere2,cyl2->radius,contact);
+	      if (n1) {
+		for (i=0; i<3; i++) sphere1[i] = pos1[i] + hi*axis1[i];
+		for (i=0; i<3; i++) sphere2[i] = pos2[i] + (hi+k)*axis2[i];
+		dContactGeom *c2 = CONTACT(contact,skip);
+		int n2 = dCollideSpheres (sphere1,cyl1->radius,
+					  sphere2,cyl2->radius, c2);
+		if (n2) {
+		  c2->g1 = o1;
+		  c2->g2 = o2;
+		  return 2;
+		}
+	      }
+	    }
+
+	    // just one contact to generate, so put it in the middle of
+	    // the range
+	    alpha1 = (lo + hi) * REAL(0.5);
+	    alpha2 = alpha1 + k;
+	    for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
+	    for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
+	    return dCollideSpheres (sphere1,cyl1->radius,
+				    sphere2,cyl2->radius,contact);
+	  }
+	  else return 0;
+	}
+	det = REAL(1.0)/det;
+	dReal delta[3];
+	for (i=0; i<3; i++) delta[i] = pos1[i] - pos2[i];
+	dReal q1 = dDOT (delta,axis1);
+	dReal q2 = dDOT (delta,axis2);
+	alpha1 = det*(a1a2*q2-q1);
+	alpha2 = det*(q2-a1a2*q1);
+	for (i=0; i<3; i++) sphere1[i] = pos1[i] + alpha1*axis1[i];
+	for (i=0; i<3; i++) sphere2[i] = pos2[i] + alpha2*axis2[i];
+      }
+    }
+
+    // if the alphas are outside their allowed ranges then fix them and
+    // try again
+    if (fix1==0) {
+      if (alpha1 < -lz1) {
+	fix1 = -1;
+	continue;
+      }
+      if (alpha1 > lz1) {
+	fix1 = 1;
+	continue;
+      }
+    }
+    if (fix2==0) {
+      if (alpha2 < -lz2) {
+	fix2 = -1;
+	continue;
+      }
+      if (alpha2 > lz2) {
+	fix2 = 1;
+	continue;
+      }
+    }
+
+    // unfix the alpha variables if the local distance gradient indicates
+    // that we are not yet at the minimum
+    dReal tmp[3];
+    for (i=0; i<3; i++) tmp[i] = sphere1[i] - sphere2[i];
+    if (fix1) {
+      dReal gradient = dDOT (tmp,axis1);
+      if ((fix1 > 0 && gradient > 0) || (fix1 < 0 && gradient < 0)) {
+	fix1 = 0;
+	continue;
+      }
+    }
+    if (fix2) {
+      dReal gradient = -dDOT (tmp,axis2);
+      if ((fix2 > 0 && gradient > 0) || (fix2 < 0 && gradient < 0)) {
+	fix2 = 0;
+	continue;
+      }
+    }
+    return dCollideSpheres (sphere1,cyl1->radius,sphere2,cyl2->radius,contact);
+  }
+  // if we go through the loop too much, then give up. we should NEVER get to
+  // this point (i hope).
+  dMessage (0,"dCollideCC(): too many iterations");
+  return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/src/sphere.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/sphere.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/sphere.cpp	(revision 216)
@@ -0,0 +1,241 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+standard ODE geometry primitives: public API and pairwise collision functions.
+
+the rule is that only the low level primitive collision functions should set
+dContactGeom::g1 and dContactGeom::g2.
+
+*/
+
+#include <ode/common.h>
+#include <ode/collision.h>
+#include <ode/matrix.h>
+#include <ode/rotation.h>
+#include <ode/odemath.h>
+#include "collision_kernel.h"
+#include "collision_std.h"
+#include "collision_util.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4291)  // for VC++, no complaints about "no matching operator delete found"
+#endif
+
+
+//****************************************************************************
+// sphere public API
+
+dxSphere::dxSphere (dSpaceID space, dReal _radius) : dxGeom (space,1)
+{
+  dAASSERT (_radius > 0);
+  type = dSphereClass;
+  radius = _radius;
+}
+
+
+void dxSphere::computeAABB()
+{
+  aabb[0] = final_posr->pos[0] - radius;
+  aabb[1] = final_posr->pos[0] + radius;
+  aabb[2] = final_posr->pos[1] - radius;
+  aabb[3] = final_posr->pos[1] + radius;
+  aabb[4] = final_posr->pos[2] - radius;
+  aabb[5] = final_posr->pos[2] + radius;
+}
+
+
+dGeomID dCreateSphere (dSpaceID space, dReal radius)
+{
+  return new dxSphere (space,radius);
+}
+
+
+void dGeomSphereSetRadius (dGeomID g, dReal radius)
+{
+  dUASSERT (g && g->type == dSphereClass,"argument not a sphere");
+  dAASSERT (radius > 0);
+  dxSphere *s = (dxSphere*) g;
+  s->radius = radius;
+  dGeomMoved (g);
+}
+
+
+dReal dGeomSphereGetRadius (dGeomID g)
+{
+  dUASSERT (g && g->type == dSphereClass,"argument not a sphere");
+  dxSphere *s = (dxSphere*) g;
+  return s->radius;
+}
+
+
+dReal dGeomSpherePointDepth (dGeomID g, dReal x, dReal y, dReal z)
+{
+  dUASSERT (g && g->type == dSphereClass,"argument not a sphere");
+  g->recomputePosr();
+  
+  dxSphere *s = (dxSphere*) g;
+  dReal * pos = s->final_posr->pos;
+  return s->radius - dSqrt ((x-pos[0])*(x-pos[0]) +
+			    (y-pos[1])*(y-pos[1]) +
+			    (z-pos[2])*(z-pos[2]));
+}
+
+//****************************************************************************
+// pairwise collision functions for standard geom types
+
+int dCollideSphereSphere (dxGeom *o1, dxGeom *o2, int flags,
+			  dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dSphereClass);
+  dIASSERT (o2->type == dSphereClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+  
+  dxSphere *sphere1 = (dxSphere*) o1;
+  dxSphere *sphere2 = (dxSphere*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+
+  return dCollideSpheres (o1->final_posr->pos,sphere1->radius,
+			  o2->final_posr->pos,sphere2->radius,contact);
+}
+
+
+int dCollideSphereBox (dxGeom *o1, dxGeom *o2, int flags,
+		       dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dSphereClass);
+  dIASSERT (o2->type == dBoxClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+  
+  // this is easy. get the sphere center `p' relative to the box, and then clip
+  // that to the boundary of the box (call that point `q'). if q is on the
+  // boundary of the box and |p-q| is <= sphere radius, they touch.
+  // if q is inside the box, the sphere is inside the box, so set a contact
+  // normal to push the sphere to the closest box face.
+
+  dVector3 l,t,p,q,r;
+  dReal depth;
+  int onborder = 0;
+
+  dxSphere *sphere = (dxSphere*) o1;
+  dxBox *box = (dxBox*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+
+  p[0] = o1->final_posr->pos[0] - o2->final_posr->pos[0];
+  p[1] = o1->final_posr->pos[1] - o2->final_posr->pos[1];
+  p[2] = o1->final_posr->pos[2] - o2->final_posr->pos[2];
+
+  l[0] = box->side[0]*REAL(0.5);
+  t[0] = dDOT14(p,o2->final_posr->R);
+  if (t[0] < -l[0]) { t[0] = -l[0]; onborder = 1; }
+  if (t[0] >  l[0]) { t[0] =  l[0]; onborder = 1; }
+
+  l[1] = box->side[1]*REAL(0.5);
+  t[1] = dDOT14(p,o2->final_posr->R+1);
+  if (t[1] < -l[1]) { t[1] = -l[1]; onborder = 1; }
+  if (t[1] >  l[1]) { t[1] =  l[1]; onborder = 1; }
+
+  t[2] = dDOT14(p,o2->final_posr->R+2);
+  l[2] = box->side[2]*REAL(0.5);
+  if (t[2] < -l[2]) { t[2] = -l[2]; onborder = 1; }
+  if (t[2] >  l[2]) { t[2] =  l[2]; onborder = 1; }
+
+  if (!onborder) {
+    // sphere center inside box. find closest face to `t'
+    dReal min_distance = l[0] - dFabs(t[0]);
+    int mini = 0;
+    for (int i=1; i<3; i++) {
+      dReal face_distance = l[i] - dFabs(t[i]);
+      if (face_distance < min_distance) {
+	min_distance = face_distance;
+	mini = i;
+      }
+    }
+    // contact position = sphere center
+    contact->pos[0] = o1->final_posr->pos[0];
+    contact->pos[1] = o1->final_posr->pos[1];
+    contact->pos[2] = o1->final_posr->pos[2];
+    // contact normal points to closest face
+    dVector3 tmp;
+    tmp[0] = 0;
+    tmp[1] = 0;
+    tmp[2] = 0;
+    tmp[mini] = (t[mini] > 0) ? REAL(1.0) : REAL(-1.0);
+    dMULTIPLY0_331 (contact->normal,o2->final_posr->R,tmp);
+    // contact depth = distance to wall along normal plus radius
+    contact->depth = min_distance + sphere->radius;
+    return 1;
+  }
+
+  t[3] = 0;			//@@@ hmmm
+  dMULTIPLY0_331 (q,o2->final_posr->R,t);
+  r[0] = p[0] - q[0];
+  r[1] = p[1] - q[1];
+  r[2] = p[2] - q[2];
+  depth = sphere->radius - dSqrt(dDOT(r,r));
+  if (depth < 0) return 0;
+  contact->pos[0] = q[0] + o2->final_posr->pos[0];
+  contact->pos[1] = q[1] + o2->final_posr->pos[1];
+  contact->pos[2] = q[2] + o2->final_posr->pos[2];
+  contact->normal[0] = r[0];
+  contact->normal[1] = r[1];
+  contact->normal[2] = r[2];
+  dNormalize3 (contact->normal);
+  contact->depth = depth;
+  return 1;
+}
+
+
+int dCollideSpherePlane (dxGeom *o1, dxGeom *o2, int flags,
+			 dContactGeom *contact, int skip)
+{
+  dIASSERT (skip >= (int)sizeof(dContactGeom));
+  dIASSERT (o1->type == dSphereClass);
+  dIASSERT (o2->type == dPlaneClass);
+  dIASSERT ((flags & NUMC_MASK) >= 1);
+
+  dxSphere *sphere = (dxSphere*) o1;
+  dxPlane *plane = (dxPlane*) o2;
+
+  contact->g1 = o1;
+  contact->g2 = o2;
+  dReal k = dDOT (o1->final_posr->pos,plane->p);
+  dReal depth = plane->p[3] - k + sphere->radius;
+  if (depth >= 0) {
+    contact->normal[0] = plane->p[0];
+    contact->normal[1] = plane->p[1];
+    contact->normal[2] = plane->p[2];
+    contact->pos[0] = o1->final_posr->pos[0] - plane->p[0] * sphere->radius;
+    contact->pos[1] = o1->final_posr->pos[1] - plane->p[1] * sphere->radius;
+    contact->pos[2] = o1->final_posr->pos[2] - plane->p[2] * sphere->radius;
+    contact->depth = depth;
+    return 1;
+  }
+  else return 0;
+}
Index: /code/branches/ode/ode-0.9/ode/src/stack.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/stack.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/stack.cpp	(revision 216)
@@ -0,0 +1,114 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+@@@ this file should not be compiled any more @@@
+
+#include <string.h>
+#include <errno.h>
+#include "stack.h"
+#include "ode/error.h"
+#include "ode/config.h"
+
+//****************************************************************************
+// unix version that uses mmap(). some systems have anonymous mmaps and some
+// need to mmap /dev/zero.
+
+#ifndef WIN32
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+void dStack::init (int max_size)
+{
+  if (sizeof(long int) != sizeof(char*)) dDebug (0,"internal");
+  if (max_size <= 0) dDebug (0,"Stack::init() given size <= 0");
+
+#ifndef MMAP_ANONYMOUS
+  static int dev_zero_fd = -1;	// cached file descriptor for /dev/zero
+  if (dev_zero_fd < 0) dev_zero_fd = open ("/dev/zero", O_RDWR);
+  if (dev_zero_fd < 0) dError (0,"can't open /dev/zero (%s)",strerror(errno));
+  base = (char*) mmap (0,max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+		       dev_zero_fd,0);
+#else
+  base = (char*) mmap (0,max_size, PROT_READ | PROT_WRITE,
+		       MAP_PRIVATE | MAP_ANON,0,0);
+#endif
+
+  if (int(base) == -1) dError (0,"Stack::init(), mmap() failed, "
+    "max_size=%d (%s)",max_size,strerror(errno));
+  size = max_size;
+  pointer = base;
+  frame = 0;
+}
+
+
+void dStack::destroy()
+{
+  munmap (base,size);
+  base = 0;
+  size = 0;
+  pointer = 0;
+  frame = 0;
+}
+
+#endif
+
+//****************************************************************************
+
+#ifdef WIN32
+
+#include "windows.h"
+
+
+void dStack::init (int max_size)
+{
+  if (sizeof(LPVOID) != sizeof(char*)) dDebug (0,"internal");
+  if (max_size <= 0) dDebug (0,"Stack::init() given size <= 0");
+  base = (char*) VirtualAlloc (NULL,max_size,MEM_RESERVE,PAGE_READWRITE);
+  if (base == 0) dError (0,"Stack::init(), VirtualAlloc() failed, "
+    "max_size=%d",max_size);
+  size = max_size;
+  pointer = base;
+  frame = 0;
+  committed = 0;
+
+  // get page size
+  SYSTEM_INFO info;
+  GetSystemInfo (&info);
+  pagesize = info.dwPageSize;
+}
+
+
+void dStack::destroy()
+{
+  VirtualFree (base,0,MEM_RELEASE);
+  base = 0;
+  size = 0;
+  pointer = 0;
+  frame = 0;
+}
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/stack.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/stack.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/stack.h	(revision 216)
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* this comes from the `reuse' library. copy any changes back to the source.
+
+these stack allocation functions are a replacement for alloca(), except that
+they allocate memory from a separate pool.
+
+advantages over alloca():
+  - consecutive allocations are guaranteed to be contiguous with increasing
+    address.
+  - functions can allocate stack memory that is returned to the caller,
+    in other words pushing and popping stack frames is optional.
+
+disadvantages compared to alloca():
+  - less portable
+  - slightly slower, although still orders of magnitude faster than malloc().
+  - longjmp() and exceptions do not deallocate stack memory (but who cares?).
+
+just like alloca():
+  - using too much stack memory does not fail gracefully, it fails with a
+    segfault.
+
+*/
+
+
+#ifndef _ODE_STACK_H_
+#define _ODE_STACK_H_
+
+
+#ifdef WIN32
+#include "windows.h"
+#endif
+
+
+struct dStack {
+  char *base;		// bottom of the stack
+  int size;		// maximum size of the stack
+  char *pointer;	// current top of the stack
+  char *frame;		// linked list of stack frame ptrs
+# ifdef WIN32		// stuff for windows:
+  int pagesize;		//   - page size - this is ASSUMED to be a power of 2
+  int committed;	//   - bytes committed in allocated region
+#endif
+
+  // initialize the stack. `max_size' is the maximum size that the stack can
+  // reach. on unix and windows a `virtual' memory block of this size is
+  // mapped into the address space but does not actually consume physical
+  // memory until it is referenced - so it is safe to set this to a high value.
+
+  void init (int max_size);
+
+
+  // destroy the stack. this unmaps any virtual memory that was allocated.
+
+  void destroy();
+
+
+  // allocate `size' bytes from the stack and return a pointer to the allocated
+  // memory. `size' must be >= 0. the returned pointer will be aligned to the
+  // size of a long int.
+
+  char * alloc (int size)
+  {
+    char *ret = pointer;
+    pointer += ((size-1) | (sizeof(long int)-1) )+1;
+#   ifdef WIN32
+    // for windows we need to commit pages as they are required
+    if ((pointer-base) > committed) {
+      committed = ((pointer-base-1) | (pagesize-1))+1;	// round up to pgsize
+      VirtualAlloc (base,committed,MEM_COMMIT,PAGE_READWRITE);
+    }
+#   endif
+    return ret;
+  }
+
+
+  // return the address that will be returned by the next call to alloc()
+
+  char *nextAlloc()
+  {
+    return pointer;
+  }
+
+
+  // push and pop the current size of the stack. pushFrame() saves the current
+  // frame pointer on the stack, and popFrame() retrieves it. a typical
+  // stack-using function will bracket alloc() calls with pushFrame() and
+  // popFrame(). both functions return the current stack pointer - this should
+  // be the same value for the two bracketing calls. calling popFrame() too
+  // many times will result in a segfault.
+
+  char * pushFrame()
+  {
+    char *newframe = pointer;
+    char **addr = (char**) alloc (sizeof(char*));
+    *addr = frame;
+    frame = newframe;
+    return newframe;
+
+    /* OLD CODE
+	*((char**)pointer) = frame;
+	frame = pointer;
+	char *ret = pointer;
+	pointer += sizeof(char*);
+	return ret;
+    */
+  }
+
+  char * popFrame()
+  {
+    pointer = frame;
+    frame = *((char**)pointer);
+    return pointer;
+  }
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/step.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/step.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/step.cpp	(revision 216)
@@ -0,0 +1,1795 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include "objects.h"
+#include "joint.h"
+#include <ode/config.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/timer.h>
+#include <ode/error.h>
+#include <ode/matrix.h>
+#include "lcp.h"
+#include "util.h"
+
+//****************************************************************************
+// misc defines
+
+#define FAST_FACTOR
+//#define TIMING
+
+// memory allocation system
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+unsigned int dMemoryFlag;
+#define REPORT_OUT_OF_MEMORY fprintf(stderr, "Insufficient memory to complete rigid body simulation.  Results will not be accurate.\n")
+
+#define ALLOCA(t,v,s) t* v=(t*)malloc(s)
+#define UNALLOCA(t)  free(t)
+
+#else
+#define ALLOCA(t,v,s) t* v=(t*)dALLOCA16(s)
+#define UNALLOCA(t)  /* nothing */
+#endif
+
+
+//****************************************************************************
+// debugging - comparison of various vectors and matrices produced by the
+// slow and fast versions of the stepper.
+
+//#define COMPARE_METHODS
+
+#ifdef COMPARE_METHODS
+#include "testing.h"
+dMatrixComparison comparator;
+#endif
+
+// undef to use the fast decomposition
+#define DIRECT_CHOLESKY
+#undef REPORT_ERROR
+
+//****************************************************************************
+// special matrix multipliers
+
+// this assumes the 4th and 8th rows of B and C are zero.
+
+static void Multiply2_p8r (dReal *A, dReal *B, dReal *C,
+			   int p, int r, int Askip)
+{
+  int i,j;
+  dReal sum,*bb,*cc;
+  dIASSERT (p>0 && r>0 && A && B && C);
+  bb = B;
+  for (i=p; i; i--) {
+    cc = C;
+    for (j=r; j; j--) {
+      sum = bb[0]*cc[0];
+      sum += bb[1]*cc[1];
+      sum += bb[2]*cc[2];
+      sum += bb[4]*cc[4];
+      sum += bb[5]*cc[5];
+      sum += bb[6]*cc[6];
+      *(A++) = sum; 
+      cc += 8;
+    }
+    A += Askip - r;
+    bb += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B and C are zero.
+
+static void MultiplyAdd2_p8r (dReal *A, dReal *B, dReal *C,
+			      int p, int r, int Askip)
+{
+  int i,j;
+  dReal sum,*bb,*cc;
+  dIASSERT (p>0 && r>0 && A && B && C);
+  bb = B;
+  for (i=p; i; i--) {
+    cc = C;
+    for (j=r; j; j--) {
+      sum = bb[0]*cc[0];
+      sum += bb[1]*cc[1];
+      sum += bb[2]*cc[2];
+      sum += bb[4]*cc[4];
+      sum += bb[5]*cc[5];
+      sum += bb[6]*cc[6];
+      *(A++) += sum; 
+      cc += 8;
+    }
+    A += Askip - r;
+    bb += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void Multiply0_p81 (dReal *A, dReal *B, dReal *C, int p)
+{
+  int i;
+  dIASSERT (p>0 && A && B && C);
+  dReal sum;
+  for (i=p; i; i--) {
+    sum =  B[0]*C[0];
+    sum += B[1]*C[1];
+    sum += B[2]*C[2];
+    sum += B[4]*C[4];
+    sum += B[5]*C[5];
+    sum += B[6]*C[6];
+    *(A++) = sum;
+    B += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void MultiplyAdd0_p81 (dReal *A, dReal *B, dReal *C, int p)
+{
+  int i;
+  dIASSERT (p>0 && A && B && C);
+  dReal sum;
+  for (i=p; i; i--) {
+    sum =  B[0]*C[0];
+    sum += B[1]*C[1];
+    sum += B[2]*C[2];
+    sum += B[4]*C[4];
+    sum += B[5]*C[5];
+    sum += B[6]*C[6];
+    *(A++) += sum;
+    B += 8;
+  }
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void MultiplyAdd1_8q1 (dReal *A, dReal *B, dReal *C, int q)
+{
+  int k;
+  dReal sum;
+  dIASSERT (q>0 && A && B && C);
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[k*8] * C[k];
+  A[0] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[1+k*8] * C[k];
+  A[1] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[2+k*8] * C[k];
+  A[2] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[4+k*8] * C[k];
+  A[4] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[5+k*8] * C[k];
+  A[5] += sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[6+k*8] * C[k];
+  A[6] += sum;
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void Multiply1_8q1 (dReal *A, dReal *B, dReal *C, int q)
+{
+  int k;
+  dReal sum;
+  dIASSERT (q>0 && A && B && C);
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[k*8] * C[k];
+  A[0] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[1+k*8] * C[k];
+  A[1] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[2+k*8] * C[k];
+  A[2] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[4+k*8] * C[k];
+  A[4] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[5+k*8] * C[k];
+  A[5] = sum;
+  sum = 0;
+  for (k=0; k<q; k++) sum += B[6+k*8] * C[k];
+  A[6] = sum;
+}
+
+//****************************************************************************
+// the slow, but sure way
+// note that this does not do any joint feedback!
+
+// given lists of bodies and joints that form an island, perform a first
+// order timestep.
+//
+// `body' is the body array, `nb' is the size of the array.
+// `_joint' is the body array, `nj' is the size of the array.
+
+void dInternalStepIsland_x1 (dxWorld *world, dxBody * const *body, int nb,
+			     dxJoint * const *_joint, int nj, dReal stepsize)
+{
+  int i,j,k;
+  int n6 = 6*nb;
+
+#ifdef TIMING
+  dTimerStart("preprocessing");
+#endif
+
+  // number all bodies in the body list - set their tag values
+  for (i=0; i<nb; i++) body[i]->tag = i;
+
+  // make a local copy of the joint array, because we might want to modify it.
+  // (the "dxJoint *const*" declaration says we're allowed to modify the joints
+  // but not the joint array, because the caller might need it unchanged).
+  ALLOCA(dxJoint*,joint,nj*sizeof(dxJoint*));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (joint == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  memcpy (joint,_joint,nj * sizeof(dxJoint*));
+
+  // for all bodies, compute the inertia tensor and its inverse in the global
+  // frame, and compute the rotational force and add it to the torque
+  // accumulator.
+  // @@@ check computation of rotational force.
+  ALLOCA(dReal,I,3*nb*4*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (I == NULL) {
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  ALLOCA(dReal,invI,3*nb*4*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (invI == NULL) {
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  //dSetZero (I,3*nb*4);
+  //dSetZero (invI,3*nb*4);
+  for (i=0; i<nb; i++) {
+    dReal tmp[12];
+    // compute inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->posr.R);
+    dMULTIPLY0_333 (I+i*12,body[i]->posr.R,tmp);
+    // compute inverse inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->posr.R);
+    dMULTIPLY0_333 (invI+i*12,body[i]->posr.R,tmp);
+    // compute rotational force
+    dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
+    dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
+  }
+
+  // add the gravity force to all bodies
+  for (i=0; i<nb; i++) {
+    if ((body[i]->flags & dxBodyNoGravity)==0) {
+      body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
+      body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
+      body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
+    }
+  }
+
+  // get m = total constraint dimension, nub = number of unbounded variables.
+  // create constraint offset array and number-of-rows array for all joints.
+  // the constraints are re-ordered as follows: the purely unbounded
+  // constraints, the mixed unbounded + LCP constraints, and last the purely
+  // LCP constraints.
+  //
+  // joints with m=0 are inactive and are removed from the joints array
+  // entirely, so that the code that follows does not consider them.
+  int m = 0;
+  ALLOCA(dxJoint::Info1,info,nj*sizeof(dxJoint::Info1));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (info == NULL) {
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  ALLOCA(int,ofs,nj*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (ofs == NULL) {
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  for (i=0, j=0; j<nj; j++) {	// i=dest, j=src
+    joint[j]->vtable->getInfo1 (joint[j],info+i);
+    dIASSERT (info[i].m >= 0 && info[i].m <= 6 &&
+	      info[i].nub >= 0 && info[i].nub <= info[i].m);
+    if (info[i].m > 0) {
+      joint[i] = joint[j];
+      i++;
+    }
+  }
+  nj = i;
+
+  // the purely unbounded constraints
+  for (i=0; i<nj; i++) if (info[i].nub == info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  int nub = m;
+  // the mixed unbounded + LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  // the purely LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub == 0) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+
+  // create (6*nb,6*nb) inverse mass matrix `invM', and fill it with mass
+  // parameters
+#ifdef TIMING
+  dTimerNow ("create mass matrix");
+#endif
+  int nskip = dPAD (n6);
+  ALLOCA(dReal, invM, n6*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (invM == NULL) {
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  dSetZero (invM,n6*nskip);
+  for (i=0; i<nb; i++) {
+    dReal *MM = invM+(i*6)*nskip+(i*6);
+    MM[0] = body[i]->invMass;
+    MM[nskip+1] = body[i]->invMass;
+    MM[2*nskip+2] = body[i]->invMass;
+    MM += 3*nskip+3;
+    for (j=0; j<3; j++) for (k=0; k<3; k++) {
+      MM[j*nskip+k] = invI[i*12+j*4+k];
+    }
+  }
+
+  // assemble some body vectors: fe = external forces, v = velocities
+  ALLOCA(dReal,fe,n6*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (fe == NULL) {
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  ALLOCA(dReal,v,n6*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (v == NULL) {
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  //dSetZero (fe,n6);
+  //dSetZero (v,n6);
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) fe[i*6+j] = body[i]->facc[j];
+    for (j=0; j<3; j++) fe[i*6+3+j] = body[i]->tacc[j];
+    for (j=0; j<3; j++) v[i*6+j] = body[i]->lvel[j];
+    for (j=0; j<3; j++) v[i*6+3+j] = body[i]->avel[j];
+  }
+
+  // this will be set to the velocity update
+  ALLOCA(dReal,vnew,n6*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (vnew == NULL) {
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  dSetZero (vnew,n6);
+
+  // if there are constraints, compute cforce
+  if (m > 0) {
+    // create a constraint equation right hand side vector `c', a constraint
+    // force mixing vector `cfm', and LCP low and high bound vectors, and an
+    // 'findex' vector.
+    ALLOCA(dReal,c,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (c == NULL) {
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,cfm,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (cfm == NULL) {
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,lo,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lo == NULL) {
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,hi,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (hi == NULL) {
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(int,findex,m*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (findex == NULL) {
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSetZero (c,m);
+    dSetValue (cfm,m,world->global_cfm);
+    dSetValue (lo,m,-dInfinity);
+    dSetValue (hi,m, dInfinity);
+    for (i=0; i<m; i++) findex[i] = -1;
+
+    // create (m,6*nb) jacobian mass matrix `J', and fill it with constraint
+    // data. also fill the c vector.
+#   ifdef TIMING
+    dTimerNow ("create J");
+#   endif
+    ALLOCA(dReal,J,m*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (J == NULL) {
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSetZero (J,m*nskip);
+    dxJoint::Info2 Jinfo;
+    Jinfo.rowskip = nskip;
+    Jinfo.fps = dRecip(stepsize);
+    Jinfo.erp = world->global_erp;
+    for (i=0; i<nj; i++) {
+      Jinfo.J1l = J + nskip*ofs[i] + 6*joint[i]->node[0].body->tag;
+      Jinfo.J1a = Jinfo.J1l + 3;
+      if (joint[i]->node[1].body) {
+	Jinfo.J2l = J + nskip*ofs[i] + 6*joint[i]->node[1].body->tag;
+	Jinfo.J2a = Jinfo.J2l + 3;
+      }
+      else {
+	Jinfo.J2l = 0;
+	Jinfo.J2a = 0;
+      }
+      Jinfo.c = c + ofs[i];
+      Jinfo.cfm = cfm + ofs[i];
+      Jinfo.lo = lo + ofs[i];
+      Jinfo.hi = hi + ofs[i];
+      Jinfo.findex = findex + ofs[i];
+      joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
+      // adjust returned findex values for global index numbering
+      for (j=0; j<info[i].m; j++) {
+	if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
+      }
+    }
+
+    // compute A = J*invM*J'
+#   ifdef TIMING
+    dTimerNow ("compute A");
+#   endif
+    ALLOCA(dReal,JinvM,m*nskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (JinvM == NULL) {
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    //dSetZero (JinvM,m*nskip);
+    dMultiply0 (JinvM,J,invM,m,n6,n6);
+    int mskip = dPAD(m);
+    ALLOCA(dReal,A,m*mskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (A == NULL) {
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    //dSetZero (A,m*mskip);
+    dMultiply2 (A,JinvM,J,m,n6,m);
+
+    // add cfm to the diagonal of A
+    for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * Jinfo.fps;
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (A,m,m,1,"A");
+#   endif
+
+    // compute `rhs', the right hand side of the equation J*a=c
+#   ifdef TIMING
+    dTimerNow ("compute rhs");
+#   endif
+    ALLOCA(dReal,tmp1,n6*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp1 == NULL) {
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    //dSetZero (tmp1,n6);
+    dMultiply0 (tmp1,invM,fe,n6,n6,1);
+    for (i=0; i<n6; i++) tmp1[i] += v[i]/stepsize;
+    ALLOCA(dReal,rhs,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (rhs == NULL) {
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    //dSetZero (rhs,m);
+    dMultiply0 (rhs,J,tmp1,m,n6,1);
+    for (i=0; i<m; i++) rhs[i] = c[i]/stepsize - rhs[i];
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (c,m,1,0,"c");
+    comparator.nextMatrix (rhs,m,1,0,"rhs");
+#   endif
+
+
+
+ 
+
+#ifndef DIRECT_CHOLESKY
+    // solve the LCP problem and get lambda.
+    // this will destroy A but that's okay
+#   ifdef TIMING
+    dTimerNow ("solving LCP problem");
+#   endif
+    ALLOCA(dReal,lambda,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lambda == NULL) {
+      UNALLOCA(rhs);
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,residual,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (residual == NULL) {
+      UNALLOCA(lambda);
+      UNALLOCA(rhs);
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex);
+    UNALLOCA(residual);
+    UNALLOCA(lambda);
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY)
+      return;
+#endif
+
+
+#else
+
+    // OLD WAY - direct factor and solve
+
+    // factorize A (L*L'=A)
+#   ifdef TIMING
+    dTimerNow ("factorize A");
+#   endif
+    ALLOCA(dReal,L,m*mskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (L == NULL) {
+      UNALLOCA(rhs);
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    memcpy (L,A,m*mskip*sizeof(dReal));
+    if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
+
+    // compute lambda
+#   ifdef TIMING
+    dTimerNow ("compute lambda");
+#   endif
+    ALLOCA(dReal,lambda,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lambda == NULL) {
+      UNALLOCA(L);
+      UNALLOCA(rhs);
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(vnew);
+      UNALLOCA(v);
+      UNALLOCA(fe);
+      UNALLOCA(invM);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    memcpy (lambda,rhs,m * sizeof(dReal));
+    dSolveCholesky (L,lambda,m);
+#endif
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (lambda,m,1,0,"lambda");
+#   endif
+
+    // compute the velocity update `vnew'
+#   ifdef TIMING
+    dTimerNow ("compute velocity update");
+#   endif
+    dMultiply1 (tmp1,J,lambda,n6,m,1);
+    for (i=0; i<n6; i++) tmp1[i] += fe[i];
+    dMultiply0 (vnew,invM,tmp1,n6,n6,1);
+    for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i];
+
+#ifdef REPORT_ERROR
+    // see if the constraint has worked: compute J*vnew and make sure it equals
+    // `c' (to within a certain tolerance).
+#   ifdef TIMING
+    dTimerNow ("verify constraint equation");
+#   endif
+    dMultiply0 (tmp1,J,vnew,m,n6,1);
+    dReal err = 0;
+    for (i=0; i<m; i++) {
+		err += dFabs(tmp1[i]-c[i]);
+    }
+	printf ("total constraint error=%.6e\n",err);
+#endif
+
+    UNALLOCA(c);
+    UNALLOCA(cfm);
+    UNALLOCA(lo);
+    UNALLOCA(hi);
+    UNALLOCA(findex);
+    UNALLOCA(J);
+    UNALLOCA(JinvM);
+    UNALLOCA(A);
+    UNALLOCA(tmp1);
+    UNALLOCA(rhs);
+    UNALLOCA(lambda); 
+    UNALLOCA(L);
+  }
+  else {
+    // no constraints
+    dMultiply0 (vnew,invM,fe,n6,n6,1);
+    for (i=0; i<n6; i++) vnew[i] = v[i] + stepsize*vnew[i];
+  }
+
+#ifdef COMPARE_METHODS
+  comparator.nextMatrix (vnew,n6,1,0,"vnew");
+#endif
+
+  // apply the velocity update to the bodies
+#ifdef TIMING
+  dTimerNow ("update velocity");
+#endif
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) body[i]->lvel[j] = vnew[i*6+j];
+    for (j=0; j<3; j++) body[i]->avel[j] = vnew[i*6+3+j];
+  }
+
+  // update the position and orientation from the new linear/angular velocity
+  // (over the given timestep)
+#ifdef TIMING
+  dTimerNow ("update position");
+#endif
+  for (i=0; i<nb; i++) dxStepBody (body[i],stepsize);
+
+#ifdef TIMING
+  dTimerNow ("tidy up");
+#endif
+
+  // zero all force accumulators
+  for (i=0; i<nb; i++) {
+    body[i]->facc[0] = 0;
+    body[i]->facc[1] = 0;
+    body[i]->facc[2] = 0;
+    body[i]->facc[3] = 0;
+    body[i]->tacc[0] = 0;
+    body[i]->tacc[1] = 0;
+    body[i]->tacc[2] = 0;
+    body[i]->tacc[3] = 0;
+  }
+
+#ifdef TIMING
+  dTimerEnd();
+  if (m > 0) dTimerReport (stdout,1);
+#endif
+
+  UNALLOCA(joint);
+  UNALLOCA(I);
+  UNALLOCA(invI);
+  UNALLOCA(info);
+  UNALLOCA(ofs);
+  UNALLOCA(invM);
+  UNALLOCA(fe);
+  UNALLOCA(v);
+  UNALLOCA(vnew);
+}
+
+//****************************************************************************
+// an optimized version of dInternalStepIsland1()
+
+void dInternalStepIsland_x2 (dxWorld *world, dxBody * const *body, int nb,
+			     dxJoint * const *_joint, int nj, dReal stepsize)
+{
+  int i,j,k;
+#ifdef TIMING
+  dTimerStart("preprocessing");
+#endif
+
+  dReal stepsize1 = dRecip(stepsize);
+
+  // number all bodies in the body list - set their tag values
+  for (i=0; i<nb; i++) body[i]->tag = i;
+
+  // make a local copy of the joint array, because we might want to modify it.
+  // (the "dxJoint *const*" declaration says we're allowed to modify the joints
+  // but not the joint array, because the caller might need it unchanged).
+  ALLOCA(dxJoint*,joint,nj*sizeof(dxJoint*));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (joint == NULL) {
+    dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+    return;
+  }
+#endif
+  memcpy (joint,_joint,nj * sizeof(dxJoint*));
+
+  // for all bodies, compute the inertia tensor and its inverse in the global
+  // frame, and compute the rotational force and add it to the torque
+  // accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
+  // @@@ check computation of rotational force.
+#ifdef dGYROSCOPIC  
+  ALLOCA(dReal,I,3*nb*4*sizeof(dReal));
+# ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (I == NULL) {
+    UNALLOCA(joint);
+    dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+    return;
+  }
+# endif
+#else
+  dReal *I = NULL;
+#endif // for dGYROSCOPIC
+
+  ALLOCA(dReal,invI,3*nb*4*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (invI == NULL) {
+    UNALLOCA(I);
+    UNALLOCA(joint);
+    dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+    return;
+  }
+#endif
+
+  //dSetZero (I,3*nb*4);
+  //dSetZero (invI,3*nb*4);
+  for (i=0; i<nb; i++) {
+    dReal tmp[12];
+
+    // compute inverse inertia tensor in global frame
+    dMULTIPLY2_333 (tmp,body[i]->invI,body[i]->posr.R);
+    dMULTIPLY0_333 (invI+i*12,body[i]->posr.R,tmp);
+#ifdef dGYROSCOPIC
+    // compute inertia tensor in global frame
+		dMULTIPLY2_333 (tmp,body[i]->mass.I,body[i]->posr.R);
+		dMULTIPLY0_333 (I+i*12,body[i]->posr.R,tmp);
+
+    // compute rotational force
+    dMULTIPLY0_331 (tmp,I+i*12,body[i]->avel);
+    dCROSS (body[i]->tacc,-=,body[i]->avel,tmp);
+#endif
+  }
+
+  // add the gravity force to all bodies
+  for (i=0; i<nb; i++) {
+    if ((body[i]->flags & dxBodyNoGravity)==0) {
+      body[i]->facc[0] += body[i]->mass.mass * world->gravity[0];
+      body[i]->facc[1] += body[i]->mass.mass * world->gravity[1];
+      body[i]->facc[2] += body[i]->mass.mass * world->gravity[2];
+    }
+  }
+
+  // get m = total constraint dimension, nub = number of unbounded variables.
+  // create constraint offset array and number-of-rows array for all joints.
+  // the constraints are re-ordered as follows: the purely unbounded
+  // constraints, the mixed unbounded + LCP constraints, and last the purely
+  // LCP constraints. this assists the LCP solver to put all unbounded
+  // variables at the start for a quick factorization.
+  //
+  // joints with m=0 are inactive and are removed from the joints array
+  // entirely, so that the code that follows does not consider them.
+  // also number all active joints in the joint list (set their tag values).
+  // inactive joints receive a tag value of -1.
+
+  int m = 0;
+  ALLOCA(dxJoint::Info1,info,nj*sizeof(dxJoint::Info1));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (info == NULL) {
+    UNALLOCA(invI);
+    UNALLOCA(I);
+    UNALLOCA(joint);
+    dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+    return;
+  }
+#endif
+  ALLOCA(int,ofs,nj*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (ofs == NULL) {
+    UNALLOCA(info);
+    UNALLOCA(invI);
+    UNALLOCA(I);
+    UNALLOCA(joint);
+    dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+    return;
+  }
+#endif
+  for (i=0, j=0; j<nj; j++) {	// i=dest, j=src
+    joint[j]->vtable->getInfo1 (joint[j],info+i);
+    dIASSERT (info[i].m >= 0 && info[i].m <= 6 &&
+	      info[i].nub >= 0 && info[i].nub <= info[i].m);
+    if (info[i].m > 0) {
+      joint[i] = joint[j];
+      joint[i]->tag = i;
+      i++;
+    }
+    else {
+      joint[j]->tag = -1;
+    }
+  }
+  nj = i;
+
+  // the purely unbounded constraints
+  for (i=0; i<nj; i++) if (info[i].nub == info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  int nub = m;
+  // the mixed unbounded + LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub > 0 && info[i].nub < info[i].m) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+  // the purely LCP constraints
+  for (i=0; i<nj; i++) if (info[i].nub == 0) {
+    ofs[i] = m;
+    m += info[i].m;
+  }
+
+  // this will be set to the force due to the constraints
+  ALLOCA(dReal,cforce,nb*8*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (cforce == NULL) {
+    UNALLOCA(ofs);
+    UNALLOCA(info);
+    UNALLOCA(invI);
+    UNALLOCA(I);
+    UNALLOCA(joint);
+    dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+    return;
+  }
+#endif
+  dSetZero (cforce,nb*8);
+
+  // if there are constraints, compute cforce
+  if (m > 0) {
+    // create a constraint equation right hand side vector `c', a constraint
+    // force mixing vector `cfm', and LCP low and high bound vectors, and an
+    // 'findex' vector.
+    ALLOCA(dReal,c,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (c == NULL) {
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,cfm,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (cfm == NULL) {
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,lo,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lo == NULL) {
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,hi,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (hi == NULL) {
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(int,findex,m*sizeof(int));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (findex == NULL) {
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSetZero (c,m);
+    dSetValue (cfm,m,world->global_cfm);
+    dSetValue (lo,m,-dInfinity);
+    dSetValue (hi,m, dInfinity);
+    for (i=0; i<m; i++) findex[i] = -1;
+
+    // get jacobian data from constraints. a (2*m)x8 matrix will be created
+    // to store the two jacobian blocks from each constraint. it has this
+    // format:
+    //
+    //   l l l 0 a a a 0  \    .
+    //   l l l 0 a a a 0   }-- jacobian body 1 block for joint 0 (3 rows)
+    //   l l l 0 a a a 0  /
+    //   l l l 0 a a a 0  \    .
+    //   l l l 0 a a a 0   }-- jacobian body 2 block for joint 0 (3 rows)
+    //   l l l 0 a a a 0  /
+    //   l l l 0 a a a 0  }--- jacobian body 1 block for joint 1 (1 row)
+    //   l l l 0 a a a 0  }--- jacobian body 2 block for joint 1 (1 row)
+    //   etc...
+    //
+    //   (lll) = linear jacobian data
+    //   (aaa) = angular jacobian data
+    //
+#   ifdef TIMING
+    dTimerNow ("create J");
+#   endif
+    ALLOCA(dReal,J,2*m*8*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (J == NULL) {
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSetZero (J,2*m*8);
+    dxJoint::Info2 Jinfo;
+    Jinfo.rowskip = 8;
+    Jinfo.fps = stepsize1;
+    Jinfo.erp = world->global_erp;
+    for (i=0; i<nj; i++) {
+      Jinfo.J1l = J + 2*8*ofs[i];
+      Jinfo.J1a = Jinfo.J1l + 4;
+      Jinfo.J2l = Jinfo.J1l + 8*info[i].m;
+      Jinfo.J2a = Jinfo.J2l + 4;
+      Jinfo.c = c + ofs[i];
+      Jinfo.cfm = cfm + ofs[i];
+      Jinfo.lo = lo + ofs[i];
+      Jinfo.hi = hi + ofs[i];
+      Jinfo.findex = findex + ofs[i];
+      joint[i]->vtable->getInfo2 (joint[i],&Jinfo);
+      // adjust returned findex values for global index numbering
+      for (j=0; j<info[i].m; j++) {
+	if (findex[ofs[i] + j] >= 0) findex[ofs[i] + j] += ofs[i];
+      }
+    }
+
+    // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
+    // format as J so we just go through the constraints in J multiplying by
+    // the appropriate scalars and matrices.
+#   ifdef TIMING
+    dTimerNow ("compute A");
+#   endif
+    ALLOCA(dReal,JinvM,2*m*8*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (JinvM == NULL) {
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSetZero (JinvM,2*m*8);
+    for (i=0; i<nj; i++) {
+      int b = joint[i]->node[0].body->tag;
+      dReal body_invMass = body[b]->invMass;
+      dReal *body_invI = invI + b*12;
+      dReal *Jsrc = J + 2*8*ofs[i];
+      dReal *Jdst = JinvM + 2*8*ofs[i];
+      for (j=info[i].m-1; j>=0; j--) {
+	for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass;
+	dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI);
+	Jsrc += 8;
+	Jdst += 8;
+      }
+      if (joint[i]->node[1].body) {
+	b = joint[i]->node[1].body->tag;
+	body_invMass = body[b]->invMass;
+	body_invI = invI + b*12;
+	for (j=info[i].m-1; j>=0; j--) {
+	  for (k=0; k<3; k++) Jdst[k] = Jsrc[k] * body_invMass;
+	  dMULTIPLY0_133 (Jdst+4,Jsrc+4,body_invI);
+	  Jsrc += 8;
+	  Jdst += 8;
+	}
+      }
+    }
+
+    // now compute A = JinvM * J'. A's rows and columns are grouped by joint,
+    // i.e. in the same way as the rows of J. block (i,j) of A is only nonzero
+    // if joints i and j have at least one body in common. this fact suggests
+    // the algorithm used to fill A:
+    //
+    //    for b = all bodies
+    //      n = number of joints attached to body b
+    //      for i = 1..n
+    //        for j = i+1..n
+    //          ii = actual joint number for i
+    //          jj = actual joint number for j
+    //          // (ii,jj) will be set to all pairs of joints around body b
+    //          compute blockwise: A(ii,jj) += JinvM(ii) * J(jj)'
+    //
+    // this algorithm catches all pairs of joints that have at least one body
+    // in common. it does not compute the diagonal blocks of A however -
+    // another similar algorithm does that.
+
+    int mskip = dPAD(m);
+    ALLOCA(dReal,A,m*mskip*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (A == NULL) {
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSetZero (A,m*mskip);
+    for (i=0; i<nb; i++) {
+      for (dxJointNode *n1=body[i]->firstjoint; n1; n1=n1->next) {
+	for (dxJointNode *n2=n1->next; n2; n2=n2->next) {
+	  // get joint numbers and ensure ofs[j1] >= ofs[j2]
+	  int j1 = n1->joint->tag;
+	  int j2 = n2->joint->tag;
+	  if (ofs[j1] < ofs[j2]) {
+	    int tmp = j1;
+	    j1 = j2;
+	    j2 = tmp;
+	  }
+
+	  // if either joint was tagged as -1 then it is an inactive (m=0)
+	  // joint that should not be considered
+	  if (j1==-1 || j2==-1) continue;
+
+	  // determine if body i is the 1st or 2nd body of joints j1 and j2
+	  int jb1 = (joint[j1]->node[1].body == body[i]);
+	  int jb2 = (joint[j2]->node[1].body == body[i]);
+	  // jb1/jb2 must be 0 for joints with only one body
+	  dIASSERT(joint[j1]->node[1].body || jb1==0);
+	  dIASSERT(joint[j2]->node[1].body || jb2==0);
+
+	  // set block of A
+	  MultiplyAdd2_p8r (A + ofs[j1]*mskip + ofs[j2],
+			    JinvM + 2*8*ofs[j1] + jb1*8*info[j1].m,
+			    J     + 2*8*ofs[j2] + jb2*8*info[j2].m,
+			    info[j1].m,info[j2].m, mskip);
+	}
+      }
+    }
+    // compute diagonal blocks of A
+    for (i=0; i<nj; i++) {
+      Multiply2_p8r (A + ofs[i]*(mskip+1),
+		     JinvM + 2*8*ofs[i],
+		     J + 2*8*ofs[i],
+		     info[i].m,info[i].m, mskip);
+      if (joint[i]->node[1].body) {
+	MultiplyAdd2_p8r (A + ofs[i]*(mskip+1),
+			  JinvM + 2*8*ofs[i] + 8*info[i].m,
+			  J + 2*8*ofs[i] + 8*info[i].m,
+			  info[i].m,info[i].m, mskip);
+      }
+    }
+
+    // add cfm to the diagonal of A
+    for (i=0; i<m; i++) A[i*mskip+i] += cfm[i] * stepsize1;
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (A,m,m,1,"A");
+#   endif
+
+    // compute the right hand side `rhs'
+#   ifdef TIMING
+    dTimerNow ("compute rhs");
+#   endif
+    ALLOCA(dReal,tmp1,nb*8*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp1 == NULL) {
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    //dSetZero (tmp1,nb*8);
+    // put v/h + invM*fe into tmp1
+    for (i=0; i<nb; i++) {
+      dReal body_invMass = body[i]->invMass;
+      dReal *body_invI = invI + i*12;
+      for (j=0; j<3; j++) tmp1[i*8+j] = body[i]->facc[j] * body_invMass +
+			    body[i]->lvel[j] * stepsize1;
+      dMULTIPLY0_331 (tmp1 + i*8 + 4,body_invI,body[i]->tacc);
+      for (j=0; j<3; j++) tmp1[i*8+4+j] += body[i]->avel[j] * stepsize1;
+    }
+    // put J*tmp1 into rhs
+    ALLOCA(dReal,rhs,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (rhs == NULL) {
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    //dSetZero (rhs,m);
+    for (i=0; i<nj; i++) {
+      dReal *JJ = J + 2*8*ofs[i];
+      Multiply0_p81 (rhs+ofs[i],JJ,
+		     tmp1 + 8*joint[i]->node[0].body->tag, info[i].m);
+      if (joint[i]->node[1].body) {
+	MultiplyAdd0_p81 (rhs+ofs[i],JJ + 8*info[i].m,
+			  tmp1 + 8*joint[i]->node[1].body->tag, info[i].m);
+      }
+    }
+    // complete rhs
+    for (i=0; i<m; i++) rhs[i] = c[i]*stepsize1 - rhs[i];
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (c,m,1,0,"c");
+    comparator.nextMatrix (rhs,m,1,0,"rhs");
+#   endif
+
+    // solve the LCP problem and get lambda.
+    // this will destroy A but that's okay
+#   ifdef TIMING
+    dTimerNow ("solving LCP problem");
+#   endif
+    ALLOCA(dReal,lambda,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (lambda == NULL) {
+      UNALLOCA(rhs);
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    ALLOCA(dReal,residual,m*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (residual == NULL) {
+      UNALLOCA(lambda);
+      UNALLOCA(rhs);
+      UNALLOCA(tmp1);
+      UNALLOCA(A);
+      UNALLOCA(JinvM);
+      UNALLOCA(J);
+      UNALLOCA(findex);
+      UNALLOCA(hi);
+      UNALLOCA(lo);
+      UNALLOCA(cfm);
+      UNALLOCA(c);
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+    dSolveLCP (m,A,lambda,rhs,residual,nub,lo,hi,findex);
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY)
+      return;
+#endif
+
+
+//  OLD WAY - direct factor and solve
+//
+//    // factorize A (L*L'=A)
+//#   ifdef TIMING
+//    dTimerNow ("factorize A");
+//#   endif
+//    dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
+//    memcpy (L,A,m*mskip*sizeof(dReal));
+//#   ifdef FAST_FACTOR
+//    dFastFactorCholesky (L,m);  // does not report non positive definiteness
+//#   else
+//    if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
+//#   endif
+//
+//    // compute lambda
+//#   ifdef TIMING
+//    dTimerNow ("compute lambda");
+//#   endif
+//    dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
+//    memcpy (lambda,rhs,m * sizeof(dReal));
+//    dSolveCholesky (L,lambda,m);
+
+#   ifdef COMPARE_METHODS
+    comparator.nextMatrix (lambda,m,1,0,"lambda");
+#   endif
+
+    // compute the constraint force `cforce'
+#   ifdef TIMING
+    dTimerNow ("compute constraint force");
+#   endif
+    // compute cforce = J'*lambda
+    for (i=0; i<nj; i++) {
+      dReal *JJ = J + 2*8*ofs[i];
+      dxBody* b1 = joint[i]->node[0].body;
+      dxBody* b2 = joint[i]->node[1].body;
+      dJointFeedback *fb = joint[i]->feedback;
+
+      if (fb) {
+	// the user has requested feedback on the amount of force that this
+	// joint is applying to the bodies. we use a slightly slower
+	// computation that splits out the force components and puts them
+	// in the feedback structure.
+	dReal data1[8],data2[8];
+	Multiply1_8q1 (data1, JJ, lambda+ofs[i], info[i].m);
+	dReal *cf1 = cforce + 8*b1->tag;
+	cf1[0] += (fb->f1[0] = data1[0]);
+	cf1[1] += (fb->f1[1] = data1[1]);
+	cf1[2] += (fb->f1[2] = data1[2]);
+	cf1[4] += (fb->t1[0] = data1[4]);
+	cf1[5] += (fb->t1[1] = data1[5]);
+	cf1[6] += (fb->t1[2] = data1[6]);
+	if (b2){
+	  Multiply1_8q1 (data2, JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
+	  dReal *cf2 = cforce + 8*b2->tag;
+	  cf2[0] += (fb->f2[0] = data2[0]);
+	  cf2[1] += (fb->f2[1] = data2[1]);
+	  cf2[2] += (fb->f2[2] = data2[2]);
+	  cf2[4] += (fb->t2[0] = data2[4]);
+	  cf2[5] += (fb->t2[1] = data2[5]);
+	  cf2[6] += (fb->t2[2] = data2[6]);
+	}
+      }
+      else {
+	// no feedback is required, let's compute cforce the faster way
+	MultiplyAdd1_8q1 (cforce + 8*b1->tag,JJ, lambda+ofs[i], info[i].m);
+	if (b2) {
+	  MultiplyAdd1_8q1 (cforce + 8*b2->tag,
+			    JJ + 8*info[i].m, lambda+ofs[i], info[i].m);
+	}
+      }
+    }
+    UNALLOCA(c);
+    UNALLOCA(cfm);
+    UNALLOCA(lo);
+    UNALLOCA(hi);
+    UNALLOCA(findex);
+    UNALLOCA(J);
+    UNALLOCA(JinvM);
+    UNALLOCA(A);
+    UNALLOCA(tmp1);
+    UNALLOCA(rhs);
+    UNALLOCA(lambda);
+    UNALLOCA(residual);
+  }
+
+  // compute the velocity update
+#ifdef TIMING
+  dTimerNow ("compute velocity update");
+#endif
+
+  // add fe to cforce
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) cforce[i*8+j] += body[i]->facc[j];
+    for (j=0; j<3; j++) cforce[i*8+4+j] += body[i]->tacc[j];
+  }
+  // multiply cforce by stepsize
+  for (i=0; i < nb*8; i++) cforce[i] *= stepsize;
+  // add invM * cforce to the body velocity
+  for (i=0; i<nb; i++) {
+    dReal body_invMass = body[i]->invMass;
+    dReal *body_invI = invI + i*12;
+    for (j=0; j<3; j++) body[i]->lvel[j] += body_invMass * cforce[i*8+j];
+    dMULTIPLYADD0_331 (body[i]->avel,body_invI,cforce+i*8+4);
+  }
+
+  // update the position and orientation from the new linear/angular velocity
+  // (over the given timestep)
+# ifdef TIMING
+  dTimerNow ("update position");
+# endif
+  for (i=0; i<nb; i++) dxStepBody (body[i],stepsize);
+
+#ifdef COMPARE_METHODS
+  ALLOCA(dReal,tmp, ALLOCA (nb*6*sizeof(dReal));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (tmp == NULL) {
+      UNALLOCA(cforce);
+      UNALLOCA(ofs);
+      UNALLOCA(info);
+      UNALLOCA(invI);
+      UNALLOCA(I);
+      UNALLOCA(joint);
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  for (i=0; i<nb; i++) {
+    for (j=0; j<3; j++) tmp_vnew[i*6+j] = body[i]->lvel[j];
+    for (j=0; j<3; j++) tmp_vnew[i*6+3+j] = body[i]->avel[j];
+  }
+  comparator.nextMatrix (tmp_vnew,nb*6,1,0,"vnew");
+  UNALLOCA(tmp);
+#endif
+
+#ifdef TIMING
+  dTimerNow ("tidy up");
+#endif
+
+  // zero all force accumulators
+  for (i=0; i<nb; i++) {
+    body[i]->facc[0] = 0;
+    body[i]->facc[1] = 0;
+    body[i]->facc[2] = 0;
+    body[i]->facc[3] = 0;
+    body[i]->tacc[0] = 0;
+    body[i]->tacc[1] = 0;
+    body[i]->tacc[2] = 0;
+    body[i]->tacc[3] = 0;
+  }
+
+#ifdef TIMING
+  dTimerEnd();
+  if (m > 0) dTimerReport (stdout,1);
+#endif
+      
+  UNALLOCA(joint);
+  UNALLOCA(I);
+  UNALLOCA(invI);
+  UNALLOCA(info);
+  UNALLOCA(ofs);
+  UNALLOCA(cforce);
+}
+
+//****************************************************************************
+
+void dInternalStepIsland (dxWorld *world, dxBody * const *body, int nb,
+			  dxJoint * const *joint, int nj, dReal stepsize)
+{
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  dMemoryFlag = d_MEMORY_OK;
+#endif
+
+#ifndef COMPARE_METHODS
+  dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize);
+
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+      REPORT_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+#endif
+
+#ifdef COMPARE_METHODS
+  int i;
+
+  // save body state
+  ALLOCA(dxBody,state,nb*sizeof(dxBody));
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (state == NULL) {
+      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
+      REPORT_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+  for (i=0; i<nb; i++) memcpy (state+i,body[i],sizeof(dxBody));
+
+  // take slow step
+  comparator.reset();
+  dInternalStepIsland_x1 (world,body,nb,joint,nj,stepsize);
+  comparator.end();
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+  if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+    UNALLOCA(state);
+    REPORT_OUT_OF_MEMORY;
+    return;
+  }
+#endif
+
+  // restore state
+  for (i=0; i<nb; i++) memcpy (body[i],state+i,sizeof(dxBody));
+
+  // take fast step
+  dInternalStepIsland_x2 (world,body,nb,joint,nj,stepsize);
+  comparator.end();
+#ifdef dUSE_MALLOC_FOR_ALLOCA
+    if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
+      UNALLOCA(state);
+      REPORT_OUT_OF_MEMORY;
+      return;
+    }
+#endif
+
+  //comparator.dump();
+  //_exit (1);
+  UNALLOCA(state);
+#endif
+}
+
+
Index: /code/branches/ode/ode-0.9/ode/src/step.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/step.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/step.h	(revision 216)
@@ -0,0 +1,36 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_STEP_H_
+#define _ODE_STEP_H_
+
+#include <ode/common.h>
+
+
+void dInternalStepIsland (dxWorld *world,
+			  dxBody * const *body, int nb,
+			  dxJoint * const *joint, int nj,
+			  dReal stepsize);
+
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/stepfast.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/stepfast.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/stepfast.cpp	(revision 216)
@@ -0,0 +1,1139 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * Fast iterative solver, David Whittaker. Email: david@csworkbench.com  *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+// This is the StepFast code by David Whittaker. This code is faster, but
+// sometimes less stable than, the original "big matrix" code.
+// Refer to the user's manual for more information.
+// Note that this source file duplicates a lot of stuff from step.cpp,
+// eventually we should move the common code to a third file.
+
+#include "objects.h"
+#include "joint.h"
+#include <ode/config.h>
+#include <ode/objects.h>
+#include <ode/odemath.h>
+#include <ode/rotation.h>
+#include <ode/timer.h>
+#include <ode/error.h>
+#include <ode/matrix.h>
+#include <ode/misc.h>
+#include "lcp.h"
+#include "step.h"
+#include "util.h"
+
+
+// misc defines
+
+#define ALLOCA dALLOCA16
+
+#define RANDOM_JOINT_ORDER
+//#define FAST_FACTOR	//use a factorization approximation to the LCP solver (fast, theoretically less accurate)
+#define SLOW_LCP      //use the old LCP solver
+//#define NO_ISLANDS    //does not perform island creation code (3~4% of simulation time), body disabling doesn't work
+//#define TIMING
+
+
+static int autoEnableDepth = 2;
+
+void dWorldSetAutoEnableDepthSF1 (dxWorld *world, int autodepth)
+{
+	if (autodepth > 0)
+		autoEnableDepth = autodepth;
+	else
+		autoEnableDepth = 0;
+}
+
+int dWorldGetAutoEnableDepthSF1 (dxWorld *world)
+{
+	return autoEnableDepth;
+}
+
+//little bit of math.... the _sym_ functions assume the return matrix will be symmetric
+static void
+Multiply2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip)
+{
+	int i, j;
+	dReal sum, *aa, *ad, *bb, *cc;
+	dIASSERT (p > 0 && A && B && C);
+	bb = B;
+	for (i = 0; i < p; i++)
+	{
+		//aa is going accross the matrix, ad down
+		aa = ad = A;
+		cc = C;
+		for (j = i; j < p; j++)
+		{
+			sum = bb[0] * cc[0];
+			sum += bb[1] * cc[1];
+			sum += bb[2] * cc[2];
+			sum += bb[4] * cc[4];
+			sum += bb[5] * cc[5];
+			sum += bb[6] * cc[6];
+			*(aa++) = *ad = sum;
+			ad += Askip;
+			cc += 8;
+		}
+		bb += 8;
+		A += Askip + 1;
+		C += 8;
+	}
+}
+
+static void
+MultiplyAdd2_sym_p8p (dReal * A, dReal * B, dReal * C, int p, int Askip)
+{
+	int i, j;
+	dReal sum, *aa, *ad, *bb, *cc;
+	dIASSERT (p > 0 && A && B && C);
+	bb = B;
+	for (i = 0; i < p; i++)
+	{
+		//aa is going accross the matrix, ad down
+		aa = ad = A;
+		cc = C;
+		for (j = i; j < p; j++)
+		{
+			sum = bb[0] * cc[0];
+			sum += bb[1] * cc[1];
+			sum += bb[2] * cc[2];
+			sum += bb[4] * cc[4];
+			sum += bb[5] * cc[5];
+			sum += bb[6] * cc[6];
+			*(aa++) += sum;
+			*ad += sum;
+			ad += Askip;
+			cc += 8;
+		}
+		bb += 8;
+		A += Askip + 1;
+		C += 8;
+	}
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void
+Multiply0_p81 (dReal * A, dReal * B, dReal * C, int p)
+{
+	int i;
+	dIASSERT (p > 0 && A && B && C);
+	dReal sum;
+	for (i = p; i; i--)
+	{
+		sum = B[0] * C[0];
+		sum += B[1] * C[1];
+		sum += B[2] * C[2];
+		sum += B[4] * C[4];
+		sum += B[5] * C[5];
+		sum += B[6] * C[6];
+		*(A++) = sum;
+		B += 8;
+	}
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void
+MultiplyAdd0_p81 (dReal * A, dReal * B, dReal * C, int p)
+{
+	int i;
+	dIASSERT (p > 0 && A && B && C);
+	dReal sum;
+	for (i = p; i; i--)
+	{
+		sum = B[0] * C[0];
+		sum += B[1] * C[1];
+		sum += B[2] * C[2];
+		sum += B[4] * C[4];
+		sum += B[5] * C[5];
+		sum += B[6] * C[6];
+		*(A++) += sum;
+		B += 8;
+	}
+}
+
+
+// this assumes the 4th and 8th rows of B are zero.
+
+static void
+Multiply1_8q1 (dReal * A, dReal * B, dReal * C, int q)
+{
+	int k;
+	dReal sum;
+	dIASSERT (q > 0 && A && B && C);
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[k * 8] * C[k];
+	A[0] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[1 + k * 8] * C[k];
+	A[1] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[2 + k * 8] * C[k];
+	A[2] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[4 + k * 8] * C[k];
+	A[4] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[5 + k * 8] * C[k];
+	A[5] = sum;
+	sum = 0;
+	for (k = 0; k < q; k++)
+		sum += B[6 + k * 8] * C[k];
+	A[6] = sum;
+}
+
+//****************************************************************************
+// body rotation
+
+// return sin(x)/x. this has a singularity at 0 so special handling is needed
+// for small arguments.
+
+static inline dReal
+sinc (dReal x)
+{
+	// if |x| < 1e-4 then use a taylor series expansion. this two term expansion
+	// is actually accurate to one LS bit within this range if double precision
+	// is being used - so don't worry!
+	if (dFabs (x) < 1.0e-4)
+		return REAL (1.0) - x * x * REAL (0.166666666666666666667);
+	else
+		return dSin (x) / x;
+}
+
+
+// given a body b, apply its linear and angular rotation over the time
+// interval h, thereby adjusting its position and orientation.
+
+static inline void
+moveAndRotateBody (dxBody * b, dReal h)
+{
+	int j;
+
+	// handle linear velocity
+	for (j = 0; j < 3; j++)
+		b->posr.pos[j] += h * b->lvel[j];
+
+	if (b->flags & dxBodyFlagFiniteRotation)
+	{
+		dVector3 irv;			// infitesimal rotation vector
+		dQuaternion q;			// quaternion for finite rotation
+
+		if (b->flags & dxBodyFlagFiniteRotationAxis)
+		{
+			// split the angular velocity vector into a component along the finite
+			// rotation axis, and a component orthogonal to it.
+			dVector3 frv, irv;	// finite rotation vector
+			dReal k = dDOT (b->finite_rot_axis, b->avel);
+			frv[0] = b->finite_rot_axis[0] * k;
+			frv[1] = b->finite_rot_axis[1] * k;
+			frv[2] = b->finite_rot_axis[2] * k;
+			irv[0] = b->avel[0] - frv[0];
+			irv[1] = b->avel[1] - frv[1];
+			irv[2] = b->avel[2] - frv[2];
+
+			// make a rotation quaternion q that corresponds to frv * h.
+			// compare this with the full-finite-rotation case below.
+			h *= REAL (0.5);
+			dReal theta = k * h;
+			q[0] = dCos (theta);
+			dReal s = sinc (theta) * h;
+			q[1] = frv[0] * s;
+			q[2] = frv[1] * s;
+			q[3] = frv[2] * s;
+		}
+		else
+		{
+			// make a rotation quaternion q that corresponds to w * h
+			dReal wlen = dSqrt (b->avel[0] * b->avel[0] + b->avel[1] * b->avel[1] + b->avel[2] * b->avel[2]);
+			h *= REAL (0.5);
+			dReal theta = wlen * h;
+			q[0] = dCos (theta);
+			dReal s = sinc (theta) * h;
+			q[1] = b->avel[0] * s;
+			q[2] = b->avel[1] * s;
+			q[3] = b->avel[2] * s;
+		}
+
+		// do the finite rotation
+		dQuaternion q2;
+		dQMultiply0 (q2, q, b->q);
+		for (j = 0; j < 4; j++)
+			b->q[j] = q2[j];
+
+		// do the infitesimal rotation if required
+		if (b->flags & dxBodyFlagFiniteRotationAxis)
+		{
+			dReal dq[4];
+			dWtoDQ (irv, b->q, dq);
+			for (j = 0; j < 4; j++)
+				b->q[j] += h * dq[j];
+		}
+	}
+	else
+	{
+		// the normal way - do an infitesimal rotation
+		dReal dq[4];
+		dWtoDQ (b->avel, b->q, dq);
+		for (j = 0; j < 4; j++)
+			b->q[j] += h * dq[j];
+	}
+
+	// normalize the quaternion and convert it to a rotation matrix
+	dNormalize4 (b->q);
+	dQtoR (b->q, b->posr.R);
+
+	// notify all attached geoms that this body has moved
+	for (dxGeom * geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+		dGeomMoved (geom);
+}
+
+//****************************************************************************
+//This is an implementation of the iterated/relaxation algorithm.
+//Here is a quick overview of the algorithm per Sergi Valverde's posts to the
+//mailing list:
+//
+//  for i=0..N-1 do
+//      for c = 0..C-1 do
+//          Solve constraint c-th
+//          Apply forces to constraint bodies
+//      next
+//  next
+//  Integrate bodies
+
+void
+dInternalStepFast (dxWorld * world, dxBody * body[2], dReal * GI[2], dReal * GinvI[2], dxJoint * joint, dxJoint::Info1 info, dxJoint::Info2 Jinfo, dReal stepsize)
+{
+	int i, j, k;
+# ifdef TIMING
+	dTimerNow ("constraint preprocessing");
+# endif
+
+	dReal stepsize1 = dRecip (stepsize);
+
+	int m = info.m;
+	// nothing to do if no constraints.
+	if (m <= 0)
+		return;
+
+	int nub = 0;
+	if (info.nub == info.m)
+		nub = m;
+
+	// compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
+	// format as J so we just go through the constraints in J multiplying by
+	// the appropriate scalars and matrices.
+#   ifdef TIMING
+	dTimerNow ("compute A");
+#   endif
+	dReal JinvM[2 * 6 * 8];
+	//dSetZero (JinvM, 2 * m * 8);
+
+	dReal *Jsrc = Jinfo.J1l;
+	dReal *Jdst = JinvM;
+	if (body[0])
+	{
+		for (j = m - 1; j >= 0; j--)
+		{
+			for (k = 0; k < 3; k++)
+				Jdst[k] = Jsrc[k] * body[0]->invMass;
+			dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[0]);
+			Jsrc += 8;
+			Jdst += 8;
+		}
+	}
+	if (body[1])
+	{
+		Jsrc = Jinfo.J2l;
+		Jdst = JinvM + 8 * m;
+		for (j = m - 1; j >= 0; j--)
+		{
+			for (k = 0; k < 3; k++)
+				Jdst[k] = Jsrc[k] * body[1]->invMass;
+			dMULTIPLY0_133 (Jdst + 4, Jsrc + 4, GinvI[1]);
+			Jsrc += 8;
+			Jdst += 8;
+		}
+	}
+
+
+	// now compute A = JinvM * J'.
+	int mskip = dPAD (m);
+	dReal A[6 * 8];
+	//dSetZero (A, 6 * 8);
+
+	if (body[0]) {
+		Multiply2_sym_p8p (A, JinvM, Jinfo.J1l, m, mskip);
+		if (body[1])
+			MultiplyAdd2_sym_p8p (A, JinvM + 8 * m, Jinfo.J2l,
+                                              m, mskip);
+	} else {
+		if (body[1])
+			Multiply2_sym_p8p (A, JinvM + 8 * m, Jinfo.J2l,
+                                           m, mskip);
+	}
+
+	// add cfm to the diagonal of A
+	for (i = 0; i < m; i++)
+		A[i * mskip + i] += Jinfo.cfm[i] * stepsize1;
+
+	// compute the right hand side `rhs'
+#   ifdef TIMING
+	dTimerNow ("compute rhs");
+#   endif
+	dReal tmp1[16];
+	//dSetZero (tmp1, 16);
+	// put v/h + invM*fe into tmp1
+	for (i = 0; i < 2; i++)
+	{
+		if (!body[i])
+			continue;
+		for (j = 0; j < 3; j++)
+			tmp1[i * 8 + j] = body[i]->facc[j] * body[i]->invMass + body[i]->lvel[j] * stepsize1;
+		dMULTIPLY0_331 (tmp1 + i * 8 + 4, GinvI[i], body[i]->tacc);
+		for (j = 0; j < 3; j++)
+			tmp1[i * 8 + 4 + j] += body[i]->avel[j] * stepsize1;
+	}
+	// put J*tmp1 into rhs
+	dReal rhs[6];
+	//dSetZero (rhs, 6);
+
+	if (body[0]) {
+		Multiply0_p81 (rhs, Jinfo.J1l, tmp1, m);
+		if (body[1])
+			MultiplyAdd0_p81 (rhs, Jinfo.J2l, tmp1 + 8, m);
+	} else {
+		if (body[1])
+			Multiply0_p81 (rhs, Jinfo.J2l, tmp1 + 8, m);
+	}
+
+	// complete rhs
+	for (i = 0; i < m; i++)
+		rhs[i] = Jinfo.c[i] * stepsize1 - rhs[i];
+
+#ifdef SLOW_LCP
+	// solve the LCP problem and get lambda.
+	// this will destroy A but that's okay
+#	ifdef TIMING
+	dTimerNow ("solving LCP problem");
+#	endif
+	dReal *lambda = (dReal *) ALLOCA (m * sizeof (dReal));
+	dReal *residual = (dReal *) ALLOCA (m * sizeof (dReal));
+	dReal lo[6], hi[6];
+	memcpy (lo, Jinfo.lo, m * sizeof (dReal));
+	memcpy (hi, Jinfo.hi, m * sizeof (dReal));
+	dSolveLCP (m, A, lambda, rhs, residual, nub, lo, hi, Jinfo.findex);
+#endif
+
+	// LCP Solver replacement:
+	// This algorithm goes like this:
+	// Do a straightforward LDLT factorization of the matrix A, solving for
+	// A*x = rhs
+	// For each x[i] that is outside of the bounds of lo[i] and hi[i],
+	//    clamp x[i] into that range.
+	//    Substitute into A the now known x's
+	//    subtract the residual away from the rhs.
+	//    Remove row and column i from L, updating the factorization
+	//    place the known x's at the end of the array, keeping up with location in p
+	// Repeat until all constraints have been clamped or all are within bounds
+	//
+	// This is probably only faster in the single joint case where only one repeat is
+	// the norm.
+
+#ifdef FAST_FACTOR
+	// factorize A (L*D*L'=A)
+#	ifdef TIMING
+	dTimerNow ("factorize A");
+#	endif
+	dReal d[6];
+	dReal L[6 * 8];
+	memcpy (L, A, m * mskip * sizeof (dReal));
+	dFactorLDLT (L, d, m, mskip);
+
+	// compute lambda
+#	ifdef TIMING
+	dTimerNow ("compute lambda");
+#	endif
+
+	int left = m;				//constraints left to solve.
+	int remove[6];
+	dReal lambda[6];
+	dReal x[6];
+	int p[6];
+	for (i = 0; i < 6; i++)
+		p[i] = i;
+	while (true)
+	{
+		memcpy (x, rhs, left * sizeof (dReal));
+		dSolveLDLT (L, d, x, left, mskip);
+
+		int fixed = 0;
+		for (i = 0; i < left; i++)
+		{
+			j = p[i];
+			remove[i] = false;
+			// This isn't the exact same use of findex as dSolveLCP.... since x[findex]
+			// may change after I've already clamped x[i], but it should be close
+			if (Jinfo.findex[j] > -1)
+			{
+				dReal f = fabs (Jinfo.hi[j] * x[p[Jinfo.findex[j]]]);
+				if (x[i] > f)
+					x[i] = f;
+				else if (x[i] < -f)
+					x[i] = -f;
+				else
+					continue;
+			}
+			else
+			{
+				if (x[i] > Jinfo.hi[j])
+					x[i] = Jinfo.hi[j];
+				else if (x[i] < Jinfo.lo[j])
+					x[i] = Jinfo.lo[j];
+				else
+					continue;
+			}
+			remove[i] = true;
+			fixed++;
+		}
+		if (fixed == 0 || fixed == left)	//no change or all constraints solved
+			break;
+
+		for (i = 0; i < left; i++)	//sub in to right hand side.
+			if (remove[i])
+				for (j = 0; j < left; j++)
+					if (!remove[j])
+						rhs[j] -= A[j * mskip + i] * x[i];
+
+		for (int r = left - 1; r >= 0; r--)	//eliminate row/col for fixed variables
+		{
+			if (remove[r])
+			{
+				//dRemoveLDLT adapted for use without row pointers.
+				if (r == left - 1)
+				{
+					left--;
+					continue;	// deleting last row/col is easy
+				}
+				else if (r == 0)
+				{
+					dReal a[6];
+					for (i = 0; i < left; i++)
+						a[i] = -A[i * mskip];
+					a[0] += REAL (1.0);
+					dLDLTAddTL (L, d, a, left, mskip);
+				}
+				else
+				{
+					dReal t[6];
+					dReal a[6];
+					for (i = 0; i < r; i++)
+						t[i] = L[r * mskip + i] / d[i];
+					for (i = 0; i < left - r; i++)
+						a[i] = dDot (L + (r + i) * mskip, t, r) - A[(r + i) * mskip + r];
+					a[0] += REAL (1.0);
+					dLDLTAddTL (L + r * mskip + r, d + r, a, left - r, mskip);
+				}
+
+				dRemoveRowCol (L, left, mskip, r);
+				//end dRemoveLDLT
+
+				left--;
+				if (r < (left - 1))
+				{
+					dReal tx = x[r];
+					memmove (d + r, d + r + 1, (left - r) * sizeof (dReal));
+					memmove (rhs + r, rhs + r + 1, (left - r) * sizeof (dReal));
+					//x will get written over by rhs anyway, no need to move it around
+					//just store the fixed value we just discovered in it.
+					x[left] = tx;
+					for (i = 0; i < m; i++)
+						if (p[i] > r && p[i] <= left)
+							p[i]--;
+					p[r] = left;
+				}
+			}
+		}
+	}
+
+	for (i = 0; i < m; i++)
+		lambda[i] = x[p[i]];
+#	endif
+	// compute the constraint force `cforce'
+#	ifdef TIMING
+	dTimerNow ("compute constraint force");
+#endif
+
+	// compute cforce = J'*lambda
+	dJointFeedback *fb = joint->feedback;
+	dReal cforce[16];
+	//dSetZero (cforce, 16);
+
+	if (fb)
+	{
+		// the user has requested feedback on the amount of force that this
+		// joint is applying to the bodies. we use a slightly slower
+		// computation that splits out the force components and puts them
+		// in the feedback structure.
+		dReal data1[8], data2[8];
+		if (body[0])
+		{
+			Multiply1_8q1 (data1, Jinfo.J1l, lambda, m);
+			dReal *cf1 = cforce;
+			cf1[0] = (fb->f1[0] = data1[0]);
+			cf1[1] = (fb->f1[1] = data1[1]);
+			cf1[2] = (fb->f1[2] = data1[2]);
+			cf1[4] = (fb->t1[0] = data1[4]);
+			cf1[5] = (fb->t1[1] = data1[5]);
+			cf1[6] = (fb->t1[2] = data1[6]);
+		}
+		if (body[1])
+		{
+			Multiply1_8q1 (data2, Jinfo.J2l, lambda, m);
+			dReal *cf2 = cforce + 8;
+			cf2[0] = (fb->f2[0] = data2[0]);
+			cf2[1] = (fb->f2[1] = data2[1]);
+			cf2[2] = (fb->f2[2] = data2[2]);
+			cf2[4] = (fb->t2[0] = data2[4]);
+			cf2[5] = (fb->t2[1] = data2[5]);
+			cf2[6] = (fb->t2[2] = data2[6]);
+		}
+	}
+	else
+	{
+		// no feedback is required, let's compute cforce the faster way
+		if (body[0])
+			Multiply1_8q1 (cforce, Jinfo.J1l, lambda, m);
+		if (body[1])
+			Multiply1_8q1 (cforce + 8, Jinfo.J2l, lambda, m);
+	}
+
+	for (i = 0; i < 2; i++)
+	{
+		if (!body[i])
+			continue;
+		for (j = 0; j < 3; j++)
+		{
+			body[i]->facc[j] += cforce[i * 8 + j];
+			body[i]->tacc[j] += cforce[i * 8 + 4 + j];
+		}
+	}
+}
+
+void
+dInternalStepIslandFast (dxWorld * world, dxBody * const *bodies, int nb, dxJoint * const *_joints, int nj, dReal stepsize, int maxiterations)
+{
+#   ifdef TIMING
+	dTimerNow ("preprocessing");
+#   endif
+	dxBody *bodyPair[2], *body;
+	dReal *GIPair[2], *GinvIPair[2];
+	dxJoint *joint;
+	int iter, b, j, i;
+	dReal ministep = stepsize / maxiterations;
+
+	// make a local copy of the joint array, because we might want to modify it.
+	// (the "dxJoint *const*" declaration says we're allowed to modify the joints
+	// but not the joint array, because the caller might need it unchanged).
+	dxJoint **joints = (dxJoint **) ALLOCA (nj * sizeof (dxJoint *));
+	memcpy (joints, _joints, nj * sizeof (dxJoint *));
+
+	// get m = total constraint dimension, nub = number of unbounded variables.
+	// create constraint offset array and number-of-rows array for all joints.
+	// the constraints are re-ordered as follows: the purely unbounded
+	// constraints, the mixed unbounded + LCP constraints, and last the purely
+	// LCP constraints. this assists the LCP solver to put all unbounded
+	// variables at the start for a quick factorization.
+	//
+	// joints with m=0 are inactive and are removed from the joints array
+	// entirely, so that the code that follows does not consider them.
+	// also number all active joints in the joint list (set their tag values).
+	// inactive joints receive a tag value of -1.
+
+	int m = 0;
+	dxJoint::Info1 * info = (dxJoint::Info1 *) ALLOCA (nj * sizeof (dxJoint::Info1));
+	int *ofs = (int *) ALLOCA (nj * sizeof (int));
+	for (i = 0, j = 0; j < nj; j++)
+	{	// i=dest, j=src
+		joints[j]->vtable->getInfo1 (joints[j], info + i);
+		dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m);
+		if (info[i].m > 0)
+		{
+			joints[i] = joints[j];
+			joints[i]->tag = i;
+			i++;
+		}
+		else
+		{
+			joints[j]->tag = -1;
+		}
+	}
+	nj = i;
+
+	// the purely unbounded constraints
+	for (i = 0; i < nj; i++)
+	{
+		ofs[i] = m;
+		m += info[i].m;
+	}
+	dReal *c = NULL;
+	dReal *cfm = NULL;
+	dReal *lo = NULL;
+	dReal *hi = NULL;
+	int *findex = NULL;
+
+	dReal *J = NULL;
+	dxJoint::Info2 * Jinfo = NULL;
+
+	if (m)
+	{
+	// create a constraint equation right hand side vector `c', a constraint
+	// force mixing vector `cfm', and LCP low and high bound vectors, and an
+	// 'findex' vector.
+		c = (dReal *) ALLOCA (m * sizeof (dReal));
+		cfm = (dReal *) ALLOCA (m * sizeof (dReal));
+		lo = (dReal *) ALLOCA (m * sizeof (dReal));
+		hi = (dReal *) ALLOCA (m * sizeof (dReal));
+		findex = (int *) ALLOCA (m * sizeof (int));
+	dSetZero (c, m);
+	dSetValue (cfm, m, world->global_cfm);
+	dSetValue (lo, m, -dInfinity);
+	dSetValue (hi, m, dInfinity);
+	for (i = 0; i < m; i++)
+		findex[i] = -1;
+
+	// get jacobian data from constraints. a (2*m)x8 matrix will be created
+	// to store the two jacobian blocks from each constraint. it has this
+	// format:
+	//
+	//   l l l 0 a a a 0  \    .
+	//   l l l 0 a a a 0   }-- jacobian body 1 block for joint 0 (3 rows)
+	//   l l l 0 a a a 0  /
+	//   l l l 0 a a a 0  \    .
+	//   l l l 0 a a a 0   }-- jacobian body 2 block for joint 0 (3 rows)
+	//   l l l 0 a a a 0  /
+	//   l l l 0 a a a 0  }--- jacobian body 1 block for joint 1 (1 row)
+	//   l l l 0 a a a 0  }--- jacobian body 2 block for joint 1 (1 row)
+	//   etc...
+	//
+	//   (lll) = linear jacobian data
+	//   (aaa) = angular jacobian data
+	//
+#   ifdef TIMING
+	dTimerNow ("create J");
+#   endif
+		J = (dReal *) ALLOCA (2 * m * 8 * sizeof (dReal));
+		dSetZero (J, 2 * m * 8);
+		Jinfo = (dxJoint::Info2 *) ALLOCA (nj * sizeof (dxJoint::Info2));
+	for (i = 0; i < nj; i++)
+	{
+		Jinfo[i].rowskip = 8;
+		Jinfo[i].fps = dRecip (stepsize);
+		Jinfo[i].erp = world->global_erp;
+		Jinfo[i].J1l = J + 2 * 8 * ofs[i];
+		Jinfo[i].J1a = Jinfo[i].J1l + 4;
+		Jinfo[i].J2l = Jinfo[i].J1l + 8 * info[i].m;
+		Jinfo[i].J2a = Jinfo[i].J2l + 4;
+		Jinfo[i].c = c + ofs[i];
+		Jinfo[i].cfm = cfm + ofs[i];
+		Jinfo[i].lo = lo + ofs[i];
+		Jinfo[i].hi = hi + ofs[i];
+		Jinfo[i].findex = findex + ofs[i];
+		//joints[i]->vtable->getInfo2 (joints[i], Jinfo+i);
+	}
+
+	}
+
+	dReal *saveFacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal));
+	dReal *saveTacc = (dReal *) ALLOCA (nb * 4 * sizeof (dReal));
+	dReal *globalI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal));
+	dReal *globalInvI = (dReal *) ALLOCA (nb * 12 * sizeof (dReal));
+	for (b = 0; b < nb; b++)
+	{
+		for (i = 0; i < 4; i++)
+		{
+			saveFacc[b * 4 + i] = bodies[b]->facc[i];
+			saveTacc[b * 4 + i] = bodies[b]->tacc[i];
+		}
+                bodies[b]->tag = b;
+	}
+
+	for (iter = 0; iter < maxiterations; iter++)
+	{
+#	ifdef TIMING
+		dTimerNow ("applying inertia and gravity");
+#	endif
+		dReal tmp[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+		for (b = 0; b < nb; b++)
+		{
+			body = bodies[b];
+
+			// for all bodies, compute the inertia tensor and its inverse in the global
+			// frame, and compute the rotational force and add it to the torque
+			// accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
+			// @@@ check computation of rotational force.
+
+			// compute inertia tensor in global frame
+			dMULTIPLY2_333 (tmp, body->mass.I, body->posr.R);
+			dMULTIPLY0_333 (globalI + b * 12, body->posr.R, tmp);
+			// compute inverse inertia tensor in global frame
+			dMULTIPLY2_333 (tmp, body->invI, body->posr.R);
+			dMULTIPLY0_333 (globalInvI + b * 12, body->posr.R, tmp);
+
+			for (i = 0; i < 4; i++)
+				body->tacc[i] = saveTacc[b * 4 + i];
+#ifdef dGYROSCOPIC
+			// compute rotational force
+			dMULTIPLY0_331 (tmp, globalI + b * 12, body->avel);
+			dCROSS (body->tacc, -=, body->avel, tmp);
+#endif
+
+			// add the gravity force to all bodies
+			if ((body->flags & dxBodyNoGravity) == 0)
+			{
+				body->facc[0] = saveFacc[b * 4 + 0] + body->mass.mass * world->gravity[0];
+				body->facc[1] = saveFacc[b * 4 + 1] + body->mass.mass * world->gravity[1];
+				body->facc[2] = saveFacc[b * 4 + 2] + body->mass.mass * world->gravity[2];
+				body->facc[3] = 0;
+			} else {
+                                body->facc[0] = saveFacc[b * 4 + 0];
+                                body->facc[1] = saveFacc[b * 4 + 1];
+                                body->facc[2] = saveFacc[b * 4 + 2];
+				body->facc[3] = 0;
+                        }
+
+		}
+
+#ifdef RANDOM_JOINT_ORDER
+#ifdef TIMING
+		dTimerNow ("randomizing joint order");
+#endif
+		//randomize the order of the joints by looping through the array
+		//and swapping the current joint pointer with a random one before it.
+		for (j = 0; j < nj; j++)
+		{
+			joint = joints[j];
+			dxJoint::Info1 i1 = info[j];
+			dxJoint::Info2 i2 = Jinfo[j];
+                        const int r = dRandInt(j+1);
+			dIASSERT (r < nj);
+			joints[j] = joints[r];
+			info[j] = info[r];
+			Jinfo[j] = Jinfo[r];
+			joints[r] = joint;
+			info[r] = i1;
+			Jinfo[r] = i2;
+		}
+#endif
+
+		//now iterate through the random ordered joint array we created.
+		for (j = 0; j < nj; j++)
+		{
+#ifdef TIMING
+			dTimerNow ("setting up joint");
+#endif
+			joint = joints[j];
+			bodyPair[0] = joint->node[0].body;
+			bodyPair[1] = joint->node[1].body;
+
+			if (bodyPair[0] && (bodyPair[0]->flags & dxBodyDisabled))
+				bodyPair[0] = 0;
+			if (bodyPair[1] && (bodyPair[1]->flags & dxBodyDisabled))
+				bodyPair[1] = 0;
+			
+			//if this joint is not connected to any enabled bodies, skip it.
+			if (!bodyPair[0] && !bodyPair[1])
+				continue;
+			
+			if (bodyPair[0])
+			{
+				GIPair[0] = globalI + bodyPair[0]->tag * 12;
+				GinvIPair[0] = globalInvI + bodyPair[0]->tag * 12;
+			}
+			if (bodyPair[1])
+			{
+				GIPair[1] = globalI + bodyPair[1]->tag * 12;
+				GinvIPair[1] = globalInvI + bodyPair[1]->tag * 12;
+			}
+
+			joints[j]->vtable->getInfo2 (joints[j], Jinfo + j);
+
+			//dInternalStepIslandFast is an exact copy of the old routine with one
+			//modification: the calculated forces are added back to the facc and tacc
+			//vectors instead of applying them to the bodies and moving them.
+			if (info[j].m > 0)
+			{
+			dInternalStepFast (world, bodyPair, GIPair, GinvIPair, joint, info[j], Jinfo[j], ministep);
+			}		
+		}
+		//  }
+#	ifdef TIMING
+		dTimerNow ("moving bodies");
+#	endif
+		//Now we can simulate all the free floating bodies, and move them.
+		for (b = 0; b < nb; b++)
+		{
+			body = bodies[b];
+
+			for (i = 0; i < 4; i++)
+			{
+				body->facc[i] *= ministep;
+				body->tacc[i] *= ministep;
+			}
+
+			//apply torque
+			dMULTIPLYADD0_331 (body->avel, globalInvI + b * 12, body->tacc);
+
+			//apply force
+			for (i = 0; i < 3; i++)
+				body->lvel[i] += body->invMass * body->facc[i];
+
+			//move It!
+			moveAndRotateBody (body, ministep);
+		}
+	}
+	for (b = 0; b < nb; b++)
+		for (j = 0; j < 4; j++)
+			bodies[b]->facc[j] = bodies[b]->tacc[j] = 0;
+}
+
+
+#ifdef NO_ISLANDS
+
+// Since the iterative algorithm doesn't care about islands of bodies, this is a
+// faster algorithm that just sends it all the joints and bodies in one array.
+// It's downfall is it's inability to handle disabled bodies as well as the old one.
+static void
+processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations)
+{
+	// nothing to do if no bodies
+	if (world->nb <= 0)
+		return;
+
+	dInternalHandleAutoDisabling (world,stepsize);
+
+#	ifdef TIMING
+	dTimerStart ("creating joint and body arrays");
+#	endif
+	dxBody **bodies, *body;
+	dxJoint **joints, *joint;
+	joints = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *));
+	bodies = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *));
+
+	int nj = 0;
+	for (joint = world->firstjoint; joint; joint = (dxJoint *) joint->next)
+		joints[nj++] = joint;
+
+	int nb = 0;
+	for (body = world->firstbody; body; body = (dxBody *) body->next)
+		bodies[nb++] = body;
+
+	dInternalStepIslandFast (world, bodies, nb, joints, nj, stepsize, maxiterations);
+#	ifdef TIMING
+	dTimerEnd ();
+	dTimerReport (stdout, 1);
+#	endif
+}
+
+#else
+
+//****************************************************************************
+// island processing
+
+// this groups all joints and bodies in a world into islands. all objects
+// in an island are reachable by going through connected bodies and joints.
+// each island can be simulated separately.
+// note that joints that are not attached to anything will not be included
+// in any island, an so they do not affect the simulation.
+//
+// this function starts new island from unvisited bodies. however, it will
+// never start a new islands from a disabled body. thus islands of disabled
+// bodies will not be included in the simulation. disabled bodies are
+// re-enabled if they are found to be part of an active island.
+
+static void
+processIslandsFast (dxWorld * world, dReal stepsize, int maxiterations)
+{
+#ifdef TIMING
+	dTimerStart ("Island Setup");
+#endif
+	dxBody *b, *bb, **body;
+	dxJoint *j, **joint;
+
+	// nothing to do if no bodies
+	if (world->nb <= 0)
+		return;
+
+	dInternalHandleAutoDisabling (world,stepsize);
+
+	// make arrays for body and joint lists (for a single island) to go into
+	body = (dxBody **) ALLOCA (world->nb * sizeof (dxBody *));
+	joint = (dxJoint **) ALLOCA (world->nj * sizeof (dxJoint *));
+	int bcount = 0;				// number of bodies in `body'
+	int jcount = 0;				// number of joints in `joint'
+	int tbcount = 0;
+	int tjcount = 0;
+	
+	// set all body/joint tags to 0
+	for (b = world->firstbody; b; b = (dxBody *) b->next)
+		b->tag = 0;
+	for (j = world->firstjoint; j; j = (dxJoint *) j->next)
+		j->tag = 0;
+
+	// allocate a stack of unvisited bodies in the island. the maximum size of
+	// the stack can be the lesser of the number of bodies or joints, because
+	// new bodies are only ever added to the stack by going through untagged
+	// joints. all the bodies in the stack must be tagged!
+	int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
+	dxBody **stack = (dxBody **) ALLOCA (stackalloc * sizeof (dxBody *));
+	int *autostack = (int *) ALLOCA (stackalloc * sizeof (int));
+
+	for (bb = world->firstbody; bb; bb = (dxBody *) bb->next)
+	{
+#ifdef TIMING
+		dTimerNow ("Island Processing");
+#endif
+		// get bb = the next enabled, untagged body, and tag it
+		if (bb->tag || (bb->flags & dxBodyDisabled))
+			continue;
+		bb->tag = 1;
+
+		// tag all bodies and joints starting from bb.
+		int stacksize = 0;
+		int autoDepth = autoEnableDepth;
+		b = bb;
+		body[0] = bb;
+		bcount = 1;
+		jcount = 0;
+		goto quickstart;
+		while (stacksize > 0)
+		{
+			b = stack[--stacksize];	// pop body off stack
+			autoDepth = autostack[stacksize];
+			body[bcount++] = b;	// put body on body list
+		  quickstart:
+
+			// traverse and tag all body's joints, add untagged connected bodies
+			// to stack
+			for (dxJointNode * n = b->firstjoint; n; n = n->next)
+			{
+				if (!n->joint->tag)
+				{
+					int thisDepth = autoEnableDepth;
+					n->joint->tag = 1;
+					joint[jcount++] = n->joint;
+					if (n->body && !n->body->tag)
+					{
+						if (n->body->flags & dxBodyDisabled)
+							thisDepth = autoDepth - 1;
+						if (thisDepth < 0)
+							continue;
+						n->body->flags &= ~dxBodyDisabled;
+						n->body->tag = 1;
+						autostack[stacksize] = thisDepth;
+						stack[stacksize++] = n->body;
+					}
+				}
+			}
+			dIASSERT (stacksize <= world->nb);
+			dIASSERT (stacksize <= world->nj);
+		}
+
+		// now do something with body and joint lists
+		dInternalStepIslandFast (world, body, bcount, joint, jcount, stepsize, maxiterations);
+
+		// what we've just done may have altered the body/joint tag values.
+		// we must make sure that these tags are nonzero.
+		// also make sure all bodies are in the enabled state.
+		int i;
+		for (i = 0; i < bcount; i++)
+		{
+			body[i]->tag = 1;
+			body[i]->flags &= ~dxBodyDisabled;
+		}
+		for (i = 0; i < jcount; i++)
+			joint[i]->tag = 1;
+		
+		tbcount += bcount;
+		tjcount += jcount;
+	}
+	
+#ifdef TIMING
+	dMessage(0, "Total joints processed: %i, bodies: %i", tjcount, tbcount);
+#endif
+
+	// if debugging, check that all objects (except for disabled bodies,
+	// unconnected joints, and joints that are connected to disabled bodies)
+	// were tagged.
+# ifndef dNODEBUG
+	for (b = world->firstbody; b; b = (dxBody *) b->next)
+	{
+		if (b->flags & dxBodyDisabled)
+		{
+			if (b->tag)
+				dDebug (0, "disabled body tagged");
+		}
+		else
+		{
+			if (!b->tag)
+				dDebug (0, "enabled body not tagged");
+		}
+	}
+	for (j = world->firstjoint; j; j = (dxJoint *) j->next)
+	{
+		if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled) == 0) || (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled) == 0))
+		{
+			if (!j->tag)
+				dDebug (0, "attached enabled joint not tagged");
+		}
+		else
+		{
+			if (j->tag)
+				dDebug (0, "unattached or disabled joint tagged");
+		}
+	}
+# endif
+
+#	ifdef TIMING
+	dTimerEnd ();
+	dTimerReport (stdout, 1);
+#	endif
+}
+
+#endif
+
+
+void dWorldStepFast1 (dWorldID w, dReal stepsize, int maxiterations)
+{
+	dUASSERT (w, "bad world argument");
+	dUASSERT (stepsize > 0, "stepsize must be > 0");
+	processIslandsFast (w, stepsize, maxiterations);
+}
Index: /code/branches/ode/ode-0.9/ode/src/testing.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/testing.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/testing.cpp	(revision 216)
@@ -0,0 +1,243 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include <ode/config.h>
+#include <ode/misc.h>
+#include <ode/memory.h>
+#include "testing.h"
+
+#ifdef dDOUBLE
+static const dReal tol = 1.0e-9;
+#else
+static const dReal tol = 1.0e-5f;
+#endif
+
+
+// matrix header on the stack
+
+struct dMatrixComparison::dMatInfo {
+  int n,m;		// size of matrix
+  char name[128];	// name of the matrix
+  dReal *data;		// matrix data
+  int size;		// size of `data'
+};
+
+
+
+dMatrixComparison::dMatrixComparison()
+{
+  afterfirst = 0;
+  index = 0;
+}
+
+
+dMatrixComparison::~dMatrixComparison()
+{
+  reset();
+}
+
+
+dReal dMatrixComparison::nextMatrix (dReal *A, int n, int m, int lower_tri,
+				     char *name, ...)
+{
+  if (A==0 || n < 1 || m < 1 || name==0) dDebug (0,"bad args to nextMatrix");
+  int num = n*dPAD(m);
+
+  if (afterfirst==0) {
+    dMatInfo *mi = (dMatInfo*) dAlloc (sizeof(dMatInfo));
+    mi->n = n;
+    mi->m = m;
+    mi->size = num * sizeof(dReal);
+    mi->data = (dReal*) dAlloc (mi->size);
+    memcpy (mi->data,A,mi->size);
+
+    va_list ap;
+    va_start (ap,name);
+    vsprintf (mi->name,name,ap);
+    if (strlen(mi->name) >= sizeof (mi->name)) dDebug (0,"name too long");
+
+    mat.push (mi);
+    return 0;
+  }
+  else {
+    if (lower_tri && n != m)
+      dDebug (0,"dMatrixComparison, lower triangular matrix must be square");
+    if (index >= mat.size()) dDebug (0,"dMatrixComparison, too many matrices");
+    dMatInfo *mp = mat[index];
+    index++;
+
+    dMatInfo mi;
+    va_list ap;
+    va_start (ap,name);
+    vsprintf (mi.name,name,ap);
+    if (strlen(mi.name) >= sizeof (mi.name)) dDebug (0,"name too long");
+
+    if (strcmp(mp->name,mi.name) != 0)
+      dDebug (0,"dMatrixComparison, name mismatch (\"%s\" and \"%s\")",
+	      mp->name,mi.name);
+    if (mp->n != n || mp->m != m)
+      dDebug (0,"dMatrixComparison, size mismatch (%dx%d and %dx%d)",
+	      mp->n,mp->m,n,m);
+
+    dReal maxdiff;
+    if (lower_tri) {
+      maxdiff = dMaxDifferenceLowerTriangle (A,mp->data,n);
+    }
+    else {
+      maxdiff = dMaxDifference (A,mp->data,n,m);
+    }
+    if (maxdiff > tol)
+      dDebug (0,"dMatrixComparison, matrix error (size=%dx%d, name=\"%s\", "
+	      "error=%.4e)",n,m,mi.name,maxdiff);
+    return maxdiff;
+  }
+}
+
+
+void dMatrixComparison::end()
+{
+  if (mat.size() <= 0) dDebug (0,"no matrices in sequence");
+  afterfirst = 1;
+  index = 0;
+}
+
+
+void dMatrixComparison::reset()
+{
+  for (int i=0; i<mat.size(); i++) {
+    dFree (mat[i]->data,mat[i]->size);
+    dFree (mat[i],sizeof(dMatInfo));
+  }
+  mat.setSize (0);
+  afterfirst = 0;
+  index = 0;
+}
+
+
+void dMatrixComparison::dump()
+{
+  for (int i=0; i<mat.size(); i++)
+    printf ("%d: %s (%dx%d)\n",i,mat[i]->name,mat[i]->n,mat[i]->m);
+}
+
+//****************************************************************************
+// unit test
+
+#include <setjmp.h>
+
+static jmp_buf jump_buffer;
+
+static void myDebug (int num, const char *msg, va_list ap)
+{
+  // printf ("(Error %d: ",num);
+  // vprintf (msg,ap);
+  // printf (")\n");
+  longjmp (jump_buffer,1);
+}
+
+
+extern "C" ODE_API void dTestMatrixComparison()
+{
+  volatile int i;
+  printf ("dTestMatrixComparison()\n");
+  dMessageFunction *orig_debug = dGetDebugHandler();
+
+  dMatrixComparison mc;
+  dReal A[50*50];
+
+  // make first sequence
+  unsigned long seed = dRandGetSeed();
+  for (i=1; i<49; i++) {
+    dMakeRandomMatrix (A,i,i+1,1.0);
+    mc.nextMatrix (A,i,i+1,0,"A%d",i);
+  }
+  mc.end();
+
+  //mc.dump();
+
+  // test identical sequence
+  dSetDebugHandler (&myDebug);
+  dRandSetSeed (seed);
+  if (setjmp (jump_buffer)) {
+    printf ("\tFAILED (1)\n");
+  }
+  else {
+    for (i=1; i<49; i++) {
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      mc.nextMatrix (A,i,i+1,0,"A%d",i);
+    }
+    mc.end();
+    printf ("\tpassed (1)\n");
+  }
+  dSetDebugHandler (orig_debug);
+
+  // test broken sequences (with matrix error)
+  dRandSetSeed (seed);
+  volatile int passcount = 0;
+  for (i=1; i<49; i++) {
+    if (setjmp (jump_buffer)) {
+      passcount++;
+    }
+    else {
+      dSetDebugHandler (&myDebug);
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      A[(i-1)*dPAD(i+1)+i] += REAL(0.01);
+      mc.nextMatrix (A,i,i+1,0,"A%d",i);
+      dSetDebugHandler (orig_debug);
+    }
+  }
+  mc.end();
+  printf ("\t%s (2)\n",(passcount == 48) ? "passed" : "FAILED");
+
+  // test broken sequences (with name error)
+  dRandSetSeed (seed);
+  passcount = 0;
+  for (i=1; i<49; i++) {
+    if (setjmp (jump_buffer)) {
+      passcount++;
+    }
+    else {
+      dSetDebugHandler (&myDebug);
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      mc.nextMatrix (A,i,i+1,0,"B%d",i);
+      dSetDebugHandler (orig_debug);
+    }
+  }
+  mc.end();
+  printf ("\t%s (3)\n",(passcount == 48) ? "passed" : "FAILED");
+
+  // test identical sequence again
+  dSetDebugHandler (&myDebug);
+  dRandSetSeed (seed);
+  if (setjmp (jump_buffer)) {
+    printf ("\tFAILED (4)\n");
+  }
+  else {
+    for (i=1; i<49; i++) {
+      dMakeRandomMatrix (A,i,i+1,1.0);
+      mc.nextMatrix (A,i,i+1,0,"A%d",i);
+    }
+    mc.end();
+    printf ("\tpassed (4)\n");
+  }
+  dSetDebugHandler (orig_debug);
+}
Index: /code/branches/ode/ode-0.9/ode/src/testing.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/testing.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/testing.h	(revision 216)
@@ -0,0 +1,65 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/* stuff used for testing */
+
+#ifndef _ODE_TESTING_H_
+#define _ODE_TESTING_H_
+
+#include <ode/common.h>
+#include "array.h"
+
+
+// compare a sequence of named matrices/vectors, i.e. to make sure that two
+// different pieces of code are giving the same results.
+
+class dMatrixComparison {
+  struct dMatInfo;
+  dArray<dMatInfo*> mat;
+  int afterfirst,index;
+
+public:
+  dMatrixComparison();
+  ~dMatrixComparison();
+
+  dReal nextMatrix (dReal *A, int n, int m, int lower_tri, char *name, ...);
+  // add a new n*m matrix A to the sequence. the name of the matrix is given
+  // by the printf-style arguments (name,...). if this is the first sequence
+  // then this object will simply record the matrices and return 0.
+  // if this the second or subsequent sequence then this object will compare
+  // the matrices with the first sequence, and report any differences.
+  // the matrix error will be returned. if `lower_tri' is 1 then only the
+  // lower triangle of the matrix (including the diagonal) will be compared
+  // (the matrix must be square).
+
+  void end();
+  // end a sequence.
+
+  void reset();
+  // restarts the object, so the next sequence will be the first sequence.
+
+  void dump();
+  // print out info about all the matrices in the sequence
+};
+
+
+#endif
Index: /code/branches/ode/ode-0.9/ode/src/timer.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/timer.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/timer.cpp	(revision 216)
@@ -0,0 +1,421 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+TODO
+----
+
+* gettimeofday() and the pentium time stamp counter return the real time,
+  not the process time. fix this somehow!
+
+*/
+
+#include <ode/common.h>
+#include <ode/timer.h>
+
+// misc defines
+#define ALLOCA dALLOCA16
+
+//****************************************************************************
+// implementation for windows based on the multimedia performance counter.
+
+#ifdef WIN32
+
+#include "windows.h"
+
+static inline void getClockCount (unsigned long cc[2])
+{
+  LARGE_INTEGER a;
+  QueryPerformanceCounter (&a);
+  cc[0] = a.LowPart;
+  cc[1] = a.HighPart;
+}
+
+
+static inline void serialize()
+{
+}
+
+
+static inline double loadClockCount (unsigned long cc[2])
+{
+  LARGE_INTEGER a;
+  a.LowPart = cc[0];
+  a.HighPart = cc[1];
+  return double(a.QuadPart);
+}
+
+
+double dTimerResolution()
+{
+  return 1.0/dTimerTicksPerSecond();
+}
+
+
+double dTimerTicksPerSecond()
+{
+  static int query=0;
+  static double hz=0.0;
+  if (!query) {
+    LARGE_INTEGER a;
+    QueryPerformanceFrequency (&a);
+    hz = double(a.QuadPart);
+    query = 1;
+  }
+  return hz;
+}
+
+#endif
+
+//****************************************************************************
+// implementation based on the pentium time stamp counter. the timer functions
+// can be serializing or non-serializing. serializing will ensure that all
+// instructions have executed and data has been written back before the cpu
+// time stamp counter is read. the CPUID instruction is used to serialize.
+
+#if defined(PENTIUM) && !defined(WIN32)
+
+// we need to know the clock rate so that the timing function can report
+// accurate times. this number only needs to be set accurately if we're
+// doing performance tests and care about real-world time numbers - otherwise,
+// just ignore this. i have not worked out how to determine this number
+// automatically yet.
+
+#define PENTIUM_HZ (500e6)
+
+static inline void getClockCount (unsigned long cc[2])
+{
+#ifndef X86_64_SYSTEM	
+  asm volatile (
+	"rdtsc\n"
+	"movl %%eax,(%%esi)\n"
+	"movl %%edx,4(%%esi)\n"
+	: : "S" (cc) : "%eax","%edx","cc","memory");
+#else
+  asm volatile (
+	"rdtsc\n"
+	"movl %%eax,(%%rsi)\n"
+	"movl %%edx,4(%%rsi)\n"
+	: : "S" (cc) : "%eax","%edx","cc","memory");
+#endif  
+}
+
+
+static inline void serialize()
+{
+#ifndef X86_64_SYSTEM
+  asm volatile (
+	"mov $0,%%eax\n"
+	"push %%ebx\n"
+	"cpuid\n"
+	"pop %%ebx\n"
+	: : : "%eax","%ecx","%edx","cc","memory");
+#else
+  asm volatile (
+	"mov $0,%%rax\n"
+	"push %%rbx\n"
+	"cpuid\n"
+	"pop %%rbx\n"
+	: : : "%rax","%rcx","%rdx","cc","memory");
+#endif
+}
+
+
+static inline double loadClockCount (unsigned long a[2])
+{
+  double ret;
+#ifndef X86_64_SYSTEM
+  asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
+		"cc","memory");
+#else
+  asm volatile ("fildll %1; fstpl %0" : "=m" (ret) : "m" (a[0]) :
+		"cc","memory");
+#endif  
+  return ret;
+}
+
+
+double dTimerResolution()
+{
+  return 1.0/PENTIUM_HZ;
+}
+
+
+double dTimerTicksPerSecond()
+{
+  return PENTIUM_HZ;
+}
+
+#endif
+
+//****************************************************************************
+// otherwise, do the implementation based on gettimeofday().
+
+#if !defined(PENTIUM) && !defined(WIN32)
+
+#ifndef macintosh
+
+#include <sys/time.h>
+#include <unistd.h>
+
+
+static inline void getClockCount (unsigned long cc[2])
+{
+  struct timeval tv;
+  gettimeofday (&tv,0);
+  cc[0] = tv.tv_usec;
+  cc[1] = tv.tv_sec;
+}
+
+#else // macintosh
+
+#include <MacTypes.h>
+#include <Timer.h>
+
+static inline void getClockCount (unsigned long cc[2])
+{
+  UnsignedWide ms;
+  Microseconds (&ms);
+  cc[1] = ms.lo / 1000000;
+  cc[0] = ms.lo - ( cc[1] * 1000000 );
+}
+
+#endif
+
+
+static inline void serialize()
+{
+}
+
+
+static inline double loadClockCount (unsigned long a[2])
+{
+  return a[1]*1.0e6 + a[0];
+}
+
+
+double dTimerResolution()
+{
+  unsigned long cc1[2],cc2[2];
+  getClockCount (cc1);
+  do {
+    getClockCount (cc2);
+  }
+  while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
+  do {
+    getClockCount (cc1);
+  }
+  while (cc1[0]==cc2[0] && cc1[1]==cc2[1]);
+  double t1 = loadClockCount (cc1);
+  double t2 = loadClockCount (cc2);
+  return (t1-t2) / dTimerTicksPerSecond();
+}
+
+
+double dTimerTicksPerSecond()
+{
+  return 1000000;
+}
+
+#endif
+
+//****************************************************************************
+// stop watches
+
+void dStopwatchReset (dStopwatch *s)
+{
+  s->time = 0;
+  s->cc[0] = 0;
+  s->cc[1] = 0;
+}
+
+
+void dStopwatchStart (dStopwatch *s)
+{
+  serialize();
+  getClockCount (s->cc);
+}
+
+
+void dStopwatchStop  (dStopwatch *s)
+{
+  unsigned long cc[2];
+  serialize();
+  getClockCount (cc);
+  double t1 = loadClockCount (s->cc);
+  double t2 = loadClockCount (cc);
+  s->time += t2-t1;
+}
+
+
+double dStopwatchTime (dStopwatch *s)
+{
+  return s->time / dTimerTicksPerSecond();
+}
+
+//****************************************************************************
+// code timers
+
+// maximum number of events to record
+#define MAXNUM 100
+
+static int num = 0;		// number of entries used in event array
+static struct {
+  unsigned long cc[2];		// clock counts
+  double total_t;		// total clocks used in this slot.
+  double total_p;		// total percentage points used in this slot.
+  int count;			// number of times this slot has been updated.
+  char *description;		// pointer to static string
+} event[MAXNUM];
+
+
+// make sure all slot totals and counts reset to 0 at start
+
+static void initSlots()
+{
+  static int initialized=0;
+  if (!initialized) {
+    for (int i=0; i<MAXNUM; i++) {
+      event[i].count = 0;
+      event[i].total_t = 0;
+      event[i].total_p = 0;
+    }
+    initialized = 1;
+  }
+}
+
+
+void dTimerStart (const char *description)
+{
+  initSlots();
+  event[0].description = const_cast<char*> (description);
+  num = 1;
+  serialize();
+  getClockCount (event[0].cc);
+}
+
+
+void dTimerNow (const char *description)
+{
+  if (num < MAXNUM) {
+    // do not serialize
+    getClockCount (event[num].cc);
+    event[num].description = const_cast<char*> (description);
+    num++;
+  }
+}
+
+
+void dTimerEnd()
+{
+  if (num < MAXNUM) {
+    serialize();
+    getClockCount (event[num].cc);
+    event[num].description = "TOTAL";
+    num++;
+  }
+}
+
+//****************************************************************************
+// print report
+
+static void fprintDoubleWithPrefix (FILE *f, double a, char *fmt)
+{
+  if (a >= 0.999999) {
+    fprintf (f,fmt,a);
+    return;
+  }
+  a *= 1000.0;
+  if (a >= 0.999999) {
+    fprintf (f,fmt,a);
+    fprintf (f,"m");
+    return;
+  }
+  a *= 1000.0;
+  if (a >= 0.999999) {
+    fprintf (f,fmt,a);
+    fprintf (f,"u");
+    return;
+  }
+  a *= 1000.0;
+  fprintf (f,fmt,a);
+  fprintf (f,"n");
+}
+
+
+void dTimerReport (FILE *fout, int average)
+{
+  int i;
+  size_t maxl;
+  double ccunit = 1.0/dTimerTicksPerSecond();
+  fprintf (fout,"\nTimer Report (");
+  fprintDoubleWithPrefix (fout,ccunit,"%.2f ");
+  fprintf (fout,"s resolution)\n------------\n");
+  if (num < 1) return;
+
+  // get maximum description length
+  maxl = 0;
+  for (i=0; i<num; i++) {
+    size_t l = strlen (event[i].description);
+    if (l > maxl) maxl = l;
+  }
+
+  // calculate total time
+  double t1 = loadClockCount (event[0].cc);
+  double t2 = loadClockCount (event[num-1].cc);
+  double total = t2 - t1;
+  if (total <= 0) total = 1;
+
+  // compute time difference for all slots except the last one. update totals
+  double *times = (double*) ALLOCA (num * sizeof(double));
+  for (i=0; i < (num-1); i++) {
+    double t1 = loadClockCount (event[i].cc);
+    double t2 = loadClockCount (event[i+1].cc);
+    times[i] = t2 - t1;
+    event[i].count++;
+    event[i].total_t += times[i];
+    event[i].total_p += times[i]/total * 100.0;
+  }
+
+  // print report (with optional averages)
+  for (i=0; i<num; i++) {
+    double t,p;
+    if (i < (num-1)) {
+      t = times[i];
+      p = t/total * 100.0;
+    }
+    else {
+      t = total;
+      p = 100.0;
+    }
+    fprintf (fout,"%-*s %7.2fms %6.2f%%",maxl,event[i].description,
+	     t*ccunit * 1000.0, p);
+    if (average && i < (num-1)) {
+      fprintf (fout,"  (avg %7.2fms %6.2f%%)",
+	       (event[i].total_t / event[i].count)*ccunit * 1000.0,
+	       event[i].total_p / event[i].count);
+    }
+    fprintf (fout,"\n");
+  }
+  fprintf (fout,"\n");
+}
Index: /code/branches/ode/ode-0.9/ode/src/util.cpp
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/util.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/util.cpp	(revision 216)
@@ -0,0 +1,374 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#include "ode/ode.h"
+#include "objects.h"
+#include "joint.h"
+#include "util.h"
+
+#define ALLOCA dALLOCA16
+
+//****************************************************************************
+// Auto disabling
+
+void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize)
+{
+	dxBody *bb;
+	for ( bb=world->firstbody; bb; bb=(dxBody*)bb->next )
+	{
+		// don't freeze objects mid-air (patch 1586738)
+		if ( bb->firstjoint == NULL ) continue;
+
+		// nothing to do unless this body is currently enabled and has
+		// the auto-disable flag set
+		if ( (bb->flags & (dxBodyAutoDisable|dxBodyDisabled)) != dxBodyAutoDisable ) continue;
+
+		// if sampling / threshold testing is disabled, we can never sleep.
+		if ( bb->adis.average_samples == 0 ) continue;
+
+		//
+		// see if the body is idle
+		//
+		
+#ifndef dNODEBUG
+		// sanity check
+		if ( bb->average_counter >= bb->adis.average_samples )
+		{
+			dUASSERT( bb->average_counter < bb->adis.average_samples, "buffer overflow" );
+
+			// something is going wrong, reset the average-calculations
+			bb->average_ready = 0; // not ready for average calculation
+			bb->average_counter = 0; // reset the buffer index
+		}
+#endif // dNODEBUG
+
+		// sample the linear and angular velocity
+		bb->average_lvel_buffer[bb->average_counter][0] = bb->lvel[0];
+		bb->average_lvel_buffer[bb->average_counter][1] = bb->lvel[1];
+		bb->average_lvel_buffer[bb->average_counter][2] = bb->lvel[2];
+		bb->average_avel_buffer[bb->average_counter][0] = bb->avel[0];
+		bb->average_avel_buffer[bb->average_counter][1] = bb->avel[1];
+		bb->average_avel_buffer[bb->average_counter][2] = bb->avel[2];
+		bb->average_counter++;
+		
+		// buffer ready test
+		if ( bb->average_counter >= bb->adis.average_samples )
+		{
+			bb->average_counter = 0; // fill the buffer from the beginning
+			bb->average_ready = 1; // this body is ready now for average calculation
+		}
+
+		int idle = 0; // Assume it's in motion unless we have samples to disprove it.
+
+		// enough samples?
+		if ( bb->average_ready )
+		{
+			idle = 1; // Initial assumption: IDLE
+
+			// the sample buffers are filled and ready for calculation
+			dVector3 average_lvel, average_avel;
+
+			// Store first velocity samples
+			average_lvel[0] = bb->average_lvel_buffer[0][0];
+			average_avel[0] = bb->average_avel_buffer[0][0];
+			average_lvel[1] = bb->average_lvel_buffer[0][1];
+			average_avel[1] = bb->average_avel_buffer[0][1];
+			average_lvel[2] = bb->average_lvel_buffer[0][2];
+			average_avel[2] = bb->average_avel_buffer[0][2];
+			
+			// If we're not in "instantaneous mode"
+			if ( bb->adis.average_samples > 1 )
+			{
+				// add remaining velocities together
+				for ( unsigned int i = 1; i < bb->adis.average_samples; ++i )
+				{
+					average_lvel[0] += bb->average_lvel_buffer[i][0];
+					average_avel[0] += bb->average_avel_buffer[i][0];
+					average_lvel[1] += bb->average_lvel_buffer[i][1];
+					average_avel[1] += bb->average_avel_buffer[i][1];
+					average_lvel[2] += bb->average_lvel_buffer[i][2];
+					average_avel[2] += bb->average_avel_buffer[i][2];
+				}
+
+				// make average
+				dReal r1 = dReal( 1.0 ) / dReal( bb->adis.average_samples );
+
+				average_lvel[0] *= r1;
+				average_avel[0] *= r1;
+				average_lvel[1] *= r1;
+				average_avel[1] *= r1;
+				average_lvel[2] *= r1;
+				average_avel[2] *= r1;
+			}
+
+			// threshold test
+			dReal av_lspeed, av_aspeed;
+			av_lspeed = dDOT( average_lvel, average_lvel );
+			if ( av_lspeed > bb->adis.linear_average_threshold )
+			{
+				idle = 0; // average linear velocity is too high for idle
+			}
+			else
+			{
+				av_aspeed = dDOT( average_avel, average_avel );
+				if ( av_aspeed > bb->adis.angular_average_threshold )
+				{
+					idle = 0; // average angular velocity is too high for idle
+				}
+			}
+		}
+
+		// if it's idle, accumulate steps and time.
+		// these counters won't overflow because this code doesn't run for disabled bodies.
+		if (idle) {
+			bb->adis_stepsleft--;
+			bb->adis_timeleft -= stepsize;
+		}
+		else {
+			// Reset countdowns
+			bb->adis_stepsleft = bb->adis.idle_steps;
+			bb->adis_timeleft = bb->adis.idle_time;
+		}
+
+		// disable the body if it's idle for a long enough time
+		if ( bb->adis_stepsleft <= 0 && bb->adis_timeleft <= 0 )
+		{
+			bb->flags |= dxBodyDisabled; // set the disable flag
+
+			// disabling bodies should also include resetting the velocity
+			// should prevent jittering in big "islands"
+			bb->lvel[0] = 0;
+			bb->lvel[1] = 0;
+			bb->lvel[2] = 0;
+			bb->avel[0] = 0;
+			bb->avel[1] = 0;
+			bb->avel[2] = 0;
+		}
+	}
+}
+
+
+//****************************************************************************
+// body rotation
+
+// return sin(x)/x. this has a singularity at 0 so special handling is needed
+// for small arguments.
+
+static inline dReal sinc (dReal x)
+{
+  // if |x| < 1e-4 then use a taylor series expansion. this two term expansion
+  // is actually accurate to one LS bit within this range if double precision
+  // is being used - so don't worry!
+  if (dFabs(x) < 1.0e-4) return REAL(1.0) - x*x*REAL(0.166666666666666666667);
+  else return dSin(x)/x;
+}
+
+
+// given a body b, apply its linear and angular rotation over the time
+// interval h, thereby adjusting its position and orientation.
+
+void dxStepBody (dxBody *b, dReal h)
+{
+  int j;
+
+  // handle linear velocity
+  for (j=0; j<3; j++) b->posr.pos[j] += h * b->lvel[j];
+
+  if (b->flags & dxBodyFlagFiniteRotation) {
+    dVector3 irv;	// infitesimal rotation vector
+    dQuaternion q;	// quaternion for finite rotation
+
+    if (b->flags & dxBodyFlagFiniteRotationAxis) {
+      // split the angular velocity vector into a component along the finite
+      // rotation axis, and a component orthogonal to it.
+      dVector3 frv;		// finite rotation vector
+      dReal k = dDOT (b->finite_rot_axis,b->avel);
+      frv[0] = b->finite_rot_axis[0] * k;
+      frv[1] = b->finite_rot_axis[1] * k;
+      frv[2] = b->finite_rot_axis[2] * k;
+      irv[0] = b->avel[0] - frv[0];
+      irv[1] = b->avel[1] - frv[1];
+      irv[2] = b->avel[2] - frv[2];
+
+      // make a rotation quaternion q that corresponds to frv * h.
+      // compare this with the full-finite-rotation case below.
+      h *= REAL(0.5);
+      dReal theta = k * h;
+      q[0] = dCos(theta);
+      dReal s = sinc(theta) * h;
+      q[1] = frv[0] * s;
+      q[2] = frv[1] * s;
+      q[3] = frv[2] * s;
+    }
+    else {
+      // make a rotation quaternion q that corresponds to w * h
+      dReal wlen = dSqrt (b->avel[0]*b->avel[0] + b->avel[1]*b->avel[1] +
+			  b->avel[2]*b->avel[2]);
+      h *= REAL(0.5);
+      dReal theta = wlen * h;
+      q[0] = dCos(theta);
+      dReal s = sinc(theta) * h;
+      q[1] = b->avel[0] * s;
+      q[2] = b->avel[1] * s;
+      q[3] = b->avel[2] * s;
+    }
+
+    // do the finite rotation
+    dQuaternion q2;
+    dQMultiply0 (q2,q,b->q);
+    for (j=0; j<4; j++) b->q[j] = q2[j];
+
+    // do the infitesimal rotation if required
+    if (b->flags & dxBodyFlagFiniteRotationAxis) {
+      dReal dq[4];
+      dWtoDQ (irv,b->q,dq);
+      for (j=0; j<4; j++) b->q[j] += h * dq[j];
+    }
+  }
+  else {
+    // the normal way - do an infitesimal rotation
+    dReal dq[4];
+    dWtoDQ (b->avel,b->q,dq);
+    for (j=0; j<4; j++) b->q[j] += h * dq[j];
+  }
+
+  // normalize the quaternion and convert it to a rotation matrix
+  dNormalize4 (b->q);
+  dQtoR (b->q,b->posr.R);
+
+  // notify all attached geoms that this body has moved
+  for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
+    dGeomMoved (geom);
+}
+
+//****************************************************************************
+// island processing
+
+// this groups all joints and bodies in a world into islands. all objects
+// in an island are reachable by going through connected bodies and joints.
+// each island can be simulated separately.
+// note that joints that are not attached to anything will not be included
+// in any island, an so they do not affect the simulation.
+//
+// this function starts new island from unvisited bodies. however, it will
+// never start a new islands from a disabled body. thus islands of disabled
+// bodies will not be included in the simulation. disabled bodies are
+// re-enabled if they are found to be part of an active island.
+
+void dxProcessIslands (dxWorld *world, dReal stepsize, dstepper_fn_t stepper)
+{
+  dxBody *b,*bb,**body;
+  dxJoint *j,**joint;
+
+  // nothing to do if no bodies
+  if (world->nb <= 0) return;
+
+  // handle auto-disabling of bodies
+  dInternalHandleAutoDisabling (world,stepsize);
+
+  // make arrays for body and joint lists (for a single island) to go into
+  body = (dxBody**) ALLOCA (world->nb * sizeof(dxBody*));
+  joint = (dxJoint**) ALLOCA (world->nj * sizeof(dxJoint*));
+  int bcount = 0;	// number of bodies in `body'
+  int jcount = 0;	// number of joints in `joint'
+
+  // set all body/joint tags to 0
+  for (b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0;
+  for (j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0;
+
+  // allocate a stack of unvisited bodies in the island. the maximum size of
+  // the stack can be the lesser of the number of bodies or joints, because
+  // new bodies are only ever added to the stack by going through untagged
+  // joints. all the bodies in the stack must be tagged!
+  int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
+  dxBody **stack = (dxBody**) ALLOCA (stackalloc * sizeof(dxBody*));
+
+  for (bb=world->firstbody; bb; bb=(dxBody*)bb->next) {
+    // get bb = the next enabled, untagged body, and tag it
+    if (bb->tag || (bb->flags & dxBodyDisabled)) continue;
+    bb->tag = 1;
+
+    // tag all bodies and joints starting from bb.
+    int stacksize = 0;
+    b = bb;
+    body[0] = bb;
+    bcount = 1;
+    jcount = 0;
+    goto quickstart;
+    while (stacksize > 0) {
+      b = stack[--stacksize];	// pop body off stack
+      body[bcount++] = b;	// put body on body list
+      quickstart:
+
+      // traverse and tag all body's joints, add untagged connected bodies
+      // to stack
+      for (dxJointNode *n=b->firstjoint; n; n=n->next) {
+	if (!n->joint->tag) {
+	  n->joint->tag = 1;
+	  joint[jcount++] = n->joint;
+	  if (n->body && !n->body->tag) {
+	    n->body->tag = 1;
+	    stack[stacksize++] = n->body;
+	  }
+	}
+      }
+      dIASSERT(stacksize <= world->nb);
+      dIASSERT(stacksize <= world->nj);
+    }
+
+    // now do something with body and joint lists
+    stepper (world,body,bcount,joint,jcount,stepsize);
+
+    // what we've just done may have altered the body/joint tag values.
+    // we must make sure that these tags are nonzero.
+    // also make sure all bodies are in the enabled state.
+    int i;
+    for (i=0; i<bcount; i++) {
+      body[i]->tag = 1;
+      body[i]->flags &= ~dxBodyDisabled;
+    }
+    for (i=0; i<jcount; i++) joint[i]->tag = 1;
+  }
+
+  // if debugging, check that all objects (except for disabled bodies,
+  // unconnected joints, and joints that are connected to disabled bodies)
+  // were tagged.
+# ifndef dNODEBUG
+  for (b=world->firstbody; b; b=(dxBody*)b->next) {
+    if (b->flags & dxBodyDisabled) {
+      if (b->tag) dDebug (0,"disabled body tagged");
+    }
+    else {
+      if (!b->tag) dDebug (0,"enabled body not tagged");
+    }
+  }
+  for (j=world->firstjoint; j; j=(dxJoint*)j->next) {
+    if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0) ||
+	(j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0)) {
+      if (!j->tag) dDebug (0,"attached enabled joint not tagged");
+    }
+    else {
+      if (j->tag) dDebug (0,"unattached or disabled joint tagged");
+    }
+  }
+# endif
+}
Index: /code/branches/ode/ode-0.9/ode/src/util.h
===================================================================
--- /code/branches/ode/ode-0.9/ode/src/util.h	(revision 216)
+++ /code/branches/ode/ode-0.9/ode/src/util.h	(revision 216)
@@ -0,0 +1,38 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of EITHER:                                  *
+ *   (1) The GNU Lesser General Public License as published by the Free  *
+ *       Software Foundation; either version 2.1 of the License, or (at  *
+ *       your option) any later version. The text of the GNU Lesser      *
+ *       General Public License is included with this library in the     *
+ *       file LICENSE.TXT.                                               *
+ *   (2) The BSD-style license that is included with this library in     *
+ *       the file LICENSE-BSD.TXT.                                       *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+#ifndef _ODE_UTIL_H_
+#define _ODE_UTIL_H_
+
+#include "objects.h"
+
+
+void dInternalHandleAutoDisabling (dxWorld *world, dReal stepsize);
+void dxStepBody (dxBody *b, dReal h);
+
+typedef void (*dstepper_fn_t) (dxWorld *world, dxBody * const *body, int nb,
+        dxJoint * const *_joint, int nj, dReal stepsize);
+
+void dxProcessIslands (dxWorld *world, dReal stepsize, dstepper_fn_t stepper);
+
+
+#endif
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/CheckMacros.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/CheckMacros.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/CheckMacros.h	(revision 216)
@@ -0,0 +1,27 @@
+#ifndef CHECK_MACROS_H
+#define CHECK_MACROS_H
+
+#include "Checks.h"
+
+#define CHECK(value) \
+	if (!CppTestHarness::Check(value)) \
+		testResults_.ReportFailure(__FILE__, __LINE__, #value);
+
+#define CHECK_EQUAL(actual, expected) \
+	if (!CppTestHarness::CheckEqual(actual, expected)) \
+		testResults_.ReportFailure(__FILE__, __LINE__, CppTestHarness::BuildFailureString(expected, actual));
+
+#define CHECK_CLOSE(actual, expected, tolerance) \
+	if (!CppTestHarness::CheckClose(actual, expected, tolerance)) \
+		testResults_.ReportFailure(__FILE__, __LINE__, CppTestHarness::BuildFailureString(expected, actual));
+
+#define CHECK_ARRAY_EQUAL(actual, expected, count) \
+	if (!CppTestHarness::CheckArrayEqual(actual, expected, count)) \
+		testResults_.ReportFailure(__FILE__, __LINE__, CppTestHarness::BuildFailureString(expected, actual, count));
+
+#define CHECK_ARRAY_CLOSE(actual, expected, count, tolerance) \
+	if (!CppTestHarness::CheckArrayClose(actual, expected, count, tolerance)) \
+		testResults_.ReportFailure(__FILE__, __LINE__, CppTestHarness::BuildFailureString(expected, actual, count));
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/Checks.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/Checks.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/Checks.h	(revision 216)
@@ -0,0 +1,97 @@
+#ifndef CHECKS_H
+#define CHECKS_H
+
+#include <sstream>
+#include <cmath>
+
+namespace CppTestHarness
+{
+	template< typename Value >
+	bool Check(Value const value)
+	{
+#ifdef _MSC_VER
+#	pragma warning(push)
+#	pragma warning(disable:4127) // conditional expression is constant
+#	pragma warning(disable:4800) // forcing value to bool true/false, performance warning
+#endif
+		return value;
+#ifdef _MSC_VER
+#	pragma warning(pop)
+#endif
+	}
+
+	template< typename Actual, typename Expected >
+	bool CheckEqual(Actual const actual, Expected const expected)
+	{
+#ifdef _MSC_VER
+#	pragma warning(push)
+#	pragma warning(disable:4127) // conditional expression is constant
+#endif
+		return (actual == expected);
+#ifdef _MSC_VER
+#	pragma warning(pop)
+#endif
+	}
+
+	template< typename Actual, typename Expected >
+	bool CheckArrayEqual(Actual const actual, Expected const expected, int const count)
+	{
+		for (int i = 0; i < count; ++i)
+		{
+			if (!(actual[i] == expected[i]))
+				return false;
+		}
+
+		return true;
+	}
+
+	template< typename Actual, typename Expected, typename Tolerance >
+	bool CheckClose(Actual const actual, Expected const expected, Tolerance const tolerance)
+	{
+		return (std::abs(double(actual) - double(expected)) <= double(tolerance));
+	}
+
+	template< typename Actual, typename Expected, typename Tolerance >
+	bool CheckArrayClose(Actual const actual, Expected const expected, int const count, Tolerance const tolerance)
+	{
+		for (int i = 0; i < count; ++i)
+		{
+			if (!CheckClose(actual[i], expected[i], tolerance))
+				return false;
+		}
+
+		return true;
+	}
+
+	template< typename Actual, typename Expected >
+	std::string BuildFailureString(Actual const actual, Expected const expected)
+	{
+		std::stringstream failureStr;
+		failureStr << "Expected " << actual << " but got " << expected << std::endl;
+		return failureStr.str();
+	}
+
+	template< typename Actual, typename Expected >
+	std::string BuildFailureString(Actual const* actual, Expected const* expected, int const count)
+	{
+		std::stringstream failureStr;
+		int i;
+		
+		failureStr << "Expected [ ";
+
+		for (i = 0; i < count; ++i)
+			failureStr << expected[i] << ' ';
+
+		failureStr << "] but got [ ";
+
+		for (i = 0; i < count; ++i)
+			failureStr << expected[i] << ' ';
+
+		failureStr << ']' << std::endl;
+
+        return failureStr.str();		
+	}
+}
+
+#endif 
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.h	(revision 216)
@@ -0,0 +1,14 @@
+#ifndef TEST_HARNESS_H
+#define TEST_HARNESS_H
+
+#include "Test.h"
+#include "TypedTestLauncher.h"
+#include "TestResults.h"
+
+#include "TestMacros.h"
+#include "CheckMacros.h"
+
+#include "TestRunner.h"
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.sln
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.sln	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.sln	(revision 216)
@@ -0,0 +1,28 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppTestHarness", "CppTestHarness.vcproj", "{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCppTestHarness", "TestCppTestHarness\TestCppTestHarness.vcproj", "{639DCE9E-BB6F-4A3E-9DC1-43A4EA9BAA61}"
+	ProjectSection(ProjectDependencies) = postProject
+		{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0} = {BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}.Debug|Win32.ActiveCfg = Debug|Win32
+		{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}.Debug|Win32.Build.0 = Debug|Win32
+		{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}.Release|Win32.ActiveCfg = Release|Win32
+		{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}.Release|Win32.Build.0 = Release|Win32
+		{639DCE9E-BB6F-4A3E-9DC1-43A4EA9BAA61}.Debug|Win32.ActiveCfg = Debug|Win32
+		{639DCE9E-BB6F-4A3E-9DC1-43A4EA9BAA61}.Debug|Win32.Build.0 = Debug|Win32
+		{639DCE9E-BB6F-4A3E-9DC1-43A4EA9BAA61}.Release|Win32.ActiveCfg = Release|Win32
+		{639DCE9E-BB6F-4A3E-9DC1-43A4EA9BAA61}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.vcproj
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.vcproj	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/CppTestHarness.vcproj	(revision 216)
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="CppTestHarness"
+	ProjectGUID="{BFA21FB6-8FF9-4B44-ACB3-FC57CEA663D0}"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/CppTestHarness.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+				ExceptionHandling="2"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/CppTestHarness.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\CheckMacros.h"
+			>
+		</File>
+		<File
+			RelativePath=".\Checks.h"
+			>
+		</File>
+		<File
+			RelativePath=".\CppTestHarness.h"
+			>
+		</File>
+		<File
+			RelativePath=".\HTMLTestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\HTMLTestReporter.h"
+			>
+		</File>
+		<File
+			RelativePath=".\PrintfTestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\PrintfTestReporter.h"
+			>
+		</File>
+		<File
+			RelativePath=".\Test.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\Test.h"
+			>
+		</File>
+		<File
+			RelativePath=".\TestLauncher.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\TestLauncher.h"
+			>
+		</File>
+		<File
+			RelativePath=".\TestMacros.h"
+			>
+		</File>
+		<File
+			RelativePath=".\TestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\TestReporter.h"
+			>
+		</File>
+		<File
+			RelativePath=".\TestResults.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\TestResults.h"
+			>
+		</File>
+		<File
+			RelativePath=".\TestRunner.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\TestRunner.h"
+			>
+		</File>
+		<File
+			RelativePath=".\TypedTestLauncher.h"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/HTMLTestReporter.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/HTMLTestReporter.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/HTMLTestReporter.cpp	(revision 216)
@@ -0,0 +1,87 @@
+#include "HTMLTestReporter.h"
+
+#ifdef _MSC_VER
+#    pragma warning(disable:4996) // shut the secure crt stuff up, ctime is used correctly here.
+#endif
+
+#include <iostream>
+#include <ctime>
+#include <sstream>
+
+namespace CppTestHarness
+{
+
+void HTMLTestReporter::ReportFailure(char const* file, int const line, std::string const failure)
+{
+	std::stringstream msg;
+	msg << file << "(" << line << ") : " << failure;
+
+	m_failureMessages.push_back(msg.str());
+}
+
+void HTMLTestReporter::ReportSingleResult(const std::string& testName, bool failed)
+{
+	ResultRecord r;
+	r.testName = testName;
+	r.failed = failed;
+
+	//get reported failures and clear temp list
+	r.failureMessages = m_failureMessages;	
+	m_failureMessages.clear();
+
+	m_results.push_back(r);
+}
+
+void HTMLTestReporter::ReportSummary(int const testCount, int const failureCount)
+{
+	std::ostream& os = std::cout;
+
+	//TODO: make all strings html safe
+	os << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">";
+	os << "<html>\n";
+	os << "<head>\n";
+	os << "    <title>Test Report</title>\n";
+	os << "</head>\n";
+	os << "<body text=\"black\" bgcolor=\"white\">\n";
+
+	std::time_t currtime;
+	std::time(&currtime);
+
+	os << "<h1>Test Report: " << std::ctime(&currtime) << "</h1>\n";
+	os << "<p><em>";
+	os << testCount << " tests run.<br />\n";
+	os << failureCount << " failed.<br />\n";
+	os << "</em></p>";
+
+	os << "<table border=1 bgcolor=\"#dddddd\">";
+
+	//for each single test
+	for (ResultList::iterator i = m_results.begin(); i != m_results.end(); ++i)
+	{
+		os << "<tr>";
+		os << "<td><strong>" << i->testName << "</strong></td>";
+		
+		if (i->failed)
+			os << "<td bgcolor=\"#ff0000\"><strong>FAILED</strong></td>";
+		else
+			os << "<td bgcolor=\"#00ee00\"><strong>PASSED</strong></td>";
+
+		os << "</tr><tr><td>";
+		if (i->failed) os << "<ul>";
+
+		for (MessageList::iterator j = i->failureMessages.begin(); j != i->failureMessages.end(); ++j)
+		{
+			os << "<li><code>"<< *j << "</code></li>\n";
+		}
+
+		if (i->failed) os << "</ul>";
+		os << "</td></tr>";
+	}
+
+	os << "</table>";
+	os << "</body>";
+	os << "</html>";
+}
+
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/HTMLTestReporter.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/HTMLTestReporter.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/HTMLTestReporter.h	(revision 216)
@@ -0,0 +1,36 @@
+#ifndef HTML_TEST_REPORTER
+#define HTML_TEST_REPORTER
+
+#include "TestReporter.h"
+#include <vector>
+
+namespace CppTestHarness
+{
+
+class HTMLTestReporter : public TestReporter
+{
+public:
+	virtual void ReportFailure(char const* file, int line, std::string failure);
+	virtual void ReportSingleResult(const std::string& testName, bool failed);
+	virtual void ReportSummary(int testCount, int failureCount);
+
+private:
+	typedef std::vector<std::string> MessageList;
+
+	struct ResultRecord 
+	{
+		std::string testName;
+		bool failed;
+		MessageList failureMessages;
+	};
+
+	MessageList m_failureMessages;
+
+	typedef std::vector<ResultRecord> ResultList;
+	ResultList m_results;
+};
+
+}
+
+#endif //HTML_TEST_REPORTER
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/Makefile.am	(revision 216)
@@ -0,0 +1,28 @@
+
+noinst_LIBRARIES = libodetest.a
+
+libodetest_a_SOURCES = \
+  CheckMacros.h \
+  Checks.h \
+  CppTestHarness.h \
+  HTMLTestReporter.cpp \
+  HTMLTestReporter.h \
+  PrintfTestReporter.cpp \
+  PrintfTestReporter.h \
+  SignalTranslator.h \
+  Test.cpp \
+  Test.h \
+  TestLauncher.cpp \
+  TestLauncher.h \
+  TestMacros.h \
+  TestReporter.cpp \
+  TestReporter.h \
+  TestResults.cpp \
+  TestResults.h \
+  TestRunner.cpp \
+  TestRunner.h \
+  TypedTestLauncher.h
+
+libodetest_a_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/Makefile.in	(revision 216)
@@ -0,0 +1,562 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = tests/CppTestHarness
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libodetest_a_AR = $(AR) $(ARFLAGS)
+libodetest_a_LIBADD =
+am_libodetest_a_OBJECTS = libodetest_a-HTMLTestReporter.$(OBJEXT) \
+	libodetest_a-PrintfTestReporter.$(OBJEXT) \
+	libodetest_a-Test.$(OBJEXT) \
+	libodetest_a-TestLauncher.$(OBJEXT) \
+	libodetest_a-TestReporter.$(OBJEXT) \
+	libodetest_a-TestResults.$(OBJEXT) \
+	libodetest_a-TestRunner.$(OBJEXT)
+libodetest_a_OBJECTS = $(am_libodetest_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libodetest_a_SOURCES)
+DIST_SOURCES = $(libodetest_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libodetest.a
+libodetest_a_SOURCES = \
+  CheckMacros.h \
+  Checks.h \
+  CppTestHarness.h \
+  HTMLTestReporter.cpp \
+  HTMLTestReporter.h \
+  PrintfTestReporter.cpp \
+  PrintfTestReporter.h \
+  SignalTranslator.h \
+  Test.cpp \
+  Test.h \
+  TestLauncher.cpp \
+  TestLauncher.h \
+  TestMacros.h \
+  TestReporter.cpp \
+  TestReporter.h \
+  TestResults.cpp \
+  TestResults.h \
+  TestRunner.cpp \
+  TestRunner.h \
+  TypedTestLauncher.h
+
+libodetest_a_CXXFLAGS = @ARCHFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  tests/CppTestHarness/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  tests/CppTestHarness/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libodetest.a: $(libodetest_a_OBJECTS) $(libodetest_a_DEPENDENCIES) 
+	-rm -f libodetest.a
+	$(libodetest_a_AR) libodetest.a $(libodetest_a_OBJECTS) $(libodetest_a_LIBADD)
+	$(RANLIB) libodetest.a
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-HTMLTestReporter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-PrintfTestReporter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-Test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-TestLauncher.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-TestReporter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-TestResults.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libodetest_a-TestRunner.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libodetest_a-HTMLTestReporter.o: HTMLTestReporter.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-HTMLTestReporter.o -MD -MP -MF $(DEPDIR)/libodetest_a-HTMLTestReporter.Tpo -c -o libodetest_a-HTMLTestReporter.o `test -f 'HTMLTestReporter.cpp' || echo '$(srcdir)/'`HTMLTestReporter.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-HTMLTestReporter.Tpo $(DEPDIR)/libodetest_a-HTMLTestReporter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='HTMLTestReporter.cpp' object='libodetest_a-HTMLTestReporter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-HTMLTestReporter.o `test -f 'HTMLTestReporter.cpp' || echo '$(srcdir)/'`HTMLTestReporter.cpp
+
+libodetest_a-HTMLTestReporter.obj: HTMLTestReporter.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-HTMLTestReporter.obj -MD -MP -MF $(DEPDIR)/libodetest_a-HTMLTestReporter.Tpo -c -o libodetest_a-HTMLTestReporter.obj `if test -f 'HTMLTestReporter.cpp'; then $(CYGPATH_W) 'HTMLTestReporter.cpp'; else $(CYGPATH_W) '$(srcdir)/HTMLTestReporter.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-HTMLTestReporter.Tpo $(DEPDIR)/libodetest_a-HTMLTestReporter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='HTMLTestReporter.cpp' object='libodetest_a-HTMLTestReporter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-HTMLTestReporter.obj `if test -f 'HTMLTestReporter.cpp'; then $(CYGPATH_W) 'HTMLTestReporter.cpp'; else $(CYGPATH_W) '$(srcdir)/HTMLTestReporter.cpp'; fi`
+
+libodetest_a-PrintfTestReporter.o: PrintfTestReporter.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-PrintfTestReporter.o -MD -MP -MF $(DEPDIR)/libodetest_a-PrintfTestReporter.Tpo -c -o libodetest_a-PrintfTestReporter.o `test -f 'PrintfTestReporter.cpp' || echo '$(srcdir)/'`PrintfTestReporter.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-PrintfTestReporter.Tpo $(DEPDIR)/libodetest_a-PrintfTestReporter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='PrintfTestReporter.cpp' object='libodetest_a-PrintfTestReporter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-PrintfTestReporter.o `test -f 'PrintfTestReporter.cpp' || echo '$(srcdir)/'`PrintfTestReporter.cpp
+
+libodetest_a-PrintfTestReporter.obj: PrintfTestReporter.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-PrintfTestReporter.obj -MD -MP -MF $(DEPDIR)/libodetest_a-PrintfTestReporter.Tpo -c -o libodetest_a-PrintfTestReporter.obj `if test -f 'PrintfTestReporter.cpp'; then $(CYGPATH_W) 'PrintfTestReporter.cpp'; else $(CYGPATH_W) '$(srcdir)/PrintfTestReporter.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-PrintfTestReporter.Tpo $(DEPDIR)/libodetest_a-PrintfTestReporter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='PrintfTestReporter.cpp' object='libodetest_a-PrintfTestReporter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-PrintfTestReporter.obj `if test -f 'PrintfTestReporter.cpp'; then $(CYGPATH_W) 'PrintfTestReporter.cpp'; else $(CYGPATH_W) '$(srcdir)/PrintfTestReporter.cpp'; fi`
+
+libodetest_a-Test.o: Test.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-Test.o -MD -MP -MF $(DEPDIR)/libodetest_a-Test.Tpo -c -o libodetest_a-Test.o `test -f 'Test.cpp' || echo '$(srcdir)/'`Test.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-Test.Tpo $(DEPDIR)/libodetest_a-Test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='Test.cpp' object='libodetest_a-Test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-Test.o `test -f 'Test.cpp' || echo '$(srcdir)/'`Test.cpp
+
+libodetest_a-Test.obj: Test.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-Test.obj -MD -MP -MF $(DEPDIR)/libodetest_a-Test.Tpo -c -o libodetest_a-Test.obj `if test -f 'Test.cpp'; then $(CYGPATH_W) 'Test.cpp'; else $(CYGPATH_W) '$(srcdir)/Test.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-Test.Tpo $(DEPDIR)/libodetest_a-Test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='Test.cpp' object='libodetest_a-Test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-Test.obj `if test -f 'Test.cpp'; then $(CYGPATH_W) 'Test.cpp'; else $(CYGPATH_W) '$(srcdir)/Test.cpp'; fi`
+
+libodetest_a-TestLauncher.o: TestLauncher.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestLauncher.o -MD -MP -MF $(DEPDIR)/libodetest_a-TestLauncher.Tpo -c -o libodetest_a-TestLauncher.o `test -f 'TestLauncher.cpp' || echo '$(srcdir)/'`TestLauncher.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestLauncher.Tpo $(DEPDIR)/libodetest_a-TestLauncher.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestLauncher.cpp' object='libodetest_a-TestLauncher.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestLauncher.o `test -f 'TestLauncher.cpp' || echo '$(srcdir)/'`TestLauncher.cpp
+
+libodetest_a-TestLauncher.obj: TestLauncher.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestLauncher.obj -MD -MP -MF $(DEPDIR)/libodetest_a-TestLauncher.Tpo -c -o libodetest_a-TestLauncher.obj `if test -f 'TestLauncher.cpp'; then $(CYGPATH_W) 'TestLauncher.cpp'; else $(CYGPATH_W) '$(srcdir)/TestLauncher.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestLauncher.Tpo $(DEPDIR)/libodetest_a-TestLauncher.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestLauncher.cpp' object='libodetest_a-TestLauncher.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestLauncher.obj `if test -f 'TestLauncher.cpp'; then $(CYGPATH_W) 'TestLauncher.cpp'; else $(CYGPATH_W) '$(srcdir)/TestLauncher.cpp'; fi`
+
+libodetest_a-TestReporter.o: TestReporter.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestReporter.o -MD -MP -MF $(DEPDIR)/libodetest_a-TestReporter.Tpo -c -o libodetest_a-TestReporter.o `test -f 'TestReporter.cpp' || echo '$(srcdir)/'`TestReporter.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestReporter.Tpo $(DEPDIR)/libodetest_a-TestReporter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestReporter.cpp' object='libodetest_a-TestReporter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestReporter.o `test -f 'TestReporter.cpp' || echo '$(srcdir)/'`TestReporter.cpp
+
+libodetest_a-TestReporter.obj: TestReporter.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestReporter.obj -MD -MP -MF $(DEPDIR)/libodetest_a-TestReporter.Tpo -c -o libodetest_a-TestReporter.obj `if test -f 'TestReporter.cpp'; then $(CYGPATH_W) 'TestReporter.cpp'; else $(CYGPATH_W) '$(srcdir)/TestReporter.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestReporter.Tpo $(DEPDIR)/libodetest_a-TestReporter.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestReporter.cpp' object='libodetest_a-TestReporter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestReporter.obj `if test -f 'TestReporter.cpp'; then $(CYGPATH_W) 'TestReporter.cpp'; else $(CYGPATH_W) '$(srcdir)/TestReporter.cpp'; fi`
+
+libodetest_a-TestResults.o: TestResults.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestResults.o -MD -MP -MF $(DEPDIR)/libodetest_a-TestResults.Tpo -c -o libodetest_a-TestResults.o `test -f 'TestResults.cpp' || echo '$(srcdir)/'`TestResults.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestResults.Tpo $(DEPDIR)/libodetest_a-TestResults.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestResults.cpp' object='libodetest_a-TestResults.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestResults.o `test -f 'TestResults.cpp' || echo '$(srcdir)/'`TestResults.cpp
+
+libodetest_a-TestResults.obj: TestResults.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestResults.obj -MD -MP -MF $(DEPDIR)/libodetest_a-TestResults.Tpo -c -o libodetest_a-TestResults.obj `if test -f 'TestResults.cpp'; then $(CYGPATH_W) 'TestResults.cpp'; else $(CYGPATH_W) '$(srcdir)/TestResults.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestResults.Tpo $(DEPDIR)/libodetest_a-TestResults.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestResults.cpp' object='libodetest_a-TestResults.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestResults.obj `if test -f 'TestResults.cpp'; then $(CYGPATH_W) 'TestResults.cpp'; else $(CYGPATH_W) '$(srcdir)/TestResults.cpp'; fi`
+
+libodetest_a-TestRunner.o: TestRunner.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestRunner.o -MD -MP -MF $(DEPDIR)/libodetest_a-TestRunner.Tpo -c -o libodetest_a-TestRunner.o `test -f 'TestRunner.cpp' || echo '$(srcdir)/'`TestRunner.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestRunner.Tpo $(DEPDIR)/libodetest_a-TestRunner.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestRunner.cpp' object='libodetest_a-TestRunner.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestRunner.o `test -f 'TestRunner.cpp' || echo '$(srcdir)/'`TestRunner.cpp
+
+libodetest_a-TestRunner.obj: TestRunner.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -MT libodetest_a-TestRunner.obj -MD -MP -MF $(DEPDIR)/libodetest_a-TestRunner.Tpo -c -o libodetest_a-TestRunner.obj `if test -f 'TestRunner.cpp'; then $(CYGPATH_W) 'TestRunner.cpp'; else $(CYGPATH_W) '$(srcdir)/TestRunner.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/libodetest_a-TestRunner.Tpo $(DEPDIR)/libodetest_a-TestRunner.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='TestRunner.cpp' object='libodetest_a-TestRunner.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libodetest_a_CXXFLAGS) $(CXXFLAGS) -c -o libodetest_a-TestRunner.obj `if test -f 'TestRunner.cpp'; then $(CYGPATH_W) 'TestRunner.cpp'; else $(CYGPATH_W) '$(srcdir)/TestRunner.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstLIBRARIES ctags distclean distclean-compile \
+	distclean-generic distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/PrintfTestReporter.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/PrintfTestReporter.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/PrintfTestReporter.cpp	(revision 216)
@@ -0,0 +1,25 @@
+#include "PrintfTestReporter.h"
+
+#include <cstdio>
+
+namespace CppTestHarness
+{
+
+void PrintfTestReporter::ReportFailure(char const* file, int const line, std::string const failure)
+{
+	printf("%s(%d) : failure: %s\n", file, line, failure.c_str());
+}
+
+void PrintfTestReporter::ReportSingleResult(const std::string& /*testName*/, bool /*failed*/)
+{
+	//empty
+}
+
+void PrintfTestReporter::ReportSummary(int const testCount, int const failureCount)
+{
+	printf("%d tests run.\n", testCount);
+	printf("%d failures.\n", failureCount);
+}
+
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/PrintfTestReporter.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/PrintfTestReporter.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/PrintfTestReporter.h	(revision 216)
@@ -0,0 +1,20 @@
+#ifndef PRINTF_TEST_REPORTER
+#define PRINTF_TEST_REPORTER
+
+#include "TestReporter.h"
+
+namespace CppTestHarness
+{
+
+class PrintfTestReporter : public TestReporter
+{
+private:
+	virtual void ReportFailure(char const* file, int line, std::string failure);
+	virtual void ReportSingleResult(const std::string& testName, bool failed);
+	virtual void ReportSummary(int testCount, int failureCount);
+};
+
+}
+
+#endif 
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/ReadMe.txt
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/ReadMe.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/ReadMe.txt	(revision 216)
@@ -0,0 +1,34 @@
+------------------------------------------------------------------------
+CppTestHarness
+
+written by Charles Nicholson (cn@cnicholson.net).
+linux/gcc port by Dan Lind (podcat@gmail.com).
+
+This work is based on CppUnitLite by Michael Feathers with changes inspired by Noel Llopis.
+
+You the user have free license to do whatever you want with this source code.
+No persons mentioned above accept any responsibility if files in this archive 
+set your computer on fire or subject you to any number of woes. Use at your own risk!
+
+
+
+HISTORY:
+------------------------------------------------------------------------
+28 dec 2005, charles nicholson (cn@cnicholson.net)
+- upgraded win32 build to VS.NET 2005
+- silenced all 'conditional expression is constant' warning (CHECK(true), CHECK_EQUAL(1,1), etc...)
+
+20 dec 2005, dan lind (podcat@gmail.com)
+- added signal-to-exception translator for posix systems
+- more methods in TestReporter. We can now optionaly have output on each finished test
+    HTMLTestReporter illustrates a fairly complex reporter doing this.
+
+13 dec 2005, dan lind (podcat@gmail.com)
+- added newlines at the end of all files (this is a warning on gcc)
+- reordered initialization list of TestRunner (init order not same as order in class)
+- added _MSC_VER to TestCppTestHarness.cpp to block pragmas from gcc
+
+11 dec 2005, charles nicholson (cn@cnicholson.net)
+- get rid of TestRegistry and static std::vector.
+- TestRunner holds a PrintfTestReporter by value to avoid dynamic allocation at static-init
+- TestCreator -> TestLauncher are now nodes in a linked list of tests.
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/SignalTranslator.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/SignalTranslator.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/SignalTranslator.h	(revision 216)
@@ -0,0 +1,53 @@
+#ifndef SIGNAL_TRANSLATOR_H
+#define SIGNAL_TRANSLATOR_H
+
+#include <signal.h>
+#include <setjmp.h>
+
+namespace CppTestHarness
+{
+
+template <int SIGNAL>
+class SignalTranslator {
+public:
+	SignalTranslator()
+	{
+		//setup new signal handler
+		struct sigaction act;
+		act.sa_handler = signalHandler;
+		sigemptyset(&act.sa_mask);
+		act.sa_flags = 0;
+
+		sigaction(SIGNAL, &act, &m_oldAction);
+
+		if (sigsetjmp(getJumpPoint(), 1) != 0)
+		{
+			//if signal thrown we will return here from handler
+			throw "Unhandled system exception";
+		}
+	}
+
+	~SignalTranslator()
+	{
+		sigaction(SIGNAL, &m_oldAction, 0);
+	}
+
+private:
+	static void signalHandler(int signum)
+	{
+		siglongjmp(getJumpPoint(), signum);
+	}
+
+		static sigjmp_buf& getJumpPoint()
+		{
+			static sigjmp_buf jmpPnt;
+			return jmpPnt;
+		}
+
+	struct sigaction m_oldAction;
+};
+
+} //CppTestHarness
+
+#endif //SIGNAL_TRANSLATOR_H
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/Test.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/Test.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/Test.cpp	(revision 216)
@@ -0,0 +1,49 @@
+#include "Test.h"
+#include "TestResults.h"
+
+#ifdef TRANSLATE_POSIX_SIGNALS
+	#include "SignalTranslator.h"
+#endif
+
+namespace CppTestHarness
+{
+
+Test::Test(std::string const testName, std::string const filename, int const lineNumber)
+	: m_testName(testName)
+	, m_filename(filename)
+	, m_lineNumber(lineNumber)
+{
+}
+
+Test::~Test()
+{
+}
+
+void Test::Run(TestResults& testResults)
+{
+	try
+	{
+#ifdef TRANSLATE_POSIX_SIGNALS
+		//add any signals you want translated into system exceptions here
+		SignalTranslator<SIGSEGV> sigSEGV;
+		SignalTranslator<SIGFPE> sigFPE;
+		SignalTranslator<SIGBUS> sigBUS;
+#endif
+		RunImpl(testResults);
+	}
+	catch (std::exception const& e)
+	{
+		std::string msg = "Unhandled exception: ";
+		msg += e.what();
+		testResults.ReportFailure(m_filename.c_str(), m_lineNumber, msg);
+	}
+	catch (...)
+	{
+		testResults.ReportFailure(m_filename.c_str(), m_lineNumber, "Unhandled exception: crash!");
+	}
+
+
+	testResults.ReportDone(m_testName);
+}
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/Test.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/Test.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/Test.h	(revision 216)
@@ -0,0 +1,40 @@
+#ifndef TEST_H
+#define TEST_H
+
+#include <string>
+
+namespace CppTestHarness
+{
+class TestResults;
+
+class Test
+{
+public:
+	virtual ~Test();
+	void Run(TestResults& testResults);
+
+	static Test* GetListHead();
+
+protected:
+	Test(std::string testName = std::string(), 
+	     std::string filename = std::string(), 
+	     int lineNumber = 0);
+
+private:
+	virtual void RunImpl(TestResults& testResults_) = 0;
+
+	std::string const m_testName;
+	std::string const m_filename;
+	int const m_lineNumber;
+
+	Test* m_listNext;
+
+	// revoked
+	Test(Test const&);
+	Test& operator =(Test const&);
+};
+
+}
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestLauncher.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestLauncher.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestLauncher.cpp	(revision 216)
@@ -0,0 +1,39 @@
+#include "TestLauncher.h"
+
+namespace CppTestHarness
+{
+
+namespace
+{
+	TestLauncher* s_listHead;
+}
+
+TestLauncher** TestLauncher::GetHeadAddr()
+{
+	static bool initialized = false;
+	if (!initialized)
+	{
+		s_listHead = 0;
+		initialized = true;
+	}
+
+	return &s_listHead;
+}
+
+TestLauncher::TestLauncher(TestLauncher** listHead)
+	: m_next(*listHead)
+{
+	*listHead = this;
+}
+
+TestLauncher::~TestLauncher()
+{
+}
+
+TestLauncher const* TestLauncher::GetNext() const
+{
+	return m_next;
+}
+
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestLauncher.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestLauncher.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestLauncher.h	(revision 216)
@@ -0,0 +1,32 @@
+#ifndef TEST_LAUNCHER_H
+#define TEST_LAUNCHER_H
+
+namespace CppTestHarness
+{
+class TestResults;
+class TestRegistry;
+
+class TestLauncher
+{
+public:
+	virtual void Launch(TestResults& results_) const = 0;
+
+	static TestLauncher** GetHeadAddr();
+	TestLauncher const* GetNext() const;
+
+protected:
+	TestLauncher(TestLauncher** listHead);
+	virtual ~TestLauncher();
+
+private:
+	TestLauncher const* m_next;
+
+	// revoked
+	TestLauncher();
+	TestLauncher(TestLauncher const&);
+	TestLauncher& operator =(TestLauncher const&);
+};
+}
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestMacros.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestMacros.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestMacros.h	(revision 216)
@@ -0,0 +1,48 @@
+#ifndef TEST_MACROS_H
+#define TEST_MACROS_H
+
+//----------------------------
+#define TEST(Name) \
+	class Test##Name : public CppTestHarness::Test \
+	{ \
+	public: \
+		Test##Name() : Test(#Name, __FILE__, __LINE__) {} \
+	private: \
+		virtual void RunImpl(CppTestHarness::TestResults& testResults_); \
+	}; \
+	CppTestHarness::TypedTestLauncher< Test##Name > \
+		staticInitTest##Name##Creator(CppTestHarness::TestLauncher::GetHeadAddr()); \
+	\
+	void Test##Name::RunImpl(CppTestHarness::TestResults& testResults_)
+
+//----------------------------
+#define TEST_FIXTURE(Fixture, Name) \
+	class Test##Name : public CppTestHarness::Test, public Fixture \
+	{ \
+	public: \
+		Test##Name() : Test(#Name, __FILE__, __LINE__) {} \
+	private: \
+		virtual void RunImpl(CppTestHarness::TestResults& testResults_); \
+	}; \
+	CppTestHarness::TypedTestLauncher< Test##Name > \
+		staticInitTest##Name##Creator(CppTestHarness::TestLauncher::GetHeadAddr()); \
+	\
+	void Test##Name::RunImpl(CppTestHarness::TestResults& testResults_)
+
+//----------------------------
+#define TEST_FIXTURE_CTOR(Fixture, CtorParams, Name) \
+	class Test##Name : public CppTestHarness::Test, public Fixture \
+	{ \
+	public: \
+		Test##Name() : Test(#Name, __FILE__, __LINE__), Fixture CtorParams {} \
+	private: \
+		virtual void RunImpl(CppTestHarness::TestResults& testResults_); \
+	}; \
+	CppTestHarness::TypedTestLauncher< Test##Name > \
+		staticInitTest##Name##Creator(CppTestHarness::TestLauncher::GetHeadAddr()); \
+	\
+	void Test##Name::RunImpl(CppTestHarness::TestResults& testResults_)
+
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestReporter.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestReporter.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestReporter.cpp	(revision 216)
@@ -0,0 +1,15 @@
+#include "TestReporter.h"
+
+namespace CppTestHarness
+{
+
+TestReporter::TestReporter()
+{
+}
+
+TestReporter::~TestReporter()
+{
+}
+
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestReporter.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestReporter.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestReporter.h	(revision 216)
@@ -0,0 +1,24 @@
+#ifndef TEST_REPORTER_H
+#define TEST_REPORTER_H
+
+#include <string>
+
+namespace CppTestHarness
+{
+
+class TestReporter
+{
+public:
+	virtual ~TestReporter();
+
+	virtual void ReportFailure(char const* file, int line, std::string failure) = 0;
+	virtual void ReportSingleResult(const std::string& testName, bool failed) = 0;
+	virtual void ReportSummary(int testCount, int failureCount) = 0;
+
+protected:
+	TestReporter();
+};
+
+}
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestResults.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestResults.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestResults.cpp	(revision 216)
@@ -0,0 +1,30 @@
+#include "TestResults.h"
+#include "TestReporter.h"
+
+namespace CppTestHarness
+{
+
+TestResults::TestResults(TestReporter& testReporter)
+	: m_failure(false)
+	, m_testReporter(testReporter)
+{
+}
+
+void TestResults::ReportFailure(char const* file, int const line, std::string const failure)
+{
+	m_failure = true;
+	m_testReporter.ReportFailure(file, line, failure);
+}
+
+void TestResults::ReportDone(const std::string& testName)
+{
+	m_testReporter.ReportSingleResult(testName, m_failure);
+}
+
+bool TestResults::Failed() const
+{
+	return m_failure;
+}
+
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestResults.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestResults.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestResults.h	(revision 216)
@@ -0,0 +1,33 @@
+#ifndef TEST_RESULTS_H
+#define TEST_RESULTS_H
+
+#include <string>
+
+namespace CppTestHarness
+{
+
+class TestReporter;
+
+class TestResults
+{
+public:
+	explicit TestResults(TestReporter& reporter);
+
+	void ReportFailure(char const* file, int line, std::string failure);
+	void ReportDone(const std::string& testName);
+
+	bool Failed() const;
+
+private:
+	bool m_failure;
+	TestReporter& m_testReporter;
+
+	// revoked
+	TestResults(TestResults const&);
+	TestResults& operator =(TestResults const&);
+};
+
+}
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestRunner.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestRunner.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestRunner.cpp	(revision 216)
@@ -0,0 +1,56 @@
+#include "TestRunner.h"
+#include "TestLauncher.h"
+#include "TestResults.h"
+#include "Test.h"
+
+#include "PrintfTestReporter.h"
+
+namespace CppTestHarness
+{
+
+TestRunner::TestRunner()
+	: m_testLauncherListHead(TestLauncher::GetHeadAddr())
+	, m_testReporter(&m_defaultTestReporter)
+{
+}
+
+TestRunner::~TestRunner()
+{
+}
+
+void TestRunner::SetTestLauncherListHead(TestLauncher** listHead)
+{
+	m_testLauncherListHead = listHead;
+}
+
+void TestRunner::SetTestReporter(TestReporter* testReporter)
+{
+	m_testReporter = testReporter;
+}
+
+int TestRunner::RunAllTests()
+{
+	int failureCount = 0;
+
+	int testCount = 0;
+	TestLauncher const* curLauncher = *m_testLauncherListHead;
+	while (curLauncher)
+	{
+		++testCount;
+
+		TestResults result(*m_testReporter);
+		curLauncher->Launch(result);
+
+		if (result.Failed())
+			++failureCount;
+
+		curLauncher = curLauncher->GetNext();
+	}
+
+	m_testReporter->ReportSummary(testCount, failureCount);
+
+	return failureCount;
+}
+
+}
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TestRunner.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TestRunner.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TestRunner.h	(revision 216)
@@ -0,0 +1,33 @@
+#ifndef TEST_RUNNER_H
+#define TEST_RUNNER_H
+
+#include "PrintfTestReporter.h"
+
+namespace CppTestHarness
+{
+class TestLauncher;
+class TestReporter;
+
+class TestRunner
+{
+public:
+	TestRunner();
+	~TestRunner();
+
+	void SetTestReporter(TestReporter* testReporter);
+	void SetTestLauncherListHead(TestLauncher** listHead);
+
+	int RunAllTests();
+	int FailureCount() const;
+
+private:
+	TestLauncher** m_testLauncherListHead;
+
+	TestReporter* m_testReporter;
+	PrintfTestReporter m_defaultTestReporter;
+};
+
+}
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/CppTestHarness/TypedTestLauncher.h
===================================================================
--- /code/branches/ode/ode-0.9/tests/CppTestHarness/TypedTestLauncher.h	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/CppTestHarness/TypedTestLauncher.h	(revision 216)
@@ -0,0 +1,27 @@
+#ifndef TYPED_TEST_CREATOR_H
+#define TYPED_TEST_CREATOR_H
+
+#include "TestLauncher.h"
+
+namespace CppTestHarness
+{
+
+template< typename TestClass >
+class TypedTestLauncher : public TestLauncher
+{
+public:
+	TypedTestLauncher(TestLauncher** listHead)
+		: TestLauncher(listHead)
+	{
+	}
+
+	virtual void Launch(TestResults& testResults_) const 
+	{
+		TestClass().Run(testResults_);
+	}
+};
+
+}
+
+#endif
+
Index: /code/branches/ode/ode-0.9/tests/Makefile.am
===================================================================
--- /code/branches/ode/ode-0.9/tests/Makefile.am	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/Makefile.am	(revision 216)
@@ -0,0 +1,26 @@
+SUBDIRS = CppTestHarness
+
+AM_CXXFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_srcdir)/tests/CppTestHarness -I$(top_builddir)/include
+AM_CFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_srcdir)/tests/CppTestHarness -I$(top_builddir)/include
+
+
+noinst_PROGRAMS=ode_unit_test
+
+ode_unit_test_SOURCES = \
+  main.cpp \
+  colliders/box_sphere.cpp
+
+ode_unit_test_DEPENDENCIES = \
+  $(top_builddir)/ode/src/libode.a \
+  $(top_builddir)/tests/CppTestHarness/libodetest.a 
+
+ode_unit_test_LDFLAGS = \
+  -L$(top_builddir)/ode/src \
+  -L$(top_builddir)/tests/CppTestHarness \
+  @LDFLAGS@
+
+ode_unit_test_LDADD = \
+  $(top_builddir)/ode/src/libode.a \
+  $(top_builddir)/tests/CppTestHarness/libodetest.a \
+  @GL_LIBS@ @LIBS@
+
Index: /code/branches/ode/ode-0.9/tests/Makefile.in
===================================================================
--- /code/branches/ode/ode-0.9/tests/Makefile.in	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/Makefile.in	(revision 216)
@@ -0,0 +1,571 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = ode_unit_test$(EXEEXT)
+subdir = tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/ode/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_ode_unit_test_OBJECTS = main.$(OBJEXT) box_sphere.$(OBJEXT)
+ode_unit_test_OBJECTS = $(am_ode_unit_test_OBJECTS)
+ode_unit_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+	$(ode_unit_test_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)/include/ode@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+	-o $@
+SOURCES = $(ode_unit_test_SOURCES)
+DIST_SOURCES = $(ode_unit_test_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+ARCHFLAGS = @ARCHFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRAWSTUFF = @DRAWSTUFF@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+ODE_AGE = @ODE_AGE@
+ODE_CURRENT = @ODE_CURRENT@
+ODE_RELEASE = @ODE_RELEASE@
+ODE_REVISION = @ODE_REVISION@
+ODE_SONAME = @ODE_SONAME@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARED_LDFLAGS = @SHARED_LDFLAGS@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TOPDIR = @TOPDIR@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_WINDRES = @ac_ct_WINDRES@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+so_ext = @so_ext@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = CppTestHarness
+AM_CXXFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_srcdir)/tests/CppTestHarness -I$(top_builddir)/include
+AM_CFLAGS = @ARCHFLAGS@ @CXXFLAGS@ -I$(top_srcdir)/include -I$(top_srcdir)/tests/CppTestHarness -I$(top_builddir)/include
+ode_unit_test_SOURCES = \
+  main.cpp \
+  colliders/box_sphere.cpp
+
+ode_unit_test_DEPENDENCIES = \
+  $(top_builddir)/ode/src/libode.a \
+  $(top_builddir)/tests/CppTestHarness/libodetest.a 
+
+ode_unit_test_LDFLAGS = \
+  -L$(top_builddir)/ode/src \
+  -L$(top_builddir)/tests/CppTestHarness \
+  @LDFLAGS@
+
+ode_unit_test_LDADD = \
+  $(top_builddir)/ode/src/libode.a \
+  $(top_builddir)/tests/CppTestHarness/libodetest.a \
+  @GL_LIBS@ @LIBS@
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  tests/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+	-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+ode_unit_test$(EXEEXT): $(ode_unit_test_OBJECTS) $(ode_unit_test_DEPENDENCIES) 
+	@rm -f ode_unit_test$(EXEEXT)
+	$(ode_unit_test_LINK) $(ode_unit_test_OBJECTS) $(ode_unit_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/box_sphere.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+box_sphere.o: colliders/box_sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT box_sphere.o -MD -MP -MF $(DEPDIR)/box_sphere.Tpo -c -o box_sphere.o `test -f 'colliders/box_sphere.cpp' || echo '$(srcdir)/'`colliders/box_sphere.cpp
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/box_sphere.Tpo $(DEPDIR)/box_sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='colliders/box_sphere.cpp' object='box_sphere.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o box_sphere.o `test -f 'colliders/box_sphere.cpp' || echo '$(srcdir)/'`colliders/box_sphere.cpp
+
+box_sphere.obj: colliders/box_sphere.cpp
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT box_sphere.obj -MD -MP -MF $(DEPDIR)/box_sphere.Tpo -c -o box_sphere.obj `if test -f 'colliders/box_sphere.cpp'; then $(CYGPATH_W) 'colliders/box_sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/colliders/box_sphere.cpp'; fi`
+@am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/box_sphere.Tpo $(DEPDIR)/box_sphere.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='colliders/box_sphere.cpp' object='box_sphere.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o box_sphere.obj `if test -f 'colliders/box_sphere.cpp'; then $(CYGPATH_W) 'colliders/box_sphere.cpp'; else $(CYGPATH_W) '$(srcdir)/colliders/box_sphere.cpp'; fi`
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+	list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	    distdir=`$(am__cd) $(distdir) && pwd`; \
+	    top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+	    (cd $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$top_distdir" \
+	        distdir="$$distdir/$$subdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+	install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic \
+	clean-noinstPROGRAMS ctags ctags-recursive distclean \
+	distclean-compile distclean-generic distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs installdirs-am \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+	tags tags-recursive uninstall uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /code/branches/ode/ode-0.9/tests/colliders/box_sphere.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/colliders/box_sphere.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/colliders/box_sphere.cpp	(revision 216)
@@ -0,0 +1,13 @@
+#include "CppTestHarness.h"
+#include "ode/ode.h"
+
+TEST(BoxSphereIntersection)
+{
+	dGeomID box    = dCreateBox(NULL, 1.0f, 1.0f, 1.0f);
+	dGeomID sphere = dCreateSphere(NULL, 1.0f);
+
+	CHECK_EQUAL(1.0, 1.0);
+
+	dGeomDestroy(box);
+	dGeomDestroy(sphere);
+}
Index: /code/branches/ode/ode-0.9/tests/main.cpp
===================================================================
--- /code/branches/ode/ode-0.9/tests/main.cpp	(revision 216)
+++ /code/branches/ode/ode-0.9/tests/main.cpp	(revision 216)
@@ -0,0 +1,7 @@
+#include "CppTestHarness.h"
+#include "PrintfTestReporter.h"
+
+int main()
+{
+	return CppTestHarness::TestRunner().RunAllTests();
+}
Index: /code/branches/ode/ode-0.9/tools/checklist.txt
===================================================================
--- /code/branches/ode/ode-0.9/tools/checklist.txt	(revision 216)
+++ /code/branches/ode/ode-0.9/tools/checklist.txt	(revision 216)
@@ -0,0 +1,25 @@
+RELEASE CHECKLIST
+---------------------------------------------
+
+( ) Update versions at start of configure.in (AC_INIT, ODE_CURRENT, etc.)
+
+( ) Create a release branch in SVN
+
+( ) Run msw-release.bat in VS2003 command prompt
+
+( ) Run src-release.sh to create source package
+    (Must run in Linux or Cygwin w/autotools)
+
+
+
+SANITY CHECK of release package
+---------------------------------------------
+
+* binaries exist
+
+* include/ode/config.h exists
+
+* configure script exists - if not: is autotools installed?
+
+* docs have been generated in docs/
+
Index: /code/branches/ode/ode-0.9/tools/ftp_msw_script
===================================================================
--- /code/branches/ode/ode-0.9/tools/ftp_msw_script	(revision 216)
+++ /code/branches/ode/ode-0.9/tools/ftp_msw_script	(revision 216)
@@ -0,0 +1,8 @@
+anonymous
+jason379@users.sourceforge.net
+cd incoming
+bin
+prompt
+mput ode-win32-*.zip
+quit
+
Index: /code/branches/ode/ode-0.9/tools/ftp_src_script
===================================================================
--- /code/branches/ode/ode-0.9/tools/ftp_src_script	(revision 216)
+++ /code/branches/ode/ode-0.9/tools/ftp_src_script	(revision 216)
@@ -0,0 +1,7 @@
+user anonymous starkos
+cd incoming
+bin
+prompt
+mput ode-src-*.zip
+quit
+
Index: /code/branches/ode/ode-0.9/tools/msw-release.bat
===================================================================
--- /code/branches/ode/ode-0.9/tools/msw-release.bat	(revision 216)
+++ /code/branches/ode/ode-0.9/tools/msw-release.bat	(revision 216)
@@ -0,0 +1,125 @@
+@echo off
+rem ***********************************************************
+rem * ODE Windows Binary Release Script
+rem * Originally written by Jason Perkins (starkos@gmail.com)
+rem *
+rem * Prerequisites:
+rem *  Command-line svn installed on path
+rem *  Command-line zip installed on path
+rem *  Run within Visual Studio 2003 command prompt
+rem ***********************************************************
+
+rem * Check arguments
+if "%1"=="" goto show_usage
+if "%2"=="" goto show_usage
+
+
+rem ***********************************************************
+rem * Pre-build checklist
+rem ***********************************************************
+
+echo. 
+echo STARTING PREBUILD CHECKLIST, PRESS ^^C TO ABORT.
+echo.
+echo Are you running at the VS2003 command prompt?
+pause
+echo.
+echo Is the version number "%1" correct?
+pause
+echo.
+echo Does the release branch "%2" exist in SVN?
+pause
+echo.
+echo Are 'svn', '7z', and 'doxygen' on the path?
+pause
+echo.
+echo Okay, ready to build the Windows binary packages for version %1!
+pause
+
+
+rem ***********************************************************
+rem * Retrieve source code
+rem ***********************************************************
+
+echo.
+echo RETRIEVING SOURCE CODE FROM REPOSITORY...
+echo.
+
+svn export https://opende.svn.sourceforge.net/svnroot/opende/branches/%2 ode-%1
+
+
+
+rem ***********************************************************
+rem * Prepare source code
+rem ***********************************************************
+
+echo.
+echo PREPARING SOURCE CODE FROM REPOSITORY...
+echo.
+
+cd ode-%1
+copy build\config-default.h include\ode\config.h
+
+cd ode\doc
+doxygen
+
+cd ..\..\..
+
+
+rem ***********************************************************
+rem * Build the binaries
+rem ***********************************************************
+
+echo.
+echo BUILDING RELEASE BINARIES...
+echo.
+
+cd ode-%1\build\vs2003
+devenv.exe ode.sln /build DebugLib /project ode
+devenv.exe ode.sln /build DebugDLL /project ode
+devenv.exe ode.sln /build ReleaseLib /project ode
+devenv.exe ode.sln /build ReleaseDLL /project ode
+
+
+rem ***********************************************************
+rem * Package things up
+rem ***********************************************************
+
+cd ..\..
+move lib\ReleaseDLL\ode.lib lib\ReleaseDLL\ode-imports.lib
+
+cd ..
+7z a -tzip ode-win32-%1.zip ode-%1\*.txt ode-%1\include\ode\*.h ode-%1\lib\* ode-%1\docs\*
+
+
+rem ***********************************************************
+rem * Clean up
+rem ***********************************************************
+
+echo.
+echo CLEANING UP...
+echo.
+
+rmdir /s /q ode-%1
+
+
+rem ***********************************************************
+rem * Upload to SF.net
+rem ***********************************************************
+
+echo.
+echo Ready to upload package to SourceForce, press ^^C to abort.
+pause
+ftp -s:ftp_msw_script upload.sourceforge.net
+goto done
+
+
+rem ***********************************************************
+rem * Error messages
+rem ***********************************************************
+
+:show_usage
+echo Usage: msw_release.bat version_number branch_name
+goto done
+
+:done
Index: /code/branches/ode/ode-0.9/tools/src-release.sh
===================================================================
--- /code/branches/ode/ode-0.9/tools/src-release.sh	(revision 216)
+++ /code/branches/ode/ode-0.9/tools/src-release.sh	(revision 216)
@@ -0,0 +1,104 @@
+#!/bin/sh
+###################################################################
+# ODE Source Code Release Script
+# Originally written by Jason Perkins (starkos@gmail.com)
+#
+# Prerequisites:
+#  svn, zip
+###################################################################
+
+# Check arguments
+if [ $# -ne 2 ]; then
+  echo 1>&2 "Usage: $0 version_number branch_name"
+  exit 1
+fi
+
+
+###################################################################
+# Pre-build checklist
+###################################################################
+
+echo "" 
+echo "STARTING PREBUILD CHECKLIST, PRESS ^^C TO ABORT."
+echo ""
+echo "Is the version number '$1' correct?"
+read line
+echo ""
+echo "Have you created a release branch named '$2' in SVN?"
+read line
+echo ""
+echo "Have you run all of the tests?"
+read line
+echo ""
+echo "Is the Changelog up to date?"
+read line
+echo ""
+echo "Okay, ready to build the source code package for version $1!"
+read line
+
+
+###################################################################
+# Retrieve source code
+###################################################################
+
+echo ""
+echo "RETRIEVING SOURCE CODE FROM REPOSITORY..."
+echo ""
+f
+svn export https://opende.svn.sourceforge.net/svnroot/opende/branches/$2 ode-$1
+
+
+###################################################################
+# Prepare source code
+###################################################################
+
+echo ""
+echo "PREPARING SOURCE TREE..."
+echo ""
+
+cd ode-$1
+chmod 755 autogen.sh
+./autogen.sh
+rm -rf autom4te.cache
+
+cp build/config-default.h include/ode/config.h
+
+cd ode/doc
+doxygen
+
+cd ../../..
+
+
+###################################################################
+# Package source code
+###################################################################
+
+echo ""
+echo "PACKAGING SOURCE CODE..."
+echo ""
+
+zip -r9 ode-src-$1.zip ode-$1/*
+
+
+###################################################################
+# Clean up
+###################################################################
+
+echo ""
+echo "CLEANING UP..."
+echo ""
+
+rm -rf ode-$1
+
+
+#####################################################################
+# Send the files to SourceForge
+#####################################################################
+
+echo ""
+echo "Upload packages to SourceForge?"
+read line
+if [ $line = "y" ]; then
+	echo "Uploading to SourceForge..."
+	ftp -n upload.sourceforge.net < ftp_src_script
+fi
